1 |
|
2 | require('./../utils/polyfills')
|
3 |
|
4 | const isFactory = require('./../utils/object').isFactory
|
5 | const typedFactory = require('./typed')
|
6 | const emitter = require('./../utils/emitter')
|
7 |
|
8 | const importFactory = require('./function/import')
|
9 | const configFactory = require('./function/config')
|
10 |
|
11 | /**
|
12 | * Math.js core. Creates a new, empty math.js instance
|
13 | * @param {Object} [options] Available options:
|
14 | * {number} epsilon
|
15 | * Minimum relative difference between two
|
16 | * compared values, used by all comparison functions.
|
17 | * {string} matrix
|
18 | * A string 'Matrix' (default) or 'Array'.
|
19 | * {string} number
|
20 | * A string 'number' (default), 'BigNumber', or 'Fraction'
|
21 | * {number} precision
|
22 | * The number of significant digits for BigNumbers.
|
23 | * Not applicable for Numbers.
|
24 | * {boolean} predictable
|
25 | * Predictable output type of functions. When true,
|
26 | * output type depends only on the input types. When
|
27 | * false (default), output type can vary depending
|
28 | * on input values. For example `math.sqrt(-4)`
|
29 | * returns `complex('2i')` when predictable is false, and
|
30 | * returns `NaN` when true.
|
31 | * {string} randomSeed
|
32 | * Random seed for seeded pseudo random number generator.
|
33 | * Set to null to randomly seed.
|
34 | * @returns {Object} Returns a bare-bone math.js instance containing
|
35 | * functions:
|
36 | * - `import` to add new functions
|
37 | * - `config` to change configuration
|
38 | * - `on`, `off`, `once`, `emit` for events
|
39 | */
|
40 | exports.create = function create (options) {
|
41 | // simple test for ES5 support
|
42 | if (typeof Object.create !== 'function') {
|
43 | throw new Error('ES5 not supported by this JavaScript engine. ' +
|
44 | 'Please load the es5-shim and es5-sham library for compatibility.')
|
45 | }
|
46 |
|
47 | // cached factories and instances
|
48 | const factories = []
|
49 | const instances = []
|
50 |
|
51 | // create a namespace for the mathjs instance, and attach emitter functions
|
52 | const math = emitter.mixin({})
|
53 | math.type = {}
|
54 | math.expression = {
|
55 | transform: {},
|
56 | mathWithTransform: {}
|
57 | }
|
58 |
|
59 | // create a new typed instance
|
60 | math.typed = typedFactory.create(math.type)
|
61 |
|
62 | // create configuration options. These are private
|
63 | const _config = {
|
64 | // minimum relative difference between two compared values,
|
65 | // used by all comparison functions
|
66 | epsilon: 1e-12,
|
67 |
|
68 | // type of default matrix output. Choose 'matrix' (default) or 'array'
|
69 | matrix: 'Matrix',
|
70 |
|
71 | // type of default number output. Choose 'number' (default) 'BigNumber', or 'Fraction
|
72 | number: 'number',
|
73 |
|
74 | // number of significant digits in BigNumbers
|
75 | precision: 64,
|
76 |
|
77 | // predictable output type of functions. When true, output type depends only
|
78 | // on the input types. When false (default), output type can vary depending
|
79 | // on input values. For example `math.sqrt(-4)` returns `complex('2i')` when
|
80 | // predictable is false, and returns `NaN` when true.
|
81 | predictable: false,
|
82 |
|
83 | // random seed for seeded pseudo random number generation
|
84 | // null = randomly seed
|
85 | randomSeed: null
|
86 | }
|
87 |
|
88 | /**
|
89 | * Load a function or data type from a factory.
|
90 | * If the function or data type already exists, the existing instance is
|
91 | * returned.
|
92 | * @param {{type: string, name: string, factory: Function}} factory
|
93 | * @returns {*}
|
94 | */
|
95 | function load (factory) {
|
96 | if (!isFactory(factory)) {
|
97 | throw new Error('Factory object with properties `type`, `name`, and `factory` expected')
|
98 | }
|
99 |
|
100 | const index = factories.indexOf(factory)
|
101 | let instance
|
102 | if (index === -1) {
|
103 | // doesn't yet exist
|
104 | if (factory.math === true) {
|
105 | // pass with math namespace
|
106 | instance = factory.factory(math.type, _config, load, math.typed, math)
|
107 | } else {
|
108 | instance = factory.factory(math.type, _config, load, math.typed)
|
109 | }
|
110 |
|
111 | // append to the cache
|
112 | factories.push(factory)
|
113 | instances.push(instance)
|
114 | } else {
|
115 | // already existing function, return the cached instance
|
116 | instance = instances[index]
|
117 | }
|
118 |
|
119 | return instance
|
120 | }
|
121 |
|
122 | // load the import and config functions
|
123 | math['import'] = load(importFactory)
|
124 | math['config'] = load(configFactory)
|
125 | math.expression.mathWithTransform['config'] = math['config']
|
126 |
|
127 | // apply options
|
128 | if (options) {
|
129 | math.config(options)
|
130 | }
|
131 |
|
132 | return math
|
133 | }
|