UNPKG

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