UNPKG

7.73 kBJavaScriptView Raw
1function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
3import './../utils/polyfills.js';
4import { deepFlatten, isLegacyFactory, values } from '../utils/object.js';
5import * as emitter from './../utils/emitter.js';
6import { importFactory } from './function/import.js';
7import { configFactory } from './function/config.js';
8import { factory, isFactory } from '../utils/factory.js';
9import { isAccessorNode, isArray, isArrayNode, isAssignmentNode, isBigNumber, isBlockNode, isBoolean, isChain, isCollection, isComplex, isConditionalNode, isConstantNode, isDate, isDenseMatrix, isFraction, isFunction, isFunctionAssignmentNode, isFunctionNode, isHelp, isIndex, isIndexNode, isMatrix, isNode, isNull, isNumber, isObject, isObjectNode, isOperatorNode, isParenthesisNode, isRange, isRangeNode, isRegExp, isResultSet, isSparseMatrix, isString, isSymbolNode, isUndefined, isUnit } from '../utils/is.js';
10import { ArgumentsError } from '../error/ArgumentsError.js';
11import { DimensionError } from '../error/DimensionError.js';
12import { IndexError } from '../error/IndexError.js';
13import { DEFAULT_CONFIG } from './config.js';
14/**
15 * Create a mathjs instance from given factory functions and optionally config
16 *
17 * Usage:
18 *
19 * const mathjs1 = create({ createAdd, createMultiply, ...})
20 * const config = { number: 'BigNumber' }
21 * const mathjs2 = create(all, config)
22 *
23 * @param {Object} [factories] An object with factory functions
24 * The object can contain nested objects,
25 * all nested objects will be flattened.
26 * @param {Object} [config] Available options:
27 * {number} epsilon
28 * Minimum relative difference between two
29 * compared values, used by all comparison functions.
30 * {string} matrix
31 * A string 'Matrix' (default) or 'Array'.
32 * {string} number
33 * A string 'number' (default), 'BigNumber', or 'Fraction'
34 * {number} precision
35 * The number of significant digits for BigNumbers.
36 * Not applicable for Numbers.
37 * {boolean} predictable
38 * Predictable output type of functions. When true,
39 * output type depends only on the input types. When
40 * false (default), output type can vary depending
41 * on input values. For example `math.sqrt(-4)`
42 * returns `complex('2i')` when predictable is false, and
43 * returns `NaN` when true.
44 * {string} randomSeed
45 * Random seed for seeded pseudo random number generator.
46 * Set to null to randomly seed.
47 * @returns {Object} Returns a bare-bone math.js instance containing
48 * functions:
49 * - `import` to add new functions
50 * - `config` to change configuration
51 * - `on`, `off`, `once`, `emit` for events
52 */
53
54export function create(factories, config) {
55 var configInternal = _extends({}, DEFAULT_CONFIG, config); // simple test for ES5 support
56
57
58 if (typeof Object.create !== 'function') {
59 throw new Error('ES5 not supported by this JavaScript engine. ' + 'Please load the es5-shim and es5-sham library for compatibility.');
60 } // create the mathjs instance
61
62
63 var math = emitter.mixin({
64 // only here for backward compatibility for legacy factory functions
65 isNumber,
66 isComplex,
67 isBigNumber,
68 isFraction,
69 isUnit,
70 isString,
71 isArray,
72 isMatrix,
73 isCollection,
74 isDenseMatrix,
75 isSparseMatrix,
76 isRange,
77 isIndex,
78 isBoolean,
79 isResultSet,
80 isHelp,
81 isFunction,
82 isDate,
83 isRegExp,
84 isObject,
85 isNull,
86 isUndefined,
87 isAccessorNode,
88 isArrayNode,
89 isAssignmentNode,
90 isBlockNode,
91 isConditionalNode,
92 isConstantNode,
93 isFunctionAssignmentNode,
94 isFunctionNode,
95 isIndexNode,
96 isNode,
97 isObjectNode,
98 isOperatorNode,
99 isParenthesisNode,
100 isRangeNode,
101 isSymbolNode,
102 isChain
103 }); // load config function and apply provided config
104
105 math.config = configFactory(configInternal, math.emit);
106 math.expression = {
107 transform: {},
108 mathWithTransform: {
109 config: math.config
110 }
111 }; // cached factories and instances used by function load
112
113 var legacyFactories = [];
114 var legacyInstances = [];
115 /**
116 * Load a function or data type from a factory.
117 * If the function or data type already exists, the existing instance is
118 * returned.
119 * @param {Function} factory
120 * @returns {*}
121 */
122
123 function load(factory) {
124 if (isFactory(factory)) {
125 return factory(math);
126 }
127
128 var firstProperty = factory[Object.keys(factory)[0]];
129
130 if (isFactory(firstProperty)) {
131 return firstProperty(math);
132 }
133
134 if (!isLegacyFactory(factory)) {
135 console.warn('Factory object with properties `type`, `name`, and `factory` expected', factory);
136 throw new Error('Factory object with properties `type`, `name`, and `factory` expected');
137 }
138
139 var index = legacyFactories.indexOf(factory);
140 var instance;
141
142 if (index === -1) {
143 // doesn't yet exist
144 if (factory.math === true) {
145 // pass with math namespace
146 instance = factory.factory(math.type, configInternal, load, math.typed, math);
147 } else {
148 instance = factory.factory(math.type, configInternal, load, math.typed);
149 } // append to the cache
150
151
152 legacyFactories.push(factory);
153 legacyInstances.push(instance);
154 } else {
155 // already existing function, return the cached instance
156 instance = legacyInstances[index];
157 }
158
159 return instance;
160 }
161
162 var importedFactories = {}; // load the import function
163
164 function lazyTyped() {
165 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
166 args[_key] = arguments[_key];
167 }
168
169 return math.typed.apply(math.typed, args);
170 }
171
172 var internalImport = importFactory(lazyTyped, load, math, importedFactories);
173 math.import = internalImport; // listen for changes in config, import all functions again when changed
174 // TODO: move this listener into the import function?
175
176 math.on('config', () => {
177 values(importedFactories).forEach(factory => {
178 if (factory && factory.meta && factory.meta.recreateOnConfigChange) {
179 // FIXME: only re-create when the current instance is the same as was initially created
180 // FIXME: delete the functions/constants before importing them again?
181 internalImport(factory, {
182 override: true
183 });
184 }
185 });
186 }); // the create function exposed on the mathjs instance is bound to
187 // the factory functions passed before
188
189 math.create = create.bind(null, factories); // export factory function
190
191 math.factory = factory; // import the factory functions like createAdd as an array instead of object,
192 // else they will get a different naming (`createAdd` instead of `add`).
193
194 math.import(values(deepFlatten(factories)));
195 math.ArgumentsError = ArgumentsError;
196 math.DimensionError = DimensionError;
197 math.IndexError = IndexError;
198 return math;
199}
\No newline at end of file