nerdamer 1.1.9 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Algebra.js +2061 -1850
- package/Calculus.js +761 -680
- package/Extra.js +148 -117
- package/README.md +30 -1
- package/Solve.js +476 -332
- package/all.min.js +1 -0
- package/gulpfile.js +16 -0
- package/index.d.ts +150 -13
- package/nerdamer.core.js +2166 -1901
- package/package.json +57 -52
- package/spec/LaTeX.spec.js +14 -44
- package/spec/TeXConvert.spec.js +3 -2
- package/spec/algebra.spec.js +181 -732
- package/spec/calculus.spec.js +160 -673
- package/spec/core.spec.js +35 -8
- package/spec/extra.spec.js +39 -171
- package/spec/solve.spec.js +89 -305
package/Extra.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
/* global module */
|
|
10
10
|
|
|
11
|
-
if
|
|
11
|
+
if((typeof module) !== 'undefined') {
|
|
12
12
|
var nerdamer = require('./nerdamer.core.js');
|
|
13
13
|
require('./Calculus');
|
|
14
14
|
require('./Algebra');
|
|
@@ -34,13 +34,13 @@ if ((typeof module) !== 'undefined') {
|
|
|
34
34
|
|
|
35
35
|
Symbol.prototype.findFunction = function (fname) {
|
|
36
36
|
//this is what we're looking for
|
|
37
|
-
if
|
|
37
|
+
if(this.group === FN && this.fname === fname)
|
|
38
38
|
return this.clone();
|
|
39
39
|
var found;
|
|
40
|
-
if
|
|
41
|
-
for
|
|
40
|
+
if(this.symbols)
|
|
41
|
+
for(var x in this.symbols) {
|
|
42
42
|
found = this.symbols[x].findFunction(fname);
|
|
43
|
-
if
|
|
43
|
+
if(found)
|
|
44
44
|
break;
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -48,14 +48,14 @@ if ((typeof module) !== 'undefined') {
|
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
var __ = core.Extra = {
|
|
51
|
-
version: '1.4.
|
|
51
|
+
version: '1.4.2',
|
|
52
52
|
//http://integral-table.com/downloads/LaplaceTable.pdf
|
|
53
53
|
//Laplace assumes all coefficients to be positive
|
|
54
54
|
LaPlace: {
|
|
55
55
|
//Using: integral_0^oo f(t)*e^(-s*t) dt
|
|
56
56
|
transform: function (symbol, t, s) {
|
|
57
57
|
symbol = symbol.clone();
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
t = t.toString();
|
|
60
60
|
//First try a lookup for a speed boost
|
|
61
61
|
symbol = Symbol.unwrapSQRT(symbol, true);
|
|
@@ -65,33 +65,33 @@ if ((typeof module) !== 'undefined') {
|
|
|
65
65
|
|
|
66
66
|
symbol = _.divide(symbol, coeff.clone());
|
|
67
67
|
|
|
68
|
-
if
|
|
68
|
+
if(symbol.isConstant() || !symbol.contains(t, true)) {
|
|
69
69
|
retval = _.parse(format('({0})/({1})', symbol, s));
|
|
70
70
|
}
|
|
71
|
-
else if
|
|
71
|
+
else if(g === S && core.Utils.isInt(symbol.power)) {
|
|
72
72
|
var n = String(symbol.power);
|
|
73
73
|
retval = _.parse(format('factorial({0})/({1})^({0}+1)', n, s));
|
|
74
74
|
}
|
|
75
|
-
else if
|
|
75
|
+
else if(symbol.group === S && symbol.power.equals(1 / 2)) {
|
|
76
76
|
retval = _.parse(format('sqrt(pi)/(2*({0})^(3/2))', s));
|
|
77
77
|
}
|
|
78
|
-
else if
|
|
78
|
+
else if(symbol.isComposite()) {
|
|
79
79
|
retval = new Symbol(0);
|
|
80
80
|
symbol.each(function (x) {
|
|
81
81
|
retval = _.add(retval, __.LaPlace.transform(x, t, s));
|
|
82
82
|
}, true);
|
|
83
83
|
}
|
|
84
|
-
else if
|
|
84
|
+
else if(symbol.isE() && (symbol.power.group === S || symbol.power.group === CB)) {
|
|
85
85
|
var a = symbol.power.stripVar(t);
|
|
86
86
|
retval = _.parse(format('1/(({1})-({0}))', a, s));
|
|
87
87
|
}
|
|
88
88
|
else {
|
|
89
89
|
var fns = ['sin', 'cos', 'sinh', 'cosh'];
|
|
90
90
|
//support for symbols in fns with arguments in the form a*t or n*t where a = symbolic and n = Number
|
|
91
|
-
if
|
|
91
|
+
if(symbol.group === FN && fns.indexOf(symbol.fname) !== -1 && (symbol.args[0].group === S || symbol.args[0].group === CB)) {
|
|
92
92
|
var a = symbol.args[0].stripVar(t);
|
|
93
93
|
|
|
94
|
-
switch
|
|
94
|
+
switch(symbol.fname) {
|
|
95
95
|
case 'sin':
|
|
96
96
|
retval = _.parse(format('({0})/(({1})^2+({0})^2)', a, s));
|
|
97
97
|
break;
|
|
@@ -112,7 +112,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
112
112
|
//we need at least the Laplace integration depth
|
|
113
113
|
var depth_is_lower = core.Settings.integration_depth < core.Settings.Laplace_integration_depth;
|
|
114
114
|
|
|
115
|
-
if
|
|
115
|
+
if(depth_is_lower) {
|
|
116
116
|
var integration_depth = core.Settings.integration_depth; //save the depth
|
|
117
117
|
core.Settings.integration_depth = core.Settings.Laplace_integration_depth; //transforms need a little more room
|
|
118
118
|
}
|
|
@@ -122,7 +122,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
122
122
|
var sym = symbol.sub(t, u);
|
|
123
123
|
var integration_expr = _.parse('e^(-' + s + '*' + u + ')*' + sym);
|
|
124
124
|
retval = core.Calculus.integrate(integration_expr, u);
|
|
125
|
-
if
|
|
125
|
+
if(retval.hasIntegral())
|
|
126
126
|
return _.symfunction('laplace', arguments);
|
|
127
127
|
// _.error('Unable to compute transform');
|
|
128
128
|
retval = retval.sub(t, 0);
|
|
@@ -134,7 +134,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
134
134
|
return _.parse(retval);
|
|
135
135
|
}, true);
|
|
136
136
|
|
|
137
|
-
if
|
|
137
|
+
if(depth_is_lower)//put the integration depth as it was
|
|
138
138
|
core.Settings.integration_depth = integration_depth;
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -146,10 +146,11 @@ if ((typeof module) !== 'undefined') {
|
|
|
146
146
|
var input_symbol = symbol.clone();
|
|
147
147
|
return core.Utils.block('POSITIVE_MULTIPLIERS', function () {
|
|
148
148
|
//expand and get partial fractions
|
|
149
|
-
if(symbol.group === CB)
|
|
149
|
+
if(symbol.group === CB) {
|
|
150
150
|
symbol = core.Algebra.PartFrac.partfrac(_.expand(symbol), s_);
|
|
151
|
+
}
|
|
151
152
|
|
|
152
|
-
if
|
|
153
|
+
if(symbol.group === S || symbol.group === CB || symbol.isComposite()) {
|
|
153
154
|
var finalize = function () {
|
|
154
155
|
//put back the numerator
|
|
155
156
|
retval = _.multiply(retval, num);
|
|
@@ -164,18 +165,19 @@ if ((typeof module) !== 'undefined') {
|
|
|
164
165
|
//get the numerator and denominator
|
|
165
166
|
num = symbol.getNum();
|
|
166
167
|
den = symbol.getDenom().toUnitMultiplier();
|
|
167
|
-
|
|
168
|
+
|
|
168
169
|
//TODO: Make it so factor doesn't destroy pi
|
|
169
170
|
//num = core.Algebra.Factor.factor(symbol.getNum());
|
|
170
171
|
//den = core.Algebra.Factor.factor(symbol.getDenom().invert(null, true));
|
|
171
172
|
|
|
172
|
-
if
|
|
173
|
+
if(den.group === CP) {
|
|
173
174
|
den_p = den.power.clone();
|
|
174
175
|
den.toLinear();
|
|
175
176
|
}
|
|
176
|
-
else
|
|
177
|
+
else {
|
|
177
178
|
den_p = new core.Frac(1);
|
|
178
|
-
|
|
179
|
+
}
|
|
180
|
+
|
|
179
181
|
//convert s to a string
|
|
180
182
|
s = s_.toString();
|
|
181
183
|
//split up the denominator if in the form ax+b
|
|
@@ -185,7 +187,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
185
187
|
num.multiplier = num.multiplier.multiply(m);
|
|
186
188
|
//store the parts in variables for easy recognition
|
|
187
189
|
//check if in the form t^n where n = integer
|
|
188
|
-
if
|
|
190
|
+
if((den.group === S || den.group === CB) && f.x.value === s && f.b.equals(0) && core.Utils.isInt(f.x.power)) {
|
|
189
191
|
var fact, p;
|
|
190
192
|
p = f.x.power - 1;
|
|
191
193
|
fact = core.Math2.factorial(p);
|
|
@@ -194,59 +196,76 @@ if ((typeof module) !== 'undefined') {
|
|
|
194
196
|
//wrap it up
|
|
195
197
|
finalize();
|
|
196
198
|
}
|
|
197
|
-
else if
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
else if(den.group === CP && den_p.equals(1)) {
|
|
200
|
+
if(f.x.group === core.groups.PL && core.Algebra.degree(den).equals(2)) {
|
|
201
|
+
// Possibly in the form 1/(s^2+2*s+1)
|
|
202
|
+
// Try factoring to get it in a more familiar form{
|
|
203
|
+
// Apply inverse of F(s-a)
|
|
204
|
+
var completed = core.Algebra.sqComplete(den, s);
|
|
205
|
+
var u = core.Utils.getU(den);
|
|
206
|
+
// Get a for the function above
|
|
207
|
+
var a = core.Utils.decompose_fn(completed.a, s, true).b;
|
|
208
|
+
var tf = __.LaPlace.inverse(_.parse(`1/((${u})^2+(${completed.c}))`), u, t);
|
|
209
|
+
retval = _.multiply(tf, _.parse(`(${m})*e^(-(${a})*(${t}))`));
|
|
204
210
|
}
|
|
205
211
|
else {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
});
|
|
221
|
-
num = new_num;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
//we need more information about the denominator to decide
|
|
225
|
-
var f2 = core.Utils.decompose_fn(num, s, true);
|
|
226
|
-
var fn1, fn2, a_has_sin, b_has_cos, a_has_cos, b_has_sin;
|
|
227
|
-
fn1 = f2.a;
|
|
228
|
-
fn2 = f2.b;
|
|
229
|
-
a_has_sin = fn1.containsFunction('sin');
|
|
230
|
-
a_has_cos = fn1.containsFunction('cos');
|
|
231
|
-
b_has_cos = fn2.containsFunction('cos');
|
|
232
|
-
b_has_sin = fn2.containsFunction('sin');
|
|
233
|
-
if (f2.x.value === s && f2.x.isLinear() && !((a_has_sin && b_has_cos) || (a_has_cos || b_has_sin))) {
|
|
234
|
-
retval = _.parse(format('(({1})*cos((sqrt(({2})*({3}))*({0}))/({2})))/({2})', t, f2.a, f.a, f.b));
|
|
212
|
+
// a/(b*s-c) -> ae^(-bt)
|
|
213
|
+
if(f.x.isLinear() && !num.contains(s)) {
|
|
214
|
+
t = _.divide(t, f.a.clone());
|
|
215
|
+
|
|
216
|
+
// Don't add factorial of one or zero
|
|
217
|
+
var p = den_p - 1;
|
|
218
|
+
var fact = p === 0 || p === 1 ? '1' : `(${den_p}-1)!`
|
|
219
|
+
retval = _.parse(format('(({0})^({3}-1)*e^(-(({2})*({0}))/({1})))/(({4})*({1})^({3}))', t, f.a, f.b, den_p, fact));
|
|
220
|
+
//wrap it up
|
|
221
|
+
finalize();
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
if(f.x.group === S && f.x.power.equals(2)) {
|
|
225
|
+
if(!num.contains(s)) {
|
|
226
|
+
retval = _.parse(format('(({1})*sin((sqrt(({2})*({3}))*({0}))/({2})))/sqrt(({2})*({3}))', t, num, f.a, f.b));
|
|
235
227
|
}
|
|
228
|
+
// a*s/(b*s^2+c^2)
|
|
236
229
|
else {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
230
|
+
var a = new Symbol(1);
|
|
231
|
+
if(num.group === CB) {
|
|
232
|
+
var new_num = new Symbol(1);
|
|
233
|
+
num.each(function (x) {
|
|
234
|
+
if(x.contains(s))
|
|
235
|
+
new_num = _.multiply(new_num, x);
|
|
236
|
+
else
|
|
237
|
+
a = _.multiply(a, x);
|
|
238
|
+
});
|
|
239
|
+
num = new_num;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
//we need more information about the denominator to decide
|
|
243
|
+
var f2 = core.Utils.decompose_fn(num, s, true);
|
|
244
|
+
var fn1, fn2, a_has_sin, b_has_cos, a_has_cos, b_has_sin;
|
|
245
|
+
fn1 = f2.a;
|
|
246
|
+
fn2 = f2.b;
|
|
247
|
+
a_has_sin = fn1.containsFunction('sin');
|
|
248
|
+
a_has_cos = fn1.containsFunction('cos');
|
|
249
|
+
b_has_cos = fn2.containsFunction('cos');
|
|
250
|
+
b_has_sin = fn2.containsFunction('sin');
|
|
251
|
+
if(f2.x.value === s && f2.x.isLinear() && !((a_has_sin && b_has_cos) || (a_has_cos || b_has_sin))) {
|
|
252
|
+
retval = _.parse(format('(({1})*cos((sqrt(({2})*({3}))*({0}))/({2})))/({2})', t, f2.a, f.a, f.b));
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
if(a_has_sin && b_has_cos) {
|
|
256
|
+
var sin, cos;
|
|
257
|
+
sin = fn1.findFunction('sin');
|
|
258
|
+
cos = fn2.findFunction('cos');
|
|
259
|
+
//who has the s?
|
|
260
|
+
if(sin.args[0].equals(cos.args[0]) && !sin.args[0].contains(s)) {
|
|
261
|
+
var b, c, d, e;
|
|
262
|
+
b = _.divide(fn2, cos.toUnitMultiplier()).toString();
|
|
263
|
+
c = sin.args[0].toString();
|
|
264
|
+
d = f.b;
|
|
265
|
+
e = _.divide(fn1, sin.toUnitMultiplier());
|
|
266
|
+
exp = '(({1})*({2})*cos({3})*sin(sqrt({4})*({0})))/sqrt({4})+({1})*sin({3})*({5})*cos(sqrt({4})*({0}))';
|
|
267
|
+
retval = _.parse(format(exp, t, a, b, c, d, e));
|
|
268
|
+
}
|
|
250
269
|
}
|
|
251
270
|
}
|
|
252
271
|
}
|
|
@@ -254,21 +273,21 @@ if ((typeof module) !== 'undefined') {
|
|
|
254
273
|
}
|
|
255
274
|
}
|
|
256
275
|
}
|
|
257
|
-
else if
|
|
276
|
+
else if(f.x.power.num && f.x.power.num.equals(3) && f.x.power.den.equals(2) && num.contains('sqrt(pi)') && !num.contains(s) && num.isLinear()) {
|
|
258
277
|
var b = _.divide(num.clone(), _.parse('sqrt(pi)'));
|
|
259
278
|
retval = _.parse(format('(2*({2})*sqrt({0}))/({1})', t, f.a, b, num));
|
|
260
279
|
}
|
|
261
|
-
else if
|
|
280
|
+
else if(den_p.equals(2) && f.x.power.equals(2)) {
|
|
262
281
|
var a, d, exp;
|
|
263
|
-
if
|
|
282
|
+
if(!num.contains(s)) {
|
|
264
283
|
a = _.divide(num, new Symbol(2));
|
|
265
284
|
exp = '(({1})*sin((sqrt(({2})*({3}))*({0}))/({2})))/(({3})*sqrt(({2})*({3})))-(({1})*({0})*cos((sqrt(({2})*({3}))*({0}))/({2})))/(({2})*({3}))';
|
|
266
285
|
retval = _.parse(format(exp, t, a, f.a, f.b));
|
|
267
286
|
}
|
|
268
287
|
else {
|
|
269
|
-
//
|
|
288
|
+
// Decompose the numerator to check value of s
|
|
270
289
|
f2 = core.Utils.decompose_fn(_.expand(num.clone()), s, true);
|
|
271
|
-
if
|
|
290
|
+
if(f2.x.isComposite()) {
|
|
272
291
|
var s_terms = [];
|
|
273
292
|
//first collect the factors e.g. (a)(bx)(cx^2+d)
|
|
274
293
|
var symbols = num.collectSymbols(function (x) {
|
|
@@ -285,20 +304,20 @@ if ((typeof module) !== 'undefined') {
|
|
|
285
304
|
return p2 - p1;
|
|
286
305
|
});
|
|
287
306
|
a = new Symbol(-1);
|
|
288
|
-
//
|
|
289
|
-
for
|
|
307
|
+
// Grab only the ones which have s
|
|
308
|
+
for(var i = 0; i < symbols.length; i++) {
|
|
290
309
|
var fc = symbols[i];
|
|
291
|
-
if
|
|
310
|
+
if(fc.x.value === s)
|
|
292
311
|
s_terms.push(fc);
|
|
293
312
|
else
|
|
294
313
|
a = _.multiply(a, fc.symbol);
|
|
295
314
|
}
|
|
296
|
-
//
|
|
297
|
-
//1. since the numerator was factored above then each s_term has a unique power
|
|
298
|
-
//2. because the terms are sorted by descending powers then the first item
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
if
|
|
315
|
+
// The following 2 assumptions are made
|
|
316
|
+
// 1. since the numerator was factored above then each s_term has a unique power
|
|
317
|
+
// 2. because the terms are sorted by descending powers then the first item
|
|
318
|
+
// has the highest power
|
|
319
|
+
// We can now check for the next type s(s^2-a^2)/(s^2+a^2)^2
|
|
320
|
+
if(s_terms[0].x.power.equals(2) && s_terms[1].x.power.equals(1) && s_terms[1].b.equals(0) && !s_terms[0].b.equals(0)) {
|
|
302
321
|
b = s_terms[0].a.negate();
|
|
303
322
|
exp = '-(({1})*({2})*({5})*({0})*sin((sqrt(({4})*({5}))*({0}))/({4})))/' +
|
|
304
323
|
'(2*({4})^2*sqrt(({4})*({5})))-(({1})*({3})*({0})*sin((sqrt(({4})*({5}))*({0}))/({4})))' +
|
|
@@ -307,13 +326,13 @@ if ((typeof module) !== 'undefined') {
|
|
|
307
326
|
}
|
|
308
327
|
}
|
|
309
328
|
else {
|
|
310
|
-
if
|
|
329
|
+
if(f2.x.isLinear()) {
|
|
311
330
|
a = _.divide(f2.a, new Symbol(2));
|
|
312
331
|
exp = '(({1})*({0})*sin((sqrt(({2})*({3}))*({0}))/({2})))/(({2})*sqrt(({2})*({3})))';
|
|
313
332
|
retval = _.parse(format(exp, t, a, f.a, f.b));
|
|
314
333
|
}
|
|
315
|
-
else if
|
|
316
|
-
if
|
|
334
|
+
else if(f2.x.power.equals(2)) {
|
|
335
|
+
if(f2.b.equals(0)) {
|
|
317
336
|
a = _.divide(f2.a, new Symbol(2));
|
|
318
337
|
exp = '(({1})*sin((sqrt(({2})*({3}))*({0}))/({2})))/(({2})*sqrt(({2})*({3})))+(({1})*({0})*cos((sqrt(({2})*({3}))*({0}))/({2})))/({2})^2';
|
|
319
338
|
retval = _.parse(format(exp, t, a, f.a, f.b));
|
|
@@ -331,16 +350,23 @@ if ((typeof module) !== 'undefined') {
|
|
|
331
350
|
}
|
|
332
351
|
}
|
|
333
352
|
else if(symbol.isComposite()) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
353
|
+
// 1/(s+1)^2
|
|
354
|
+
if(den_p.equals(2) && f.x.group === S) {
|
|
355
|
+
retval = _.parse(`(${m})*(${t})*e^(-(${f.b})*(${t}))`);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
retval = new Symbol(0);
|
|
359
|
+
|
|
360
|
+
symbol.each(function (x) {
|
|
361
|
+
retval = _.add(retval, __.LaPlace.inverse(x, s_, t));
|
|
362
|
+
}, true);
|
|
363
|
+
}
|
|
339
364
|
}
|
|
340
365
|
}
|
|
341
366
|
|
|
342
|
-
if
|
|
367
|
+
if(!retval) {
|
|
343
368
|
retval = _.symfunction('ilt', [input_symbol, s_, t]);
|
|
369
|
+
}
|
|
344
370
|
|
|
345
371
|
return retval;
|
|
346
372
|
}, true);
|
|
@@ -350,10 +376,10 @@ if ((typeof module) !== 'undefined') {
|
|
|
350
376
|
frequencyMap: function (arr) {
|
|
351
377
|
var map = {};
|
|
352
378
|
//get the frequency map
|
|
353
|
-
for
|
|
379
|
+
for(var i = 0, l = arr.length; i < l; i++) {
|
|
354
380
|
var e = arr[i],
|
|
355
381
|
key = e.toString();
|
|
356
|
-
if
|
|
382
|
+
if(!map[key]) //default it to zero
|
|
357
383
|
map[key] = 0;
|
|
358
384
|
map[key]++; //increment
|
|
359
385
|
}
|
|
@@ -361,7 +387,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
361
387
|
},
|
|
362
388
|
sort: function (arr) {
|
|
363
389
|
return arr.sort(function (a, b) {
|
|
364
|
-
if
|
|
390
|
+
if(!a.isConstant() || !b.isConstant())
|
|
365
391
|
_.error('Unable to sort! All values must be numeric');
|
|
366
392
|
return a.multiplier.subtract(b.multiplier);
|
|
367
393
|
});
|
|
@@ -371,9 +397,9 @@ if ((typeof module) !== 'undefined') {
|
|
|
371
397
|
},
|
|
372
398
|
sum: function (arr, x_) {
|
|
373
399
|
var sum = new Symbol(0);
|
|
374
|
-
for
|
|
400
|
+
for(var i = 0, l = arr.length; i < l; i++) {
|
|
375
401
|
var xi = arr[i].clone();
|
|
376
|
-
if
|
|
402
|
+
if(x_) {
|
|
377
403
|
sum = _.add(_.pow(_.subtract(xi, x_.clone()), new Symbol(2)), sum);
|
|
378
404
|
}
|
|
379
405
|
else
|
|
@@ -385,26 +411,26 @@ if ((typeof module) !== 'undefined') {
|
|
|
385
411
|
mean: function () {
|
|
386
412
|
var args = [].slice.call(arguments);
|
|
387
413
|
//handle arrays
|
|
388
|
-
if
|
|
414
|
+
if(isVector(args[0]))
|
|
389
415
|
return __.Statistics.mean.apply(this, args[0].elements);
|
|
390
416
|
return _.divide(__.Statistics.sum(args), __.Statistics.count(args));
|
|
391
417
|
},
|
|
392
418
|
median: function () {
|
|
393
419
|
var args = [].slice.call(arguments), retval;
|
|
394
420
|
//handle arrays
|
|
395
|
-
if
|
|
421
|
+
if(isVector(args[0]))
|
|
396
422
|
return __.Statistics.median.apply(this, args[0].elements);
|
|
397
423
|
try {
|
|
398
424
|
var sorted = __.Statistics.sort(args);
|
|
399
425
|
var l = args.length;
|
|
400
|
-
if
|
|
426
|
+
if(core.Utils.even(l)) {
|
|
401
427
|
var mid = l / 2;
|
|
402
428
|
retval = __.Statistics.mean(sorted[mid - 1], sorted[mid]);
|
|
403
429
|
}
|
|
404
430
|
else
|
|
405
431
|
retval = sorted[Math.floor(l / 2)];
|
|
406
432
|
}
|
|
407
|
-
catch
|
|
433
|
+
catch(e) {
|
|
408
434
|
retval = _.symfunction('median', args);
|
|
409
435
|
}
|
|
410
436
|
return retval;
|
|
@@ -413,26 +439,26 @@ if ((typeof module) !== 'undefined') {
|
|
|
413
439
|
var args = [].slice.call(arguments),
|
|
414
440
|
retval;
|
|
415
441
|
//handle arrays
|
|
416
|
-
if
|
|
442
|
+
if(isVector(args[0]))
|
|
417
443
|
return __.Statistics.mode.apply(this, args[0].elements);
|
|
418
444
|
|
|
419
445
|
var map = __.Statistics.frequencyMap(args);
|
|
420
446
|
|
|
421
447
|
//the mode of 1 item is that item as per issue #310 (verified by Happypig375).
|
|
422
|
-
if
|
|
448
|
+
if(core.Utils.keys(map).length === 1)
|
|
423
449
|
retval = args[0];
|
|
424
450
|
else {
|
|
425
451
|
//invert by arraning them according to their frequency
|
|
426
452
|
var inverse = {};
|
|
427
|
-
for
|
|
453
|
+
for(var x in map) {
|
|
428
454
|
var freq = map[x];
|
|
429
455
|
//check if it's in the inverse already
|
|
430
|
-
if
|
|
456
|
+
if(!(freq in inverse))
|
|
431
457
|
inverse[freq] = x;
|
|
432
458
|
else {
|
|
433
459
|
var e = inverse[freq];
|
|
434
460
|
//if it's already an array then just add it
|
|
435
|
-
if
|
|
461
|
+
if(isArray(e))
|
|
436
462
|
e.push(x);
|
|
437
463
|
//convert it to and array
|
|
438
464
|
else
|
|
@@ -443,7 +469,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
443
469
|
var max = inverse[Math.max.apply(null, core.Utils.keys(inverse))];
|
|
444
470
|
//check it's an array. If it is then map over the results and convert
|
|
445
471
|
//them to Symbol
|
|
446
|
-
if
|
|
472
|
+
if(isArray(max)) {
|
|
447
473
|
retval = _.symfunction('mode', max.sort());
|
|
448
474
|
}
|
|
449
475
|
else
|
|
@@ -460,7 +486,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
460
486
|
variance: function () {
|
|
461
487
|
var args = [].slice.call(arguments);
|
|
462
488
|
//handle arrays
|
|
463
|
-
if
|
|
489
|
+
if(isVector(args[0]))
|
|
464
490
|
return __.Statistics.variance.apply(this, args[0].elements);
|
|
465
491
|
var k = _.divide(new Symbol(1), __.Statistics.count(args));
|
|
466
492
|
return __.Statistics.gVariance(k, args);
|
|
@@ -468,7 +494,7 @@ if ((typeof module) !== 'undefined') {
|
|
|
468
494
|
sampleVariance: function () {
|
|
469
495
|
var args = [].slice.call(arguments);
|
|
470
496
|
//handle arrays
|
|
471
|
-
if
|
|
497
|
+
if(isVector(args[0]))
|
|
472
498
|
return __.Statistics.sampleVariance.apply(this, args[0].elements);
|
|
473
499
|
|
|
474
500
|
var k = _.divide(new Symbol(1), _.subtract(__.Statistics.count(args), new Symbol(1)));
|
|
@@ -477,14 +503,14 @@ if ((typeof module) !== 'undefined') {
|
|
|
477
503
|
standardDeviation: function () {
|
|
478
504
|
var args = [].slice.call(arguments);
|
|
479
505
|
//handle arrays
|
|
480
|
-
if
|
|
506
|
+
if(isVector(args[0]))
|
|
481
507
|
return __.Statistics.standardDeviation.apply(this, args[0].elements);
|
|
482
508
|
return _.pow(__.Statistics.variance.apply(__.Statistics, args), new Symbol(1 / 2));
|
|
483
509
|
},
|
|
484
510
|
sampleStandardDeviation: function () {
|
|
485
511
|
var args = [].slice.call(arguments);
|
|
486
512
|
//handle arrays
|
|
487
|
-
if
|
|
513
|
+
if(isVector(args[0]))
|
|
488
514
|
return __.Statistics.sampleStandardDeviation.apply(this, args[0].elements);
|
|
489
515
|
return _.pow(__.Statistics.sampleVariance.apply(__.Statistics, args), new Symbol(1 / 2));
|
|
490
516
|
},
|
|
@@ -587,5 +613,10 @@ if ((typeof module) !== 'undefined') {
|
|
|
587
613
|
]);
|
|
588
614
|
|
|
589
615
|
//link registered functions externally
|
|
590
|
-
nerdamer.
|
|
591
|
-
}());
|
|
616
|
+
nerdamer.updateAPI();
|
|
617
|
+
}());
|
|
618
|
+
|
|
619
|
+
// Added for all.min.js
|
|
620
|
+
if((typeof module) !== 'undefined') {
|
|
621
|
+
module.exports = nerdamer;
|
|
622
|
+
};
|
package/README.md
CHANGED
|
@@ -20,6 +20,25 @@ Load the library in your html page
|
|
|
20
20
|
<script src="Solve.js"></script>
|
|
21
21
|
<script src="Extra.js"></script>
|
|
22
22
|
```
|
|
23
|
+
Or import everything
|
|
24
|
+
```html
|
|
25
|
+
<script src="all.min.js"></script> <!-- assuming you've saved the file in the root -->
|
|
26
|
+
```
|
|
27
|
+
If you're using node.js install it using `npm i nerdamer` and then
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
// const cannot be used since nerdamer gets modified when other modules are loaded
|
|
31
|
+
var nerdamer = require('nerdamer');
|
|
32
|
+
// Load additional modules. These are not required.
|
|
33
|
+
require('nerdamer/Algebra');
|
|
34
|
+
require('nerdamer/Calculus');
|
|
35
|
+
require('nerdamer/Solve');
|
|
36
|
+
require('nerdamer/Extra');
|
|
37
|
+
```
|
|
38
|
+
Or do a single import to import everything
|
|
39
|
+
```javascript
|
|
40
|
+
const nerdamer = require("nerdamer/all.min")
|
|
41
|
+
```
|
|
23
42
|
|
|
24
43
|
Some functions have dependencies from other add-ons.
|
|
25
44
|
|
|
@@ -29,7 +48,7 @@ For full documentation go to http://nerdamer.com/documentation
|
|
|
29
48
|
|
|
30
49
|
All operations are done using the 'nerdamer' object.
|
|
31
50
|
|
|
32
|
-
To add an expression just add it to the nerdamer object which will return a
|
|
51
|
+
To add an expression just add it to the nerdamer object which will return a `Expression` object.
|
|
33
52
|
|
|
34
53
|
```javascript
|
|
35
54
|
var e = nerdamer('x^2+2*(cos(x)+x*x)');
|
|
@@ -38,6 +57,16 @@ console.log(e.text());
|
|
|
38
57
|
//result:
|
|
39
58
|
//2*cos(x)+3*x^2
|
|
40
59
|
```
|
|
60
|
+
It is also possible to use `nerdamer` functions directly within the need for string manipulation of the input. The input will be parsed and the output will of type `Expression`. For example:
|
|
61
|
+
```javascript
|
|
62
|
+
var ans = nerdamer.expand('(x-1)^5');
|
|
63
|
+
console.log(ans.text());
|
|
64
|
+
// -1-10*x^2-5*x^4+10*x^3+5*x+x^5
|
|
65
|
+
|
|
66
|
+
var sol = nerdamer.solve('x^2-4', 'x');
|
|
67
|
+
console.log(sol.text())
|
|
68
|
+
// [2,-2]
|
|
69
|
+
```
|
|
41
70
|
|
|
42
71
|
You can also pass in an object with known values as the second parameter.
|
|
43
72
|
|