UNPKG

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