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/Calculus.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
1
|
/* global module */
|
|
2
2
|
|
|
3
3
|
/*
|
|
4
|
-
* Author : Martin Donk
|
|
5
|
-
* Website : http://www.nerdamer.com
|
|
6
|
-
* Email : martin.r.donk@gmail.com
|
|
7
|
-
* Source : https://github.com/jiggzson/nerdamer
|
|
8
|
-
*/
|
|
4
|
+
* Author : Martin Donk
|
|
5
|
+
* Website : http://www.nerdamer.com
|
|
6
|
+
* Email : martin.r.donk@gmail.com
|
|
7
|
+
* Source : https://github.com/jiggzson/nerdamer
|
|
8
|
+
*/
|
|
9
9
|
|
|
10
10
|
if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
11
11
|
var nerdamer = require('./nerdamer.core.js');
|
|
12
12
|
require('./Algebra.js');
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
(function() {
|
|
15
|
+
(function () {
|
|
16
16
|
"use strict";
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
var core = nerdamer.getCore(),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
19
|
+
_ = core.PARSER,
|
|
20
|
+
Frac = core.Frac,
|
|
21
|
+
Settings = core.Settings,
|
|
22
|
+
isSymbol = core.Utils.isSymbol,
|
|
23
|
+
FN = core.groups.FN,
|
|
24
|
+
Symbol = core.Symbol,
|
|
25
|
+
text = core.Utils.text,
|
|
26
|
+
inBrackets = core.Utils.inBrackets,
|
|
27
|
+
isInt = core.Utils.isInt,
|
|
28
|
+
format = core.Utils.format,
|
|
29
|
+
even = core.Utils.even,
|
|
30
|
+
evaluate = core.Utils.evaluate,
|
|
31
|
+
N = core.groups.N,
|
|
32
|
+
S = core.groups.S,
|
|
33
|
+
FN = core.groups.FN,
|
|
34
|
+
PL = core.groups.PL,
|
|
35
|
+
CP = core.groups.CP,
|
|
36
|
+
CB = core.groups.CB,
|
|
37
|
+
EX = core.groups.EX,
|
|
38
|
+
P = core.groups.P,
|
|
39
|
+
LOG = Settings.LOG,
|
|
40
|
+
EXP = 'exp',
|
|
41
|
+
ABS = 'abs',
|
|
42
|
+
SQRT = 'sqrt',
|
|
43
|
+
SIN = 'sin',
|
|
44
|
+
COS = 'cos',
|
|
45
|
+
TAN = 'tan',
|
|
46
|
+
SEC = 'sec',
|
|
47
|
+
CSC = 'csc',
|
|
48
|
+
COT = 'cot',
|
|
49
|
+
ASIN = 'asin',
|
|
50
|
+
ACOS = 'acos',
|
|
51
|
+
ATAN = 'atan',
|
|
52
|
+
ASEC = 'asec',
|
|
53
|
+
ACSC = 'acsc',
|
|
54
|
+
ACOT = 'acot',
|
|
55
|
+
SINH = 'sinh',
|
|
56
|
+
COSH = 'cosh',
|
|
57
|
+
TANH = 'tanh',
|
|
58
|
+
CSCH = 'csch',
|
|
59
|
+
SECH = 'sech',
|
|
60
|
+
COTH = 'coth',
|
|
61
|
+
ASECH = 'asech',
|
|
62
|
+
ACSCH = 'acsch',
|
|
63
|
+
ACOTH = 'acoth';
|
|
64
|
+
|
|
65
65
|
//custom errors
|
|
66
|
-
function NoIntegralFound(msg){
|
|
66
|
+
function NoIntegralFound(msg) {
|
|
67
67
|
this.message = msg || "";
|
|
68
68
|
}
|
|
69
69
|
NoIntegralFound.prototype = new Error();
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
//Preparations
|
|
72
|
-
Symbol.prototype.hasIntegral = function() {
|
|
72
|
+
Symbol.prototype.hasIntegral = function () {
|
|
73
73
|
return this.containsFunction('integrate');
|
|
74
74
|
};
|
|
75
75
|
//transforms a function
|
|
76
|
-
Symbol.prototype.fnTransform = function() {
|
|
76
|
+
Symbol.prototype.fnTransform = function () {
|
|
77
77
|
if(this.group !== FN)
|
|
78
78
|
return this;
|
|
79
79
|
var retval, a = this.args[0];
|
|
@@ -159,26 +159,26 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
159
159
|
}
|
|
160
160
|
//cos(a*x)^(2*n) or sin(a*x)^(2*n)
|
|
161
161
|
else if((this.fname === COS || this.fname === SIN) && even(this.power)) {
|
|
162
|
-
var n = this.power/2;
|
|
162
|
+
var n = this.power / 2;
|
|
163
163
|
//convert to a double angle
|
|
164
164
|
var double_angle = _.pow(this.clone().toLinear(), _.parse(2)).fnTransform();
|
|
165
165
|
//raise to the n and expand
|
|
166
166
|
var transformed = _.expand(_.pow(double_angle, _.parse(n)));
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
retval = new Symbol(0);
|
|
169
|
-
|
|
170
|
-
transformed.each(function(s) {
|
|
169
|
+
|
|
170
|
+
transformed.each(function (s) {
|
|
171
171
|
var t = s.fnTransform();
|
|
172
172
|
retval = _.add(retval, t);
|
|
173
173
|
}, true);
|
|
174
174
|
}
|
|
175
175
|
else
|
|
176
176
|
retval = sym;
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
return _.multiply(retval, m);
|
|
179
179
|
};
|
|
180
|
-
|
|
181
|
-
Symbol.prototype.hasTrig = function() {
|
|
180
|
+
|
|
181
|
+
Symbol.prototype.hasTrig = function () {
|
|
182
182
|
if(this.isConstant(true) || this.group === S)
|
|
183
183
|
return false;
|
|
184
184
|
if(this.fname && (core.Utils.in_trig(this.fname) || core.Utils.in_inverse_trig(this.fname)))
|
|
@@ -191,25 +191,25 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
191
191
|
return false;
|
|
192
192
|
};
|
|
193
193
|
|
|
194
|
-
core.Expression.prototype.hasIntegral = function() {
|
|
194
|
+
core.Expression.prototype.hasIntegral = function () {
|
|
195
195
|
return this.symbol.hasIntegral();
|
|
196
196
|
};
|
|
197
197
|
/**
|
|
198
198
|
* Attempts to rewrite a symbol under one common denominator
|
|
199
199
|
* @param {Symbol} symbol
|
|
200
200
|
*/
|
|
201
|
-
core.Utils.toCommonDenominator = function(symbol) {
|
|
201
|
+
core.Utils.toCommonDenominator = function (symbol) {
|
|
202
202
|
//transform x/a+x -> (ax+x)/a
|
|
203
203
|
if(symbol.isComposite() && symbol.isLinear()) {
|
|
204
204
|
var m = new Symbol(symbol.multiplier);
|
|
205
205
|
var denominator = new Symbol(1);
|
|
206
206
|
var numerator = new Symbol(0);
|
|
207
|
-
symbol.each(function(x) {
|
|
207
|
+
symbol.each(function (x) {
|
|
208
208
|
denominator = _.multiply(denominator, x.getDenom());
|
|
209
209
|
}, true);
|
|
210
210
|
|
|
211
211
|
//remove the denomitor in each term
|
|
212
|
-
symbol.each(function(x) {
|
|
212
|
+
symbol.each(function (x) {
|
|
213
213
|
var num = x.getNum();
|
|
214
214
|
var den = x.getDenom();
|
|
215
215
|
var factor = _.multiply(num, _.divide(denominator.clone(), den));
|
|
@@ -221,132 +221,170 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
221
221
|
return symbol;
|
|
222
222
|
};
|
|
223
223
|
//A function to check if a function name is an inverse trig function
|
|
224
|
-
core.Utils.in_inverse_trig = function(x) {
|
|
225
|
-
var inv_trig_fns = [ASIN, ACOS, ATAN,
|
|
224
|
+
core.Utils.in_inverse_trig = function (x) {
|
|
225
|
+
var inv_trig_fns = [ASIN, ACOS, ATAN, ACSC, ASEC, ACOT];
|
|
226
226
|
return inv_trig_fns.indexOf(x) !== -1;
|
|
227
227
|
};
|
|
228
228
|
//A function to check if a function name is a trig function
|
|
229
|
-
core.Utils.in_trig = function(x) {
|
|
229
|
+
core.Utils.in_trig = function (x) {
|
|
230
230
|
var trig_fns = [COS, SIN, TAN, SEC, CSC, COT];
|
|
231
231
|
return trig_fns.indexOf(x) !== -1;
|
|
232
232
|
};
|
|
233
|
-
|
|
234
|
-
core.Utils.in_htrig = function(x) {
|
|
233
|
+
|
|
234
|
+
core.Utils.in_htrig = function (x) {
|
|
235
235
|
var trig_fns = [SINH, COSH, TANH, ACSCH, ASECH, ACOTH];
|
|
236
236
|
return trig_fns.indexOf(x) !== -1;
|
|
237
237
|
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
|
|
239
|
+
// Matrix functions
|
|
240
|
+
core.Matrix.jacobian = function (eqns, vars) {
|
|
241
|
+
var jacobian = new core.Matrix();
|
|
242
|
+
//get the variables if not supplied
|
|
243
|
+
if(!vars) {
|
|
244
|
+
vars = core.Utils.arrayGetVariables(eqns);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
vars.forEach(function (v, i) {
|
|
248
|
+
eqns.forEach(function (eq, j) {
|
|
249
|
+
var e = core.Calculus.diff(eq.clone(), v);
|
|
250
|
+
jacobian.set(j, i, e);
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
return jacobian;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
core.Matrix.prototype.max = function () {
|
|
258
|
+
var max = new Symbol(0);
|
|
259
|
+
this.each(function (x) {
|
|
260
|
+
var e = x.abs();
|
|
261
|
+
if(e.gt(max))
|
|
262
|
+
max = e;
|
|
263
|
+
});
|
|
264
|
+
return max;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
core.Matrix.cMatrix = function (value, vars) {
|
|
268
|
+
var m = new core.Matrix();
|
|
269
|
+
//make an initial guess
|
|
270
|
+
vars.forEach(function (v, i) {
|
|
271
|
+
m.set(i, 0, _.parse(value));
|
|
272
|
+
});
|
|
273
|
+
return m;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
var all_functions = core.Utils.all_functions = function (arr) {
|
|
277
|
+
for(var i = 0, l = arr.length; i < l; i++)
|
|
241
278
|
if(arr[i].group !== FN)
|
|
242
279
|
return false;
|
|
243
280
|
return true;
|
|
244
281
|
},
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
282
|
+
cosAsinBtransform = core.Utils.cosAsinBtranform = function (symbol1, symbol2) {
|
|
283
|
+
var a, b;
|
|
284
|
+
a = symbol1.args[0];
|
|
285
|
+
b = symbol2.args[0];
|
|
286
|
+
return _.parse(format('(sin(({0})+({1}))-sin(({0})-({1})))/2', a, b));
|
|
287
|
+
},
|
|
288
|
+
cosAsinAtransform = core.Utils.cosAsinAtranform = function (symbol1, symbol2) {
|
|
289
|
+
//TODO: temporary fix for integrate(e^x*sin(x)*cos(x)^2).
|
|
290
|
+
//we technically know how to do this transform but more is needed for correct output
|
|
291
|
+
if(Number(symbol2.power) !== 1)
|
|
292
|
+
return _.multiply(symbol1, symbol2);
|
|
293
|
+
var a;
|
|
294
|
+
a = symbol1.args[0];
|
|
295
|
+
return _.parse(format('(sin(2*({0})))/2', a));
|
|
296
|
+
},
|
|
297
|
+
sinAsinBtransform = core.Utils.cosAsinBtranform = function (symbol1, symbol2) {
|
|
298
|
+
var a, b;
|
|
299
|
+
a = symbol1.args[0];
|
|
300
|
+
b = symbol2.args[0];
|
|
301
|
+
return _.parse(format('(cos(({0})+({1}))-cos(({0})-({1})))/2', a, b));
|
|
302
|
+
},
|
|
303
|
+
trigTransform = core.Utils.trigTransform = function (arr) {
|
|
304
|
+
var map = {}, symbol, t,
|
|
305
|
+
retval = new Symbol(1);
|
|
306
|
+
for(var i = 0, l = arr.length; i < l; i++) {
|
|
307
|
+
symbol = arr[i];
|
|
308
|
+
|
|
309
|
+
if(symbol.group === FN) {
|
|
310
|
+
var fname = symbol.fname;
|
|
311
|
+
|
|
312
|
+
if(fname === COS && map[SIN]) {
|
|
313
|
+
|
|
314
|
+
if(map[SIN].args[0].toString() !== symbol.args[0].toString()) {
|
|
315
|
+
t = cosAsinBtransform(symbol, map[SIN]);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
t = cosAsinAtransform(symbol, map[SIN]);
|
|
319
|
+
}
|
|
320
|
+
delete map[SIN];
|
|
321
|
+
|
|
322
|
+
retval = _.multiply(retval, t);
|
|
323
|
+
}
|
|
324
|
+
else if(fname === SIN && map[COS]) {
|
|
325
|
+
if(map[COS].args[0].toString() !== symbol.args[0].toString()) {
|
|
326
|
+
t = cosAsinBtransform(symbol, map[COS]);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
t = cosAsinAtransform(symbol, map[COS]);
|
|
330
|
+
}
|
|
331
|
+
delete map[COS];
|
|
332
|
+
|
|
333
|
+
retval = _.multiply(retval, t);
|
|
334
|
+
}
|
|
335
|
+
else if(fname === SIN && map[SIN]) {
|
|
336
|
+
if(map[SIN].args[0].toString() !== symbol.args[0].toString()) {
|
|
337
|
+
t = sinAsinBtransform(symbol, map[SIN]);
|
|
338
|
+
delete map[SIN];
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
//This should actually be redundant code but let's put just in case
|
|
342
|
+
t = _.multiply(symbol, map[SIN]);
|
|
343
|
+
delete map[SIN];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
retval = t;
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
map[fname] = symbol;
|
|
350
|
+
}
|
|
307
351
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
map[fname] = symbol;
|
|
352
|
+
else
|
|
353
|
+
retval = _.multiply(retval, symbol);
|
|
313
354
|
}
|
|
314
|
-
}
|
|
315
|
-
else
|
|
316
|
-
retval = _.multiply(retval, symbol);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
//put back the remaining functions
|
|
320
|
-
for(var x in map)
|
|
321
|
-
retval = _.multiply(retval, map[x]);
|
|
322
|
-
|
|
323
|
-
return retval;
|
|
324
355
|
|
|
325
|
-
|
|
326
|
-
|
|
356
|
+
//put back the remaining functions
|
|
357
|
+
for(var x in map)
|
|
358
|
+
retval = _.multiply(retval, map[x]);
|
|
359
|
+
|
|
360
|
+
return retval;
|
|
361
|
+
|
|
362
|
+
};
|
|
363
|
+
|
|
327
364
|
core.Settings.integration_depth = 10;
|
|
328
|
-
|
|
365
|
+
|
|
329
366
|
core.Settings.max_lim_depth = 10;
|
|
330
|
-
|
|
367
|
+
|
|
331
368
|
var __ = core.Calculus = {
|
|
332
369
|
|
|
333
370
|
version: '1.4.6',
|
|
334
371
|
|
|
335
|
-
sum: function(fn, index, start, end) {
|
|
336
|
-
if(!(index.group === core.groups.S))
|
|
372
|
+
sum: function (fn, index, start, end) {
|
|
373
|
+
if(!(index.group === core.groups.S))
|
|
374
|
+
throw new core.exceptions.NerdamerTypeError('Index must be symbol. ' + text(index) + ' provided');
|
|
337
375
|
index = index.value;
|
|
338
376
|
var retval;
|
|
339
377
|
if(core.Utils.isNumericSymbol(start) && core.Utils.isNumericSymbol(end)) {
|
|
340
378
|
var modifier = end - start < 200 ? '' : 'PARSE2NUMBER';
|
|
341
379
|
start = Number(start);
|
|
342
380
|
end = Number(end);
|
|
343
|
-
retval = core.Utils.block(modifier, function() {
|
|
381
|
+
retval = core.Utils.block(modifier, function () {
|
|
344
382
|
var f = fn.text(),
|
|
345
|
-
|
|
346
|
-
|
|
383
|
+
subs = {'~': true}, //lock subs. Is this even being used?
|
|
384
|
+
retval = new core.Symbol(0);
|
|
347
385
|
|
|
348
|
-
for(var i=start; i<=end; i++) {
|
|
349
|
-
subs[index] = new Symbol(i);
|
|
386
|
+
for(var i = start; i <= end; i++) {
|
|
387
|
+
subs[index] = new Symbol(i);
|
|
350
388
|
var ans = _.parse(f, subs);
|
|
351
389
|
retval = _.add(retval, ans);
|
|
352
390
|
}
|
|
@@ -354,27 +392,28 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
354
392
|
});
|
|
355
393
|
}
|
|
356
394
|
else {
|
|
357
|
-
retval = _.symfunction('sum',arguments);
|
|
395
|
+
retval = _.symfunction('sum', arguments);
|
|
358
396
|
}
|
|
359
397
|
|
|
360
398
|
return retval;
|
|
361
399
|
},
|
|
362
|
-
product: function(fn, index, start, end) {
|
|
363
|
-
if(!(index.group === core.groups.S))
|
|
400
|
+
product: function (fn, index, start, end) {
|
|
401
|
+
if(!(index.group === core.groups.S))
|
|
402
|
+
throw new core.exceptions.NerdamerTypeError('Index must be symbol. ' + text(index) + ' provided');
|
|
364
403
|
index = index.value;
|
|
365
404
|
var retval;
|
|
366
405
|
if(core.Utils.isNumericSymbol(start) && core.Utils.isNumericSymbol(end)) {
|
|
367
406
|
var modifier = end - start < 200 ? '' : 'PARSE2NUMBER';
|
|
368
|
-
retval = core.Utils.block(modifier, function() {
|
|
407
|
+
retval = core.Utils.block(modifier, function () {
|
|
369
408
|
start = Number(start);
|
|
370
409
|
end = Number(end.multiplier);
|
|
371
410
|
|
|
372
411
|
var f = fn.text(),
|
|
373
|
-
|
|
374
|
-
|
|
412
|
+
subs = {},
|
|
413
|
+
retval = new core.Symbol(1);
|
|
375
414
|
|
|
376
|
-
for(var i=start; i<=end; i++) {
|
|
377
|
-
subs[index] = new Symbol(i);
|
|
415
|
+
for(var i = start; i <= end; i++) {
|
|
416
|
+
subs[index] = new Symbol(i);
|
|
378
417
|
retval = _.multiply(retval, _.parse(f, subs));
|
|
379
418
|
}
|
|
380
419
|
return retval;
|
|
@@ -386,100 +425,102 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
386
425
|
|
|
387
426
|
return retval;
|
|
388
427
|
},
|
|
389
|
-
diff: function(symbol, wrt, nth) {
|
|
428
|
+
diff: function (symbol, wrt, nth) {
|
|
390
429
|
if(core.Utils.isVector(symbol)) {
|
|
391
430
|
var vector = new core.Vector([]);
|
|
392
|
-
symbol.each(function(x) {
|
|
431
|
+
symbol.each(function (x) {
|
|
393
432
|
vector.elements.push(__.diff(x, wrt, nth));
|
|
394
433
|
});
|
|
395
434
|
return vector;
|
|
396
435
|
}
|
|
397
436
|
else if(core.Utils.isMatrix(symbol)) {
|
|
398
437
|
var matrix = new core.Matrix();
|
|
399
|
-
symbol.each(function(x, i, j) {
|
|
438
|
+
symbol.each(function (x, i, j) {
|
|
400
439
|
matrix.set(i, j, __.diff(x, wrt, nth));
|
|
401
440
|
});
|
|
402
441
|
return matrix;
|
|
403
442
|
}
|
|
404
443
|
|
|
405
|
-
var d = isSymbol(wrt) ? wrt.text() : wrt;
|
|
444
|
+
var d = isSymbol(wrt) ? wrt.text() : wrt;
|
|
406
445
|
//the nth derivative
|
|
407
446
|
nth = isSymbol(nth) ? nth.multiplier : nth || 1;
|
|
408
|
-
|
|
409
|
-
if(d === undefined)
|
|
410
|
-
|
|
447
|
+
|
|
448
|
+
if(d === undefined)
|
|
449
|
+
d = core.Utils.variables(symbol)[0];
|
|
450
|
+
|
|
411
451
|
//unwrap sqrt
|
|
412
452
|
if(symbol.group === FN && symbol.fname === SQRT) {
|
|
413
453
|
var s = symbol.args[0],
|
|
414
|
-
|
|
454
|
+
sp = symbol.power.clone();
|
|
415
455
|
//these groups go to zero anyway so why waste time?
|
|
416
456
|
if(s.group !== N || s.group !== P) {
|
|
417
|
-
s.power = isSymbol(s.power) ? _.multiply(s.power, _.multiply(new Symbol(1/2)), sp) : s.power.multiply(new Frac(0.5)).multiply(sp);
|
|
457
|
+
s.power = isSymbol(s.power) ? _.multiply(s.power, _.multiply(new Symbol(1 / 2)), sp) : s.power.multiply(new Frac(0.5)).multiply(sp);
|
|
418
458
|
s.multiplier = s.multiplier.multiply(symbol.multiplier);
|
|
419
459
|
}
|
|
420
|
-
|
|
460
|
+
|
|
421
461
|
symbol = s;
|
|
422
462
|
}
|
|
423
463
|
|
|
424
464
|
if(symbol.group === FN && !isSymbol(symbol.power)) {
|
|
425
|
-
var a = derive(_.parse(symbol));
|
|
426
|
-
var b = __.diff(symbol.args[0].clone(), d);
|
|
465
|
+
var a = derive(_.parse(symbol));
|
|
466
|
+
var b = __.diff(symbol.args[0].clone(), d);
|
|
427
467
|
symbol = _.multiply(a, b);//chain rule
|
|
428
468
|
}
|
|
429
469
|
else {
|
|
430
470
|
symbol = derive(symbol);
|
|
431
471
|
}
|
|
432
|
-
|
|
433
|
-
if(nth > 1) {
|
|
472
|
+
|
|
473
|
+
if(nth > 1) {
|
|
434
474
|
nth--;
|
|
435
475
|
symbol = __.diff(symbol, wrt, nth);
|
|
436
476
|
}
|
|
437
477
|
|
|
438
478
|
return symbol;
|
|
439
|
-
|
|
440
|
-
|
|
479
|
+
|
|
480
|
+
// Equivalent to "derivative of the outside".
|
|
441
481
|
function polydiff(symbol) {
|
|
442
|
-
if(symbol.value === d || symbol.contains(d, true)) {
|
|
482
|
+
if(symbol.value === d || symbol.contains(d, true)) {
|
|
443
483
|
symbol.multiplier = symbol.multiplier.multiply(symbol.power);
|
|
444
|
-
symbol.power = symbol.power.subtract(new Frac(1));
|
|
484
|
+
symbol.power = symbol.power.subtract(new Frac(1));
|
|
445
485
|
if(symbol.power.equals(0)) {
|
|
446
486
|
symbol = Symbol(symbol.multiplier);
|
|
447
487
|
}
|
|
448
|
-
}
|
|
449
|
-
|
|
488
|
+
}
|
|
489
|
+
|
|
450
490
|
return symbol;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function derive(symbol) {
|
|
494
|
+
var g = symbol.group, a, b, cp;
|
|
454
495
|
|
|
455
|
-
if(g === N || g === S && symbol.value !== d || g === P) {
|
|
496
|
+
if(g === N || g === S && symbol.value !== d || g === P) {
|
|
456
497
|
symbol = Symbol(0);
|
|
457
498
|
}
|
|
458
|
-
else if(g === S) {
|
|
499
|
+
else if(g === S) {
|
|
459
500
|
symbol = polydiff(symbol);
|
|
460
501
|
}
|
|
461
|
-
else if(g === CB) {
|
|
502
|
+
else if(g === CB) {
|
|
462
503
|
var m = symbol.multiplier.clone();
|
|
463
504
|
symbol.toUnitMultiplier();
|
|
464
|
-
var retval =
|
|
505
|
+
var retval = _.multiply(product_rule(symbol), polydiff(symbol));
|
|
465
506
|
retval.multiplier = retval.multiplier.multiply(m);
|
|
466
507
|
return retval;
|
|
467
508
|
}
|
|
468
|
-
else if(g === FN && symbol.power.equals(1)) {
|
|
509
|
+
else if(g === FN && symbol.power.equals(1)) {
|
|
469
510
|
// Table of known derivatives
|
|
470
511
|
switch(symbol.fname) {
|
|
471
512
|
case LOG:
|
|
472
|
-
cp = symbol.clone();
|
|
513
|
+
cp = symbol.clone();
|
|
473
514
|
symbol = symbol.args[0].clone();//get the arguments
|
|
474
515
|
symbol.power = symbol.power.negate();
|
|
475
|
-
symbol.multiplier = cp.multiplier.divide(symbol.multiplier);
|
|
516
|
+
symbol.multiplier = cp.multiplier.divide(symbol.multiplier);
|
|
476
517
|
break;
|
|
477
518
|
case COS:
|
|
478
519
|
//cos -> -sin
|
|
479
520
|
symbol.fname = SIN;
|
|
480
521
|
symbol.multiplier.negate();
|
|
481
522
|
break;
|
|
482
|
-
case SIN:
|
|
523
|
+
case SIN:
|
|
483
524
|
//sin -> cos
|
|
484
525
|
symbol.fname = COS;
|
|
485
526
|
break;
|
|
@@ -488,7 +529,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
488
529
|
symbol.fname = SEC;
|
|
489
530
|
symbol.power = new Frac(2);
|
|
490
531
|
break;
|
|
491
|
-
case SEC:
|
|
532
|
+
case SEC:
|
|
492
533
|
// Use a clone if this gives errors
|
|
493
534
|
symbol = qdiff(symbol, TAN);
|
|
494
535
|
break;
|
|
@@ -501,22 +542,22 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
501
542
|
symbol.power = new Frac(2);
|
|
502
543
|
break;
|
|
503
544
|
case ASIN:
|
|
504
|
-
symbol = _.parse('(sqrt(1-('+text(symbol.args[0])+')^2))^(-1)');
|
|
545
|
+
symbol = _.parse('(sqrt(1-(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
505
546
|
break;
|
|
506
547
|
case ACOS:
|
|
507
|
-
symbol = _.parse('-(sqrt(1-('+text(symbol.args[0])+')^2))^(-1)');
|
|
548
|
+
symbol = _.parse('-(sqrt(1-(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
508
549
|
break;
|
|
509
550
|
case ATAN:
|
|
510
|
-
symbol = _.parse('(1+('+text(symbol.args[0])+')^2)^(-1)');
|
|
551
|
+
symbol = _.parse('(1+(' + text(symbol.args[0]) + ')^2)^(-1)');
|
|
511
552
|
break;
|
|
512
|
-
case ABS:
|
|
513
|
-
m = symbol.multiplier.clone();
|
|
553
|
+
case ABS:
|
|
554
|
+
m = symbol.multiplier.clone();
|
|
514
555
|
symbol.toUnitMultiplier();
|
|
515
556
|
//depending on the complexity of the symbol it's easier to just parse it into a new symbol
|
|
516
557
|
//this should really be readdressed soon
|
|
517
558
|
b = symbol.args[0].clone();
|
|
518
559
|
b.toUnitMultiplier();
|
|
519
|
-
symbol = _.parse(inBrackets(text(symbol.args[0]))+'/abs'+inBrackets(text(b)));
|
|
560
|
+
symbol = _.parse(inBrackets(text(symbol.args[0])) + '/abs' + inBrackets(text(b)));
|
|
520
561
|
symbol.multiplier = m;
|
|
521
562
|
break;
|
|
522
563
|
case 'parens':
|
|
@@ -528,7 +569,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
528
569
|
//cosh -> -sinh
|
|
529
570
|
symbol.fname = 'sinh';
|
|
530
571
|
break;
|
|
531
|
-
case 'sinh':
|
|
572
|
+
case 'sinh':
|
|
532
573
|
//sinh -> cosh
|
|
533
574
|
symbol.fname = 'cosh';
|
|
534
575
|
break;
|
|
@@ -537,88 +578,88 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
537
578
|
symbol.fname = SECH;
|
|
538
579
|
symbol.power = new Frac(2);
|
|
539
580
|
break;
|
|
540
|
-
case SECH:
|
|
581
|
+
case SECH:
|
|
541
582
|
// Use a clone if this gives errors
|
|
542
583
|
symbol = qdiff(symbol, '-tanh');
|
|
543
584
|
break;
|
|
544
|
-
case CSCH:
|
|
585
|
+
case CSCH:
|
|
545
586
|
var arg = String(symbol.args[0]);
|
|
546
|
-
return _.parse('-coth('+arg+')*csch('+arg+')');
|
|
587
|
+
return _.parse('-coth(' + arg + ')*csch(' + arg + ')');
|
|
547
588
|
break;
|
|
548
|
-
case COTH:
|
|
589
|
+
case COTH:
|
|
549
590
|
var arg = String(symbol.args[0]);
|
|
550
|
-
return _.parse('-csch('+arg+')^2');
|
|
591
|
+
return _.parse('-csch(' + arg + ')^2');
|
|
551
592
|
break;
|
|
552
593
|
case 'asinh':
|
|
553
|
-
symbol = _.parse('(sqrt(1+('+text(symbol.args[0])+')^2))^(-1)');
|
|
594
|
+
symbol = _.parse('(sqrt(1+(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
554
595
|
break;
|
|
555
596
|
case 'acosh':
|
|
556
|
-
symbol = _.parse('(sqrt(-1+('+text(symbol.args[0])+')^2))^(-1)');
|
|
597
|
+
symbol = _.parse('(sqrt(-1+(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
557
598
|
break;
|
|
558
599
|
case 'atanh':
|
|
559
|
-
symbol = _.parse('(1-('+text(symbol.args[0])+')^2)^(-1)');
|
|
600
|
+
symbol = _.parse('(1-(' + text(symbol.args[0]) + ')^2)^(-1)');
|
|
560
601
|
break;
|
|
561
602
|
case ASECH:
|
|
562
603
|
var arg = String(symbol.args[0]);
|
|
563
|
-
symbol = _.parse('-1/(sqrt(1/('+arg+')^2-1)*('+arg+')^2)');
|
|
604
|
+
symbol = _.parse('-1/(sqrt(1/(' + arg + ')^2-1)*(' + arg + ')^2)');
|
|
564
605
|
break;
|
|
565
606
|
case ACOTH:
|
|
566
|
-
symbol = _.parse('-1/(('+symbol.args[0]+')^2-1)');
|
|
607
|
+
symbol = _.parse('-1/((' + symbol.args[0] + ')^2-1)');
|
|
567
608
|
break;
|
|
568
609
|
case ACSCH:
|
|
569
610
|
var arg = String(symbol.args[0]);
|
|
570
|
-
symbol = _.parse('-1/(sqrt(1/('+arg+')^2+1)*('+arg+')^2)');
|
|
611
|
+
symbol = _.parse('-1/(sqrt(1/(' + arg + ')^2+1)*(' + arg + ')^2)');
|
|
571
612
|
break;
|
|
572
613
|
case ASEC:
|
|
573
614
|
var arg = String(symbol.args[0]);
|
|
574
|
-
symbol = _.parse('1/(sqrt(1-1/('+arg+')^2)*('+arg+')^2)');
|
|
615
|
+
symbol = _.parse('1/(sqrt(1-1/(' + arg + ')^2)*(' + arg + ')^2)');
|
|
575
616
|
break;
|
|
576
617
|
case ACSC:
|
|
577
618
|
var arg = String(symbol.args[0]);
|
|
578
|
-
symbol = _.parse('-1/(sqrt(1-1/('+arg+')^2)*('+arg+')^2)');
|
|
619
|
+
symbol = _.parse('-1/(sqrt(1-1/(' + arg + ')^2)*(' + arg + ')^2)');
|
|
579
620
|
break;
|
|
580
621
|
case ACOT:
|
|
581
|
-
symbol = _.parse('-1/(('+symbol.args[0]+')^2+1)');
|
|
622
|
+
symbol = _.parse('-1/((' + symbol.args[0] + ')^2+1)');
|
|
582
623
|
break;
|
|
583
624
|
case 'S':
|
|
584
625
|
var arg = String(symbol.args[0]);
|
|
585
|
-
symbol = _.parse('sin((pi*('+arg+')^2)/2)');
|
|
626
|
+
symbol = _.parse('sin((pi*(' + arg + ')^2)/2)');
|
|
586
627
|
break;
|
|
587
628
|
case 'C':
|
|
588
629
|
var arg = String(symbol.args[0]);
|
|
589
|
-
symbol = _.parse('cos((pi*('+arg+')^2)/2)');
|
|
630
|
+
symbol = _.parse('cos((pi*(' + arg + ')^2)/2)');
|
|
590
631
|
break;
|
|
591
632
|
case 'Si':
|
|
592
633
|
var arg = symbol.args[0];
|
|
593
|
-
symbol = _.parse('sin('+arg+')/('+arg+')');
|
|
634
|
+
symbol = _.parse('sin(' + arg + ')/(' + arg + ')');
|
|
594
635
|
break;
|
|
595
636
|
case 'Shi':
|
|
596
637
|
var arg = symbol.args[0];
|
|
597
|
-
symbol = _.parse('sinh('+arg+')/('+arg+')');
|
|
638
|
+
symbol = _.parse('sinh(' + arg + ')/(' + arg + ')');
|
|
598
639
|
break;
|
|
599
640
|
case 'Ci':
|
|
600
641
|
var arg = symbol.args[0];
|
|
601
|
-
symbol = _.parse('cos('+arg+')/('+arg+')');
|
|
642
|
+
symbol = _.parse('cos(' + arg + ')/(' + arg + ')');
|
|
602
643
|
break;
|
|
603
644
|
case 'Chi':
|
|
604
645
|
var arg = symbol.args[0];
|
|
605
|
-
symbol = _.parse('cosh('+arg+')/('+arg+')');
|
|
646
|
+
symbol = _.parse('cosh(' + arg + ')/(' + arg + ')');
|
|
606
647
|
break;
|
|
607
648
|
case 'Ei':
|
|
608
649
|
var arg = symbol.args[0];
|
|
609
|
-
symbol = _.parse('e^('+arg+')/('+arg+')');
|
|
650
|
+
symbol = _.parse('e^(' + arg + ')/(' + arg + ')');
|
|
610
651
|
break;
|
|
611
652
|
case 'Li':
|
|
612
653
|
var arg = symbol.args[0];
|
|
613
|
-
symbol = _.parse('1/'+Settings.LOG+'('+arg+')');
|
|
654
|
+
symbol = _.parse('1/' + Settings.LOG + '(' + arg + ')');
|
|
614
655
|
break;
|
|
615
656
|
case 'erf':
|
|
616
|
-
symbol = _.parse('(2*e^(-('+symbol.args[0]+')^2))/sqrt(pi)');
|
|
657
|
+
symbol = _.parse('(2*e^(-(' + symbol.args[0] + ')^2))/sqrt(pi)');
|
|
617
658
|
break;
|
|
618
659
|
case 'atan2':
|
|
619
660
|
var x_ = String(symbol.args[0]),
|
|
620
|
-
|
|
621
|
-
symbol = _.parse('('+y_+')/(('+y_+')^2+('+x_+')^2)');
|
|
661
|
+
y_ = String(symbol.args[1]);
|
|
662
|
+
symbol = _.parse('(' + y_ + ')/((' + y_ + ')^2+(' + x_ + ')^2)');
|
|
622
663
|
break;
|
|
623
664
|
case 'sign':
|
|
624
665
|
symbol = new Symbol(0);
|
|
@@ -627,35 +668,36 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
627
668
|
symbol = _.parse(format('(({0})*cos({0})-sin({0}))*({0})^(-2)', symbol.args[0]));
|
|
628
669
|
break;
|
|
629
670
|
case Settings.LOG10:
|
|
630
|
-
symbol = _.parse('1/(('+symbol.args[0]+')*'+Settings.LOG+'(10))');
|
|
671
|
+
symbol = _.parse('1/((' + symbol.args[0] + ')*' + Settings.LOG + '(10))');
|
|
631
672
|
break;
|
|
632
673
|
default:
|
|
633
674
|
symbol = _.symfunction('diff', [symbol, wrt]);
|
|
634
675
|
}
|
|
635
676
|
}
|
|
636
|
-
else if(g === EX || g === FN && isSymbol(symbol.power)) {
|
|
677
|
+
else if(g === EX || g === FN && isSymbol(symbol.power)) {
|
|
637
678
|
var value;
|
|
638
679
|
if(g === EX) {
|
|
639
680
|
value = symbol.value;
|
|
640
681
|
}
|
|
641
|
-
else if(g === FN && symbol.contains(d)) {
|
|
682
|
+
else if(g === FN && symbol.contains(d)) {
|
|
642
683
|
value = symbol.fname + inBrackets(text(symbol.args[0]));
|
|
643
684
|
}
|
|
644
685
|
else {
|
|
645
686
|
value = symbol.value + inBrackets(text(symbol.args[0]));
|
|
646
687
|
}
|
|
647
|
-
|
|
648
|
-
|
|
688
|
+
a = _.multiply(_.parse(LOG + inBrackets(value)), symbol.power.clone());
|
|
689
|
+
b = __.diff(_.multiply(_.parse(LOG + inBrackets(value)), symbol.power.clone()), d);
|
|
649
690
|
symbol = _.multiply(symbol, b);
|
|
650
691
|
}
|
|
651
|
-
else if(g === FN && !symbol.power.equals(1)) {
|
|
692
|
+
else if(g === FN && !symbol.power.equals(1)) {
|
|
652
693
|
b = symbol.clone();
|
|
653
694
|
b.toLinear();
|
|
654
695
|
b.toUnitMultiplier();
|
|
655
|
-
symbol = _.multiply(polydiff(symbol.clone()), derive(b));
|
|
696
|
+
symbol = _.multiply(polydiff(symbol.clone()), derive(b));
|
|
656
697
|
}
|
|
657
|
-
else if(
|
|
658
|
-
|
|
698
|
+
else if(g === CP || g === PL) {
|
|
699
|
+
// Note: Do not use `parse` since this puts back the sqrt and causes a bug as in #610. Use clone.
|
|
700
|
+
var c = symbol.clone();
|
|
659
701
|
var result = new Symbol(0);
|
|
660
702
|
for(var x in symbol.symbols) {
|
|
661
703
|
result = _.add(result, __.diff(symbol.symbols[x].clone(), d));
|
|
@@ -664,23 +706,25 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
664
706
|
}
|
|
665
707
|
|
|
666
708
|
symbol.updateHash();
|
|
667
|
-
|
|
709
|
+
|
|
668
710
|
return symbol;
|
|
669
|
-
}
|
|
711
|
+
}
|
|
712
|
+
;
|
|
670
713
|
|
|
671
714
|
function qdiff(symbol, val, altVal) {
|
|
672
|
-
return _.multiply(symbol, _.parse(val+inBrackets(altVal || text(symbol.args[0]))));
|
|
673
|
-
}
|
|
715
|
+
return _.multiply(symbol, _.parse(val + inBrackets(altVal || text(symbol.args[0]))));
|
|
716
|
+
}
|
|
717
|
+
;
|
|
674
718
|
|
|
675
|
-
function product_rule(symbol) {
|
|
719
|
+
function product_rule(symbol) {
|
|
676
720
|
//grab all the symbols within the CB symbol
|
|
677
|
-
var symbols = symbol.collectSymbols(),
|
|
678
|
-
|
|
679
|
-
|
|
721
|
+
var symbols = symbol.collectSymbols(),
|
|
722
|
+
result = new Symbol(0),
|
|
723
|
+
l = symbols.length;
|
|
680
724
|
//loop over all the symbols
|
|
681
|
-
for(var i=0; i<l; i++) {
|
|
725
|
+
for(var i = 0; i < l; i++) {
|
|
682
726
|
var df = __.diff(symbols[i].clone(), d);
|
|
683
|
-
for(var j=0; j<l; j++) {
|
|
727
|
+
for(var j = 0; j < l; j++) {
|
|
684
728
|
//skip the symbol of which we just pulled the derivative
|
|
685
729
|
if(i !== j) {
|
|
686
730
|
//multiply out the remaining symbols
|
|
@@ -691,18 +735,19 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
691
735
|
result = _.add(result, df);
|
|
692
736
|
}
|
|
693
737
|
return result; //done
|
|
694
|
-
}
|
|
738
|
+
}
|
|
739
|
+
;
|
|
695
740
|
},
|
|
696
741
|
integration: {
|
|
697
|
-
u_substitution: function(symbols, dx) {
|
|
742
|
+
u_substitution: function (symbols, dx) {
|
|
698
743
|
function try_combo(a, b, f) {
|
|
699
744
|
var d = __.diff(b, dx);
|
|
700
745
|
var q = f ? f(a, b) : _.divide(a.clone(), d);
|
|
701
|
-
if(!q.contains(dx, true))
|
|
746
|
+
if(!q.contains(dx, true))
|
|
702
747
|
return q;
|
|
703
748
|
return null;
|
|
704
749
|
}
|
|
705
|
-
function do_fn_sub(fname, arg) {
|
|
750
|
+
function do_fn_sub(fname, arg) {
|
|
706
751
|
var subbed = __.integrate(_.symfunction(fname, [new Symbol(u)]), u, 0);
|
|
707
752
|
subbed = subbed.sub(new Symbol(u), arg);
|
|
708
753
|
subbed.updateHash();
|
|
@@ -710,18 +755,18 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
710
755
|
}
|
|
711
756
|
|
|
712
757
|
var a = symbols[0].clone(),
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
758
|
+
b = symbols[1].clone(),
|
|
759
|
+
g1 = a.group,
|
|
760
|
+
g2 = b.group,
|
|
761
|
+
//may cause problems if person is using this already. Will need
|
|
762
|
+
//to find algorithm for detecting conflict
|
|
763
|
+
u = '__u__',
|
|
764
|
+
Q;
|
|
720
765
|
if(g1 === FN && g2 !== FN) {
|
|
721
766
|
//e.g. 2*x*cos(x^2)
|
|
722
767
|
var arg = a.args[0];
|
|
723
768
|
Q = try_combo(b, arg.clone());
|
|
724
|
-
if(Q)
|
|
769
|
+
if(Q)
|
|
725
770
|
return _.multiply(Q, do_fn_sub(a.fname, arg));
|
|
726
771
|
Q = try_combo(b, a);
|
|
727
772
|
if(Q) {
|
|
@@ -732,7 +777,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
732
777
|
//e.g. 2*(x+1)*cos((x+1)^2
|
|
733
778
|
var arg = b.args[0];
|
|
734
779
|
Q = try_combo(a, arg.clone());
|
|
735
|
-
if(Q)
|
|
780
|
+
if(Q)
|
|
736
781
|
return _.multiply(Q, do_fn_sub(b.fname, arg));
|
|
737
782
|
}
|
|
738
783
|
else if(g1 === FN && g2 === FN) {
|
|
@@ -743,8 +788,8 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
743
788
|
if(Q)
|
|
744
789
|
return _.multiply(__.integration.poly_integrate(b), Q);
|
|
745
790
|
}
|
|
746
|
-
else if(g1 === EX && g2 !== EX) {
|
|
747
|
-
var p = a.power;
|
|
791
|
+
else if(g1 === EX && g2 !== EX) {
|
|
792
|
+
var p = a.power;
|
|
748
793
|
Q = try_combo(b, p.clone());
|
|
749
794
|
if(!Q) {
|
|
750
795
|
//one more try
|
|
@@ -764,8 +809,8 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
764
809
|
}
|
|
765
810
|
var integrated = __.integrate(a.sub(p.clone(), new Symbol(u)), u, 0),
|
|
766
811
|
retval = _.multiply(integrated.sub(new Symbol(u), p), Q);
|
|
767
|
-
|
|
768
|
-
|
|
812
|
+
|
|
813
|
+
|
|
769
814
|
return retval;
|
|
770
815
|
}
|
|
771
816
|
else if(g2 === EX && g1 !== EX) {
|
|
@@ -774,18 +819,18 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
774
819
|
var integrated = __.integrate(b.sub(p, new Symbol(u)), u, 0);
|
|
775
820
|
return _.multiply(integrated.sub(new Symbol(u), p), Q);
|
|
776
821
|
}
|
|
777
|
-
else if(a.isComposite() || b.isComposite()) {
|
|
778
|
-
var f = function(a, b) {
|
|
822
|
+
else if(a.isComposite() || b.isComposite()) {
|
|
823
|
+
var f = function (a, b) {
|
|
779
824
|
var d = __.diff(b, dx);
|
|
780
825
|
var A = core.Algebra.Factor.factor(a),
|
|
781
|
-
|
|
826
|
+
B = core.Algebra.Factor.factor(d);
|
|
782
827
|
var q = _.divide(A, B);
|
|
783
828
|
return q;
|
|
784
829
|
};
|
|
785
830
|
var f1 = a.isComposite() ? a.clone().toLinear() : a.clone(),
|
|
786
|
-
|
|
787
|
-
Q = try_combo(f1.clone(), f2.clone(), f);
|
|
788
|
-
if(Q)
|
|
831
|
+
f2 = b.isComposite() ? b.clone().toLinear() : b.clone();
|
|
832
|
+
Q = try_combo(f1.clone(), f2.clone(), f);
|
|
833
|
+
if(Q)
|
|
789
834
|
return _.multiply(__.integration.poly_integrate(b), Q);
|
|
790
835
|
Q = try_combo(f2.clone(), f1.clone(), f);
|
|
791
836
|
if(Q)
|
|
@@ -793,10 +838,10 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
793
838
|
}
|
|
794
839
|
},
|
|
795
840
|
//simple integration of a single polynomial x^(n+1)/(n+1)
|
|
796
|
-
poly_integrate: function(x) {
|
|
841
|
+
poly_integrate: function (x) {
|
|
797
842
|
var p = x.power.toString(),
|
|
798
|
-
|
|
799
|
-
|
|
843
|
+
m = x.multiplier.toDecimal(),
|
|
844
|
+
s = x.toUnitMultiplier().toLinear();
|
|
800
845
|
if(Number(p) === -1) {
|
|
801
846
|
return _.multiply(new Symbol(m), _.symfunction(LOG, [s]));
|
|
802
847
|
}
|
|
@@ -804,27 +849,27 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
804
849
|
},
|
|
805
850
|
//If we're just spinning wheels we want to stop. This is why we
|
|
806
851
|
//wrap integration in a try catch block and call this to stop.
|
|
807
|
-
stop: function(msg) {
|
|
852
|
+
stop: function (msg) {
|
|
808
853
|
msg = msg || 'Unable to compute integral!';
|
|
809
854
|
core.Utils.warn(msg);
|
|
810
855
|
throw new NoIntegralFound(msg);
|
|
811
856
|
},
|
|
812
|
-
partial_fraction: function(input, dx, depth, opt) {
|
|
857
|
+
partial_fraction: function (input, dx, depth, opt) {
|
|
813
858
|
//TODO: This whole thing needs to be rolled into one but for now I'll leave it as two separate parts
|
|
814
859
|
if(!isSymbol(dx))
|
|
815
860
|
dx = _.parse(dx);
|
|
816
|
-
|
|
861
|
+
|
|
817
862
|
var result, partial_fractions;
|
|
818
863
|
result = new Symbol(0);
|
|
819
864
|
partial_fractions = core.Algebra.PartFrac.partfrac(input, dx);
|
|
820
865
|
|
|
821
866
|
if(partial_fractions.group === CB && partial_fractions.isLinear()) {
|
|
822
867
|
//perform a quick check to make sure that all partial fractions are linear
|
|
823
|
-
partial_fractions.each(function(x) {
|
|
868
|
+
partial_fractions.each(function (x) {
|
|
824
869
|
if(!x.isLinear())
|
|
825
870
|
__.integration.stop();
|
|
826
871
|
});
|
|
827
|
-
partial_fractions.each(function(x) {
|
|
872
|
+
partial_fractions.each(function (x) {
|
|
828
873
|
result = _.add(result, __.integrate(x, dx, depth, opt));
|
|
829
874
|
});
|
|
830
875
|
}
|
|
@@ -833,11 +878,11 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
833
878
|
}
|
|
834
879
|
return result;
|
|
835
880
|
},
|
|
836
|
-
get_udv: function(symbol) {
|
|
881
|
+
get_udv: function (symbol) {
|
|
837
882
|
var parts = [[/*L*/], [/*I*/], [/*A*/], [/*T*/], [/*E*/]];
|
|
838
883
|
//first we sort them
|
|
839
|
-
var setSymbol = function(x) {
|
|
840
|
-
var g = x.group;
|
|
884
|
+
var setSymbol = function (x) {
|
|
885
|
+
var g = x.group;
|
|
841
886
|
if(g === FN) {
|
|
842
887
|
var fname = x.fname;
|
|
843
888
|
if(core.Utils.in_trig(fname) || core.Utils.in_htrig(fname))
|
|
@@ -846,7 +891,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
846
891
|
parts[1].push(x);
|
|
847
892
|
else if(fname === LOG)
|
|
848
893
|
parts[0].push(x);
|
|
849
|
-
else {
|
|
894
|
+
else {
|
|
850
895
|
__.integration.stop();
|
|
851
896
|
}
|
|
852
897
|
}
|
|
@@ -858,72 +903,73 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
858
903
|
else
|
|
859
904
|
__.integration.stop();
|
|
860
905
|
};
|
|
861
|
-
|
|
862
|
-
if(symbol.group === CB)
|
|
863
|
-
symbol.each(function(x) {
|
|
906
|
+
|
|
907
|
+
if(symbol.group === CB)
|
|
908
|
+
symbol.each(function (x) {
|
|
864
909
|
setSymbol(Symbol.unwrapSQRT(x, true));
|
|
865
910
|
});
|
|
866
|
-
else
|
|
911
|
+
else
|
|
867
912
|
setSymbol(symbol);
|
|
868
913
|
var u, dv = new Symbol(1);
|
|
869
914
|
//compile u and dv
|
|
870
|
-
for(var i=0; i<5; i++) {
|
|
915
|
+
for(var i = 0; i < 5; i++) {
|
|
871
916
|
var part = parts[i], t,
|
|
872
|
-
|
|
917
|
+
l = part.length;
|
|
873
918
|
if(l > 0) {
|
|
874
919
|
if(l > 1) {
|
|
875
920
|
t = new Symbol(1);
|
|
876
|
-
for(var j=0; j<l; j++)
|
|
921
|
+
for(var j = 0; j < l; j++)
|
|
877
922
|
t = _.multiply(t, part[j].clone());
|
|
878
923
|
}
|
|
879
924
|
else
|
|
880
925
|
t = part[0].clone();
|
|
881
926
|
|
|
882
|
-
if(!u) {
|
|
927
|
+
if(!u) {
|
|
883
928
|
u = t;//the first u encountered gets chosen
|
|
884
929
|
u.multiplier = u.multiplier.multiply(symbol.multiplier); //the first one gets the mutliplier
|
|
885
|
-
}
|
|
886
|
-
else
|
|
887
|
-
|
|
930
|
+
}
|
|
931
|
+
else
|
|
932
|
+
dv = _.multiply(dv, t); //everything else belongs to dv
|
|
933
|
+
}
|
|
888
934
|
}
|
|
889
935
|
|
|
890
936
|
return [u, dv];
|
|
891
937
|
},
|
|
892
|
-
|
|
893
|
-
trig_sub: function(symbol, dx, depth, opt, parts, symbols) {
|
|
938
|
+
|
|
939
|
+
trig_sub: function (symbol, dx, depth, opt, parts, symbols) {
|
|
894
940
|
parts = parts || __.integration.decompose_arg(symbol.clone().toLinear(), dx);
|
|
895
941
|
var b = parts[3],
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
942
|
+
ax = parts[2],
|
|
943
|
+
a = parts[0],
|
|
944
|
+
x = parts[1];
|
|
899
945
|
if(x.power.equals(2) && a.greaterThan(0)) {
|
|
900
946
|
//use tan(x)
|
|
901
947
|
var t = core.Utils.getU(symbol), //get an appropriate u
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
948
|
+
u = _.parse(TAN + inBrackets(t)), //u
|
|
949
|
+
du = _.parse(SEC + inBrackets(t) + '^2'), //du
|
|
950
|
+
f = _.multiply(symbol.sub(x, u), du);
|
|
905
951
|
var integral = __.integrate(f, t, depth, opt).sub(u, x);
|
|
906
952
|
core.Utils.clearU(u);
|
|
907
953
|
return integral;
|
|
908
954
|
}
|
|
909
955
|
},
|
|
910
|
-
|
|
911
|
-
by_parts: function(symbol, dx, depth, o) {
|
|
956
|
+
|
|
957
|
+
by_parts: function (symbol, dx, depth, o) {
|
|
912
958
|
o.previous = o.previous || [];
|
|
913
959
|
var udv, u, dv, du, v, vdu, uv, retval, integral_vdu, m, c, vdu_s;
|
|
914
960
|
//first LIATE
|
|
915
961
|
udv = __.integration.get_udv(symbol);
|
|
916
|
-
u = udv[0];
|
|
917
|
-
dv = udv[1];
|
|
918
|
-
du = Symbol.unwrapSQRT(_.expand(__.diff(u.clone(), dx)), true);
|
|
962
|
+
u = udv[0];
|
|
963
|
+
dv = udv[1];
|
|
964
|
+
du = Symbol.unwrapSQRT(_.expand(__.diff(u.clone(), dx)), true);
|
|
919
965
|
c = du.clone().stripVar(dx);
|
|
920
966
|
//strip any coefficients
|
|
921
967
|
du = _.divide(du, c.clone());
|
|
922
|
-
v = __.integrate(dv.clone(), dx, depth || 0);
|
|
923
|
-
vdu = _.multiply(v.clone(), du);
|
|
968
|
+
v = __.integrate(dv.clone(), dx, depth || 0);
|
|
969
|
+
vdu = _.multiply(v.clone(), du);
|
|
924
970
|
vdu_s = vdu.toString();
|
|
925
971
|
//currently only supports e^x*(some trig)
|
|
926
|
-
if(o.previous.indexOf(vdu_s) !== -1 && (core.Utils.in_trig(u.fname)) && dv.isE()) {
|
|
972
|
+
if(o.previous.indexOf(vdu_s) !== -1 && (core.Utils.in_trig(u.fname)) && dv.isE()) {
|
|
927
973
|
//We're going to exploit the fact that vdu can never be constant
|
|
928
974
|
//to work out way out of this cycle. We'll return the length of
|
|
929
975
|
//the this.previous array until we're back at level one
|
|
@@ -934,21 +980,21 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
934
980
|
else
|
|
935
981
|
o.previous.push(vdu_s);
|
|
936
982
|
|
|
937
|
-
uv = _.multiply(u, v);
|
|
983
|
+
uv = _.multiply(u, v);
|
|
938
984
|
//clear the multiplier so we're dealing with a bare integral
|
|
939
985
|
m = vdu.multiplier.clone();
|
|
940
986
|
vdu.toUnitMultiplier();
|
|
941
|
-
integral_vdu = _.multiply(__.integrate(vdu.clone(), dx, depth, o), c);
|
|
987
|
+
integral_vdu = _.multiply(__.integrate(vdu.clone(), dx, depth, o), c);
|
|
942
988
|
integral_vdu.multiplier = integral_vdu.multiplier.multiply(m);
|
|
943
989
|
retval = _.subtract(uv, integral_vdu);
|
|
944
990
|
//we know that there cannot be constants so they're a holdover from a cyclic integral
|
|
945
|
-
if(o.is_cyclic) {
|
|
991
|
+
if(o.is_cyclic) {
|
|
946
992
|
//start popping the previous stack so we know how deep in we are
|
|
947
993
|
o.previous.pop();
|
|
948
994
|
if(o.previous.length === 0) {
|
|
949
995
|
retval = _.expand(retval);
|
|
950
996
|
var rem = new Symbol(0);
|
|
951
|
-
retval.each(function(x) {
|
|
997
|
+
retval.each(function (x) {
|
|
952
998
|
if(!x.contains(dx))
|
|
953
999
|
rem = _.add(rem, x.clone());
|
|
954
1000
|
});
|
|
@@ -956,7 +1002,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
956
1002
|
retval = _.divide(_.subtract(retval, rem.clone()), _.subtract(new Symbol(1), rem));
|
|
957
1003
|
}
|
|
958
1004
|
}
|
|
959
|
-
|
|
1005
|
+
|
|
960
1006
|
return retval;
|
|
961
1007
|
},
|
|
962
1008
|
/*
|
|
@@ -965,56 +1011,56 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
965
1011
|
decompose_arg: core.Utils.decompose_fn
|
|
966
1012
|
},
|
|
967
1013
|
//TODO: nerdamer.integrate('-e^(-a*t)*sin(t)', 't') -> gives incorrect output
|
|
968
|
-
integrate: function(original_symbol, dt, depth, opt) {
|
|
1014
|
+
integrate: function (original_symbol, dt, depth, opt) {
|
|
969
1015
|
//assume integration wrt independent variable if expression only has one variable
|
|
970
1016
|
if(!dt) {
|
|
971
1017
|
var vars = core.Utils.variables(original_symbol);
|
|
972
1018
|
if(vars.length === 1)
|
|
973
|
-
dt = vars[0];
|
|
1019
|
+
dt = vars[0];
|
|
974
1020
|
//defaults to x
|
|
975
1021
|
dt = dt || 'x';
|
|
976
1022
|
}
|
|
977
1023
|
//add support for integrating vectors
|
|
978
1024
|
if(core.Utils.isVector(original_symbol)) {
|
|
979
1025
|
var vector = new core.Vector([]);
|
|
980
|
-
original_symbol.each(function(x) {
|
|
1026
|
+
original_symbol.each(function (x) {
|
|
981
1027
|
vector.elements.push(__.integrate(x, dt));
|
|
982
1028
|
});
|
|
983
1029
|
return vector;
|
|
984
1030
|
}
|
|
985
1031
|
if(!isNaN(dt))
|
|
986
|
-
_.error('variable expected but received '+dt);
|
|
1032
|
+
_.error('variable expected but received ' + dt);
|
|
987
1033
|
//get rid of constants right away
|
|
988
1034
|
if(original_symbol.isConstant(true))
|
|
989
1035
|
return _.multiply(original_symbol.clone(), _.parse(dt));
|
|
990
|
-
|
|
1036
|
+
|
|
991
1037
|
//configurations options for integral. This is needed for tracking extra options
|
|
992
1038
|
//e.g. cyclic integrals or additional settings
|
|
993
1039
|
opt = opt || {};
|
|
994
|
-
return core.Utils.block('PARSE2NUMBER', function() {
|
|
1040
|
+
return core.Utils.block('PARSE2NUMBER', function () {
|
|
995
1041
|
//make a note of the original symbol. Set only if undefined
|
|
996
1042
|
depth = depth || 0;
|
|
997
1043
|
var dx = isSymbol(dt) ? dt.toString() : dt,
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1044
|
+
//we don't want the symbol in sqrt form. x^(1/2) is prefererred
|
|
1045
|
+
symbol = Symbol.unwrapSQRT(original_symbol.clone(), true),
|
|
1046
|
+
g = symbol.group,
|
|
1047
|
+
retval;
|
|
1002
1048
|
|
|
1003
|
-
try {
|
|
1049
|
+
try {
|
|
1004
1050
|
//We stop integration after x amount of recursive calls
|
|
1005
|
-
if(++depth > core.Settings.integration_depth)
|
|
1051
|
+
if(++depth > core.Settings.integration_depth)
|
|
1006
1052
|
__.integration.stop('Maximum depth reached. Exiting!');
|
|
1007
1053
|
|
|
1008
1054
|
//constants. We first eliminate anything that doesn't have dx. Everything after this has
|
|
1009
1055
|
//to have dx or else it would have been taken care of below
|
|
1010
|
-
if(!symbol.contains(dx, true)) {
|
|
1056
|
+
if(!symbol.contains(dx, true)) {
|
|
1011
1057
|
retval = _.multiply(symbol.clone(), _.parse(dx));
|
|
1012
1058
|
}
|
|
1013
1059
|
//e.g. 2*x
|
|
1014
1060
|
else if(g === S) {
|
|
1015
1061
|
retval = __.integration.poly_integrate(symbol, dx, depth);
|
|
1016
1062
|
}
|
|
1017
|
-
else if(g === EX) {
|
|
1063
|
+
else if(g === EX) {
|
|
1018
1064
|
if(symbol.previousGroup === FN && !(symbol.fname === 'sqrt' || symbol.fname === Settings.PARENTHESIS))
|
|
1019
1065
|
__.integration.stop();
|
|
1020
1066
|
//check the base
|
|
@@ -1023,7 +1069,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1023
1069
|
//don't know what to do with it e.g. x^x
|
|
1024
1070
|
if(symbol.power.contains(dx))
|
|
1025
1071
|
__.integration.stop();
|
|
1026
|
-
else {
|
|
1072
|
+
else {
|
|
1027
1073
|
var t = __.diff(symbol.clone().toLinear(), dx);
|
|
1028
1074
|
if(t.contains(dx))
|
|
1029
1075
|
__.integration.stop();
|
|
@@ -1037,7 +1083,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1037
1083
|
var a = __.diff(symbol.power.clone(), dx);
|
|
1038
1084
|
if(a.contains(dx)) {
|
|
1039
1085
|
var aa = a.stripVar(dx),
|
|
1040
|
-
|
|
1086
|
+
x = _.divide(a.clone(), aa.clone());
|
|
1041
1087
|
if(x.group === S && x.isLinear()) {
|
|
1042
1088
|
aa.multiplier = aa.multiplier.divide(new Frac(2));
|
|
1043
1089
|
return _.parse(format('({2})*(sqrt(pi)*erf(sqrt(-{0})*{1}))/(2*sqrt(-{0}))', aa, dx, symbol.multiplier));
|
|
@@ -1045,7 +1091,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1045
1091
|
else
|
|
1046
1092
|
__.integration.stop();
|
|
1047
1093
|
}
|
|
1048
|
-
if(symbol.isE()) {
|
|
1094
|
+
if(symbol.isE()) {
|
|
1049
1095
|
if(a.isLinear())
|
|
1050
1096
|
retval = symbol;
|
|
1051
1097
|
else {
|
|
@@ -1062,63 +1108,63 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1062
1108
|
retval = _.divide(retval, a);
|
|
1063
1109
|
}
|
|
1064
1110
|
}
|
|
1065
|
-
else if(symbol.isComposite() && symbol.isLinear()) {
|
|
1111
|
+
else if(symbol.isComposite() && symbol.isLinear()) {
|
|
1066
1112
|
var m = _.parse(symbol.multiplier);
|
|
1067
1113
|
symbol.toUnitMultiplier();
|
|
1068
1114
|
retval = new Symbol(0);
|
|
1069
|
-
symbol.each(function(x) {
|
|
1115
|
+
symbol.each(function (x) {
|
|
1070
1116
|
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
1071
1117
|
});
|
|
1072
1118
|
retval = _.multiply(m, retval);
|
|
1073
1119
|
}
|
|
1074
|
-
else if(g === CP) {
|
|
1120
|
+
else if(g === CP) {
|
|
1075
1121
|
if(symbol.power.greaterThan(1))
|
|
1076
1122
|
symbol = _.expand(symbol);
|
|
1077
1123
|
if(symbol.power.equals(1)) {
|
|
1078
1124
|
retval = new Symbol(0);
|
|
1079
|
-
symbol.each(function(x) {
|
|
1125
|
+
symbol.each(function (x) {
|
|
1080
1126
|
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
1081
1127
|
}, true);
|
|
1082
1128
|
}
|
|
1083
1129
|
else {
|
|
1084
1130
|
var p = Number(symbol.power),
|
|
1085
|
-
|
|
1131
|
+
m = symbol.multiplier.clone();//temporarily remove the multiplier
|
|
1086
1132
|
symbol.toUnitMultiplier();
|
|
1087
1133
|
var //below we consider the form ax+b
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
if(p === -1 && x.group !== PL && x.power.equals(2)) {
|
|
1134
|
+
fn = symbol.clone().toLinear(), //get just the pure function without the power
|
|
1135
|
+
decomp = __.integration.decompose_arg(fn, dx),
|
|
1136
|
+
//I have no idea why I used bx+a and not ax+b. TODO change this to something that makes sense
|
|
1137
|
+
b = decomp[3],
|
|
1138
|
+
ax = decomp[2],
|
|
1139
|
+
a = decomp[0],
|
|
1140
|
+
x = decomp[1];
|
|
1141
|
+
if(p === -1 && x.group !== PL && x.power.equals(2)) {
|
|
1096
1142
|
var b_is_positive = isInt(b) ? b > 0 : true;
|
|
1097
1143
|
//we can now check for atan
|
|
1098
|
-
if(x.group === S && x.power.equals(2) && b_is_positive) {
|
|
1144
|
+
if(x.group === S && x.power.equals(2) && b_is_positive) {
|
|
1099
1145
|
////then we have atan
|
|
1100
1146
|
//abs is redundants since the sign appears in both denom and num.
|
|
1101
|
-
var unwrapAbs = function(s) {
|
|
1147
|
+
var unwrapAbs = function (s) {
|
|
1102
1148
|
var result = new Symbol(1);
|
|
1103
|
-
s.each(function(x) {
|
|
1149
|
+
s.each(function (x) {
|
|
1104
1150
|
result = _.multiply(result, x.fname === 'abs' ? x.args[0] : x);
|
|
1105
1151
|
});
|
|
1106
1152
|
return result;
|
|
1107
1153
|
};
|
|
1108
1154
|
var A = a.clone(),
|
|
1109
|
-
|
|
1110
|
-
A = _.pow(A, new Symbol(1/2));
|
|
1111
|
-
B = _.pow(B, new Symbol(1/2));
|
|
1155
|
+
B = b.clone();
|
|
1156
|
+
A = _.pow(A, new Symbol(1 / 2));
|
|
1157
|
+
B = _.pow(B, new Symbol(1 / 2));
|
|
1112
1158
|
//unwrap abs
|
|
1113
1159
|
|
|
1114
1160
|
var d = _.multiply(unwrapAbs(B), unwrapAbs(A)),
|
|
1115
|
-
|
|
1161
|
+
f = _.symfunction(ATAN, [_.divide(_.multiply(a, x.toLinear()), d.clone())]);
|
|
1116
1162
|
retval = _.divide(f, d);
|
|
1117
1163
|
}
|
|
1118
1164
|
else if(x.group === S && x.isLinear()) {
|
|
1119
1165
|
retval = _.divide(__.integration.poly_integrate(symbol), a);
|
|
1120
1166
|
}
|
|
1121
|
-
else {
|
|
1167
|
+
else {
|
|
1122
1168
|
//1/(x^4+1)
|
|
1123
1169
|
if(x.power.equals(4)) {
|
|
1124
1170
|
//https://www.freemathhelp.com/forum/threads/55678-difficult-integration-int-1-(1-x-4)-dx
|
|
@@ -1126,22 +1172,22 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1126
1172
|
var br = inBrackets;
|
|
1127
1173
|
//apply rule: ax^4+b = (√ax^2+√2∜a∜bx+√b)(√ax^2-√2∜a∜bx+√b)
|
|
1128
1174
|
//get quadratic factors
|
|
1129
|
-
A = _.parse(SQRT+br(a)+'*'+dx+'^2');
|
|
1130
|
-
B = _.parse(SQRT+br(2)+'*'+br(a)+'^'+br('1/4')+'*'+br(b)+'^'+br('1/4')+'*'+dx);
|
|
1131
|
-
C = _.parse(SQRT+br(b));
|
|
1175
|
+
A = _.parse(SQRT + br(a) + '*' + dx + '^2');
|
|
1176
|
+
B = _.parse(SQRT + br(2) + '*' + br(a) + '^' + br('1/4') + '*' + br(b) + '^' + br('1/4') + '*' + dx);
|
|
1177
|
+
C = _.parse(SQRT + br(b));
|
|
1132
1178
|
f1 = _.add(_.add(A.clone(), B.clone()), C.clone());
|
|
1133
1179
|
f2 = _.add(_.subtract(A, B), C);
|
|
1134
1180
|
//calculate numerators: [D+E, D-E] -> [√2*b^(3/4)+√b∜ax, √2*b^(3/4)-√b∜ax]
|
|
1135
|
-
D = _.parse(SQRT+br(2)+'*'+br(b)+'^'+br('3/4'));
|
|
1136
|
-
E = _.parse(SQRT+br(b)+'*'+br(b)+'^'+br('1/4')+'*'+dx);
|
|
1181
|
+
D = _.parse(SQRT + br(2) + '*' + br(b) + '^' + br('3/4'));
|
|
1182
|
+
E = _.parse(SQRT + br(b) + '*' + br(b) + '^' + br('1/4') + '*' + dx);
|
|
1137
1183
|
//let F = 2b√2∜b
|
|
1138
|
-
F = _.parse(2+'*'+br(b)+'*'+SQRT+br(2)+'*'+br(b)+'^'+br('1/4'));
|
|
1184
|
+
F = _.parse(2 + '*' + br(b) + '*' + SQRT + br(2) + '*' + br(b) + '^' + br('1/4'));
|
|
1139
1185
|
//calculate the factors
|
|
1140
1186
|
L1 = _.divide(_.subtract(D.clone(), E.clone()), _.multiply(F.clone(), f2));
|
|
1141
1187
|
L2 = _.divide(_.add(D, E), _.multiply(F, f1.clone()));
|
|
1142
1188
|
retval = _.add(
|
|
1143
|
-
|
|
1144
|
-
|
|
1189
|
+
__.integrate(L1, dx, depth, opt),
|
|
1190
|
+
__.integrate(L2, dx, depth, opt)
|
|
1145
1191
|
);
|
|
1146
1192
|
}
|
|
1147
1193
|
else
|
|
@@ -1149,7 +1195,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1149
1195
|
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1150
1196
|
}
|
|
1151
1197
|
}
|
|
1152
|
-
else if(p === -1/2) {
|
|
1198
|
+
else if(p === -1 / 2) {
|
|
1153
1199
|
//detect asin and atan
|
|
1154
1200
|
if(x.group === S && x.power.equals(2)) {
|
|
1155
1201
|
if(ax.multiplier.lessThan(0) && !b.multiplier.lessThan(0)) {
|
|
@@ -1157,13 +1203,13 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1157
1203
|
//it's asin
|
|
1158
1204
|
if(b.isConstant() && a.isConstant()) {
|
|
1159
1205
|
var d = _.symfunction(SQRT, [a.clone()]),
|
|
1160
|
-
|
|
1206
|
+
d2 = _.symfunction(SQRT, [_.multiply(a.clone(), b)]);
|
|
1161
1207
|
retval = _.divide(_.symfunction(ASIN, [_.divide(ax.toLinear(), d2)]), d);
|
|
1162
1208
|
}
|
|
1163
1209
|
//I'm not sure about this one. I'm trusting Wolfram Alpha here
|
|
1164
1210
|
else {
|
|
1165
1211
|
var sqrt_a = _.symfunction(SQRT, [a]),
|
|
1166
|
-
|
|
1212
|
+
sqrt_ax = _.multiply(sqrt_a.clone(), x.clone().toLinear());
|
|
1167
1213
|
retval = _.divide(_.symfunction(ATAN, [_.divide(sqrt_ax, _.symfunction(SQRT, [fn.clone()]))]), sqrt_a);
|
|
1168
1214
|
}
|
|
1169
1215
|
}
|
|
@@ -1177,38 +1223,42 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1177
1223
|
__.integration.stop();
|
|
1178
1224
|
}
|
|
1179
1225
|
}
|
|
1180
|
-
else {
|
|
1181
|
-
|
|
1226
|
+
else if(p === 1/2 && x.power.equals(2) && a.greaterThan(0)) {
|
|
1227
|
+
// TODO: Revisit
|
|
1228
|
+
__.integration.stop();
|
|
1229
|
+
}
|
|
1230
|
+
else {
|
|
1231
|
+
if(x.isLinear() && x.group !== PL)
|
|
1182
1232
|
retval = _.divide(__.integration.poly_integrate(symbol), a);
|
|
1183
|
-
else if(x.power.equals(2) && a.greaterThan(0)) {
|
|
1233
|
+
else if(x.power.equals(2) && a.greaterThan(0)) {
|
|
1184
1234
|
var sqa, sqb, aob, bsqi, n, integral, u, v, uv;
|
|
1185
1235
|
//1/(a*x^2+b^2)^n
|
|
1186
1236
|
//strip the value of b so b = 1
|
|
1187
|
-
sqa = _.parse(SQRT+inBrackets(a)); //strip a so b = 1
|
|
1188
|
-
sqb = _.parse(SQRT+inBrackets(b));
|
|
1237
|
+
sqa = _.parse(SQRT + inBrackets(a)); //strip a so b = 1
|
|
1238
|
+
sqb = _.parse(SQRT + inBrackets(b));
|
|
1189
1239
|
aob = _.multiply(sqa.clone(), sqb.clone()).invert();
|
|
1190
1240
|
bsqi = _.pow(b, new Symbol(symbol.power));
|
|
1191
1241
|
uv = core.Utils.getU(symbol);
|
|
1192
1242
|
u = _.multiply(aob, x.clone().toLinear());
|
|
1193
|
-
v = _.parse(ATAN+inBrackets(u));
|
|
1243
|
+
v = _.parse(ATAN + inBrackets(u));
|
|
1194
1244
|
//the conversion will be 1+tan(x)^2 -> sec(x)^2
|
|
1195
1245
|
//since the denominator is now (sec(x)^2)^n and the numerator is sec(x)^2
|
|
1196
1246
|
//then the remaining sec will be (n-1)*2;
|
|
1197
|
-
var n = (Math.abs(symbol.power)-1)*2;
|
|
1247
|
+
var n = (Math.abs(symbol.power) - 1) * 2;
|
|
1198
1248
|
//1/sec(x)^n can now be converted to cos(x)^n and we can pull the integral of that
|
|
1199
|
-
var integral = __.integrate(_.parse(COS+inBrackets(uv)+'^'+n));
|
|
1249
|
+
var integral = __.integrate(_.parse(COS + inBrackets(uv) + '^' + n));
|
|
1200
1250
|
core.Utils.clearU(uv);
|
|
1201
1251
|
return _.multiply(integral.sub(uv, v), bsqi);
|
|
1202
1252
|
}
|
|
1203
|
-
else {
|
|
1253
|
+
else {
|
|
1204
1254
|
if(symbol.group !== CB && !symbol.power.lessThan(0)) {
|
|
1205
1255
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1206
1256
|
}
|
|
1207
|
-
else {
|
|
1257
|
+
else {
|
|
1208
1258
|
var f = symbol.clone().toLinear();
|
|
1209
1259
|
var factored = core.Algebra.Factor.factor(f);
|
|
1210
1260
|
var was_factored = factored.toString() !== f.toString();
|
|
1211
|
-
if(core.Algebra.degree(f, _.parse(dx)).equals(2) && !was_factored) {
|
|
1261
|
+
if(core.Algebra.degree(f, _.parse(dx)).equals(2) && !was_factored) {
|
|
1212
1262
|
try {
|
|
1213
1263
|
var f1, fx, u, sq;
|
|
1214
1264
|
sq = core.Algebra.sqComplete(f, dx);
|
|
@@ -1229,43 +1279,43 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1229
1279
|
retval.multiplier = retval.multiplier.multiply(m);
|
|
1230
1280
|
}
|
|
1231
1281
|
}
|
|
1232
|
-
else if(g === FN) {
|
|
1282
|
+
else if(g === FN) {
|
|
1233
1283
|
var arg = symbol.args[0],
|
|
1234
|
-
|
|
1284
|
+
m = symbol.multiplier.clone();
|
|
1235
1285
|
symbol.toUnitMultiplier();
|
|
1236
1286
|
var decomp = __.integration.decompose_arg(arg, dx);
|
|
1237
1287
|
//easies way I can think of to get the coefficient and to make sure
|
|
1238
1288
|
//that the symbol is linear wrt dx. I'm not actually trying to get the
|
|
1239
1289
|
//derivative
|
|
1240
1290
|
var a = decomp[0],
|
|
1241
|
-
|
|
1242
|
-
|
|
1291
|
+
x = decomp[1],
|
|
1292
|
+
fname = symbol.fname;
|
|
1243
1293
|
//log is a special case that can be handled with integration by parts
|
|
1244
|
-
if(fname === LOG || (fname === ASIN || fname === ACOS || fname === ATAN && x.isLinear())) {
|
|
1294
|
+
if(fname === LOG || (fname === ASIN || fname === ACOS || fname === ATAN && x.isLinear())) {
|
|
1245
1295
|
/*integration by parts */
|
|
1246
|
-
var p = symbol.power.toString();
|
|
1296
|
+
var p = symbol.power.toString();
|
|
1247
1297
|
if(isInt(p))
|
|
1248
1298
|
depth = depth - p; //it needs more room to find the integral
|
|
1249
|
-
|
|
1299
|
+
|
|
1250
1300
|
if(!arg.isComposite())
|
|
1251
|
-
retval = _.multiply(_.parse(m),__.integration.by_parts(symbol, dx, depth, opt));
|
|
1301
|
+
retval = _.multiply(_.parse(m), __.integration.by_parts(symbol, dx, depth, opt));
|
|
1252
1302
|
else {
|
|
1253
1303
|
//integral u du
|
|
1254
1304
|
var u = core.Utils.getU(symbol);
|
|
1255
|
-
var f = _.pow(_.parse(LOG+inBrackets(u)),new Symbol(p));
|
|
1305
|
+
var f = _.pow(_.parse(LOG + inBrackets(u)), new Symbol(p));
|
|
1256
1306
|
var du = __.diff(arg, dx);
|
|
1257
1307
|
var u_du = _.multiply(f, du);
|
|
1258
1308
|
var integral = __.integrate(u_du, u, depth, opt);
|
|
1259
|
-
retval = _.multiply(_.parse(m),integral.sub(u, arg));
|
|
1309
|
+
retval = _.multiply(_.parse(m), integral.sub(u, arg));
|
|
1260
1310
|
}
|
|
1261
1311
|
|
|
1262
1312
|
}
|
|
1263
1313
|
else if(fname === TAN && symbol.power.lessThan(0)) {
|
|
1264
1314
|
//convert to cotangent
|
|
1265
|
-
var sym
|
|
1315
|
+
var sym = symbol.clone();
|
|
1266
1316
|
sym.power.negate();
|
|
1267
1317
|
sym.fname = COT;
|
|
1268
|
-
return _.multiply(_.parse(m),__.integrate(sym, dx, depth));
|
|
1318
|
+
return _.multiply(_.parse(m), __.integrate(sym, dx, depth));
|
|
1269
1319
|
}
|
|
1270
1320
|
else {
|
|
1271
1321
|
if(!a.contains(dx, true) && symbol.isLinear()) { //perform a deep search for safety
|
|
@@ -1283,13 +1333,13 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1283
1333
|
retval = _.multiply(_.multiply(_.symfunction(ABS, [x.toLinear()]), integrated), a);
|
|
1284
1334
|
}
|
|
1285
1335
|
}
|
|
1286
|
-
else
|
|
1336
|
+
else
|
|
1287
1337
|
__.integration.stop();
|
|
1288
1338
|
}
|
|
1289
|
-
else {
|
|
1339
|
+
else {
|
|
1290
1340
|
var ag = symbol.args[0].group,
|
|
1291
|
-
|
|
1292
|
-
|
|
1341
|
+
decomposed = __.integration.decompose_arg(arg, dx);
|
|
1342
|
+
|
|
1293
1343
|
if(!(ag === CP || ag === S || ag === CB) || !decomposed[1].power.equals(1) || arg.hasFunc())
|
|
1294
1344
|
__.integration.stop();
|
|
1295
1345
|
/**TODO**/ //ASIN, ACOS, ATAN
|
|
@@ -1302,16 +1352,16 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1302
1352
|
retval.negate();
|
|
1303
1353
|
break;
|
|
1304
1354
|
case TAN:
|
|
1305
|
-
retval = _.parse(format(Settings.LOG+'(sec({0}))', arg));
|
|
1355
|
+
retval = _.parse(format(Settings.LOG + '(sec({0}))', arg));
|
|
1306
1356
|
break;
|
|
1307
1357
|
case SEC:
|
|
1308
|
-
retval = _.parse(format(Settings.LOG+'(tan({0})+sec({0}))', arg));
|
|
1358
|
+
retval = _.parse(format(Settings.LOG + '(tan({0})+sec({0}))', arg));
|
|
1309
1359
|
break;
|
|
1310
1360
|
case CSC:
|
|
1311
|
-
retval = _.parse(format('-'+Settings.LOG+'(csc({0})+cot({0}))', arg));
|
|
1361
|
+
retval = _.parse(format('-' + Settings.LOG + '(csc({0})+cot({0}))', arg));
|
|
1312
1362
|
break;
|
|
1313
1363
|
case COT:
|
|
1314
|
-
retval = _.parse(format(Settings.LOG+'(sin({0}))', arg));
|
|
1364
|
+
retval = _.parse(format(Settings.LOG + '(sin({0}))', arg));
|
|
1315
1365
|
break;
|
|
1316
1366
|
case SINH:
|
|
1317
1367
|
retval = _.symfunction(COSH, [arg]);
|
|
@@ -1320,7 +1370,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1320
1370
|
retval = _.symfunction(SINH, [arg]);
|
|
1321
1371
|
break;
|
|
1322
1372
|
case TANH:
|
|
1323
|
-
retval = _.parse(format(Settings.LOG+'(cosh({0}))', arg));
|
|
1373
|
+
retval = _.parse(format(Settings.LOG + '(cosh({0}))', arg));
|
|
1324
1374
|
break;
|
|
1325
1375
|
case ASEC:
|
|
1326
1376
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
@@ -1331,7 +1381,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1331
1381
|
case ACOT:
|
|
1332
1382
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1333
1383
|
break;
|
|
1334
|
-
|
|
1384
|
+
//inverse htrig
|
|
1335
1385
|
case ASECH:
|
|
1336
1386
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1337
1387
|
break;
|
|
@@ -1341,42 +1391,42 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1341
1391
|
case ACOTH:
|
|
1342
1392
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1343
1393
|
break;
|
|
1344
|
-
|
|
1345
|
-
|
|
1394
|
+
//end inverse htrig
|
|
1395
|
+
//htrigh
|
|
1346
1396
|
case SECH:
|
|
1347
1397
|
retval = _.parse(format('atan(sinh({0}))', arg));
|
|
1348
1398
|
break;
|
|
1349
1399
|
case CSCH:
|
|
1350
|
-
retval = _.parse(format(Settings.LOG+'(tanh(({0})/2))', arg));
|
|
1400
|
+
retval = _.parse(format(Settings.LOG + '(tanh(({0})/2))', arg));
|
|
1351
1401
|
break;
|
|
1352
1402
|
case COTH:
|
|
1353
|
-
retval = _.parse(format(Settings.LOG+'(sinh({0}))', arg));
|
|
1403
|
+
retval = _.parse(format(Settings.LOG + '(sinh({0}))', arg));
|
|
1354
1404
|
break;
|
|
1355
|
-
|
|
1405
|
+
//end htrig
|
|
1356
1406
|
case EXP:
|
|
1357
1407
|
retval = __.integrate(_.parse(format('e^({0})', arg)), dx, depth);
|
|
1358
1408
|
break;
|
|
1359
1409
|
case 'S':
|
|
1360
1410
|
var arg = symbol.args[0].clone(),
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1411
|
+
dc = __.integration.decompose_arg(arg, dx),
|
|
1412
|
+
x_ = dc[1],
|
|
1413
|
+
a_ = dc[0];
|
|
1364
1414
|
var b_ = dc[3];
|
|
1365
1415
|
retval = _.parse(format('(cos((1/2)*pi*(({1})+({0})*({2}))^2)+pi*(({1})+({0})*({2}))*S(({1})+({0})*({2})))/(({0})*pi)', a_, b_, x));
|
|
1366
1416
|
break;
|
|
1367
1417
|
case 'C':
|
|
1368
1418
|
var arg = symbol.args[0].clone(),
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1419
|
+
dc = __.integration.decompose_arg(arg, dx),
|
|
1420
|
+
x_ = dc[1],
|
|
1421
|
+
a_ = dc[0];
|
|
1372
1422
|
var b_ = dc[3];
|
|
1373
1423
|
retval = _.parse(format('(pi*(({1})+({0})*({2}))*C(({1})+({0})*({2}))-sin((1/2)*pi*(({1})+({0})*({2}))^2))/(({0})*pi)', a_, b_, x_));
|
|
1374
1424
|
break;
|
|
1375
1425
|
case 'erf':
|
|
1376
1426
|
var arg = symbol.args[0].clone(),
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1427
|
+
dc = __.integration.decompose_arg(arg, dx),
|
|
1428
|
+
x_ = dc[1],
|
|
1429
|
+
a_ = dc[0];
|
|
1380
1430
|
retval = _.parse(format('e^(-(({2}))^2)/(({0})*sqrt(pi))+(1/({0})+({1}))*erf(({2}))', a_, x_, arg));
|
|
1381
1431
|
break;
|
|
1382
1432
|
case 'sign':
|
|
@@ -1386,10 +1436,10 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1386
1436
|
__.integration.stop();
|
|
1387
1437
|
}
|
|
1388
1438
|
|
|
1389
|
-
retval = _.divide(retval, a);
|
|
1439
|
+
retval = _.divide(retval, a);
|
|
1390
1440
|
}
|
|
1391
1441
|
}
|
|
1392
|
-
else if(x.isLinear()) {
|
|
1442
|
+
else if(x.isLinear()) {
|
|
1393
1443
|
if(fname === COS || fname === SIN) {
|
|
1394
1444
|
var p = Number(symbol.power);
|
|
1395
1445
|
//check to see if it's negative and then just transform it to sec or csc
|
|
@@ -1400,44 +1450,45 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1400
1450
|
}
|
|
1401
1451
|
else {
|
|
1402
1452
|
var arg = symbol.args[0],
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1453
|
+
rd = symbol.clone(), //cos^(n-1)
|
|
1454
|
+
rd2 = symbol.clone(), //cos^(n-2)
|
|
1455
|
+
q = new Symbol((p - 1) / p), //
|
|
1456
|
+
na = _.multiply(a.clone(), new Symbol(p)).invert(); //1/(n*a)
|
|
1407
1457
|
rd.power = rd.power.subtract(new Frac(1));
|
|
1408
1458
|
rd2.power = rd2.power.subtract(new Frac(2));
|
|
1409
1459
|
|
|
1410
1460
|
var t = _.symfunction(fname === COS ? SIN : COS, [arg.clone()]);
|
|
1411
|
-
if(fname === SIN)
|
|
1461
|
+
if(fname === SIN)
|
|
1462
|
+
t.negate();
|
|
1412
1463
|
retval = _.add(_.multiply(_.multiply(na, rd), t), _.multiply(q, __.integrate(_.parse(rd2), dx, depth)));
|
|
1413
1464
|
}
|
|
1414
1465
|
}
|
|
1415
1466
|
//tan(x)^n or cot(x)^n
|
|
1416
|
-
else if(fname === TAN || fname === COT) {
|
|
1467
|
+
else if(fname === TAN || fname === COT) {
|
|
1417
1468
|
//http://www.sosmath.com/calculus/integration/moretrigpower/moretrigpower.html
|
|
1418
1469
|
if(symbol.args[0].isLinear(dx)) {
|
|
1419
1470
|
var n = symbol.power.subtract(new Frac(1)).toString(),
|
|
1420
|
-
|
|
1421
|
-
|
|
1471
|
+
r = symbol.clone().toUnitMultiplier(),
|
|
1472
|
+
w = _.parse(format((fname === COT ? '-' : '') + '1/({2}*{0})*{3}({1})^({0})', n, arg, a, fname));
|
|
1422
1473
|
r.power = r.power.subtract(new Frac(2));
|
|
1423
1474
|
if(r.power.equals(0))
|
|
1424
1475
|
r = _.parse(r);
|
|
1425
1476
|
retval = _.subtract(w, __.integrate(r, dx, depth));
|
|
1426
|
-
}
|
|
1477
|
+
}
|
|
1427
1478
|
}
|
|
1428
1479
|
//sec(x)^n or csc(x)^n
|
|
1429
|
-
else if(fname === SEC || fname === CSC) {
|
|
1480
|
+
else if(fname === SEC || fname === CSC) {
|
|
1430
1481
|
//http://www.sosmath.com/calculus/integration/moretrigpower/moretrigpower.html
|
|
1431
1482
|
var n1 = symbol.power.subtract(new Frac(1)).toString(),
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1483
|
+
n2 = symbol.power.subtract(new Frac(2)).toString(),
|
|
1484
|
+
f2 = fname === SEC ? TAN : COT,
|
|
1485
|
+
r = symbol.clone().toUnitMultiplier(),
|
|
1486
|
+
parse_str = format((fname === CSC ? '-' : '') + '1/({0}*{1})*{4}({3})^({2})*{5}({3})', a, n1, n2, arg, fname, f2),
|
|
1487
|
+
w = _.parse(parse_str);
|
|
1437
1488
|
r.power = r.power.subtract(new Frac(2));
|
|
1438
1489
|
if(r.power.equals(0))
|
|
1439
1490
|
r = _.parse(r);
|
|
1440
|
-
retval = _.add(w, _.multiply(new Symbol(n2/n1), __.integrate(r, dx, depth)));
|
|
1491
|
+
retval = _.add(w, _.multiply(new Symbol(n2 / n1), __.integrate(r, dx, depth)));
|
|
1441
1492
|
}
|
|
1442
1493
|
else if((fname === COSH || fname === SINH) && symbol.power.equals(2)) {
|
|
1443
1494
|
retval = __.integrate(symbol.fnTransform(), dx, depth);
|
|
@@ -1445,7 +1496,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1445
1496
|
else
|
|
1446
1497
|
__.integration.stop();
|
|
1447
1498
|
}
|
|
1448
|
-
else
|
|
1499
|
+
else
|
|
1449
1500
|
__.integration.stop();
|
|
1450
1501
|
|
|
1451
1502
|
retval.multiplier = retval.multiplier.multiply(m);
|
|
@@ -1458,9 +1509,9 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1458
1509
|
var den = symbol.getDenom();
|
|
1459
1510
|
if(den.group === S)
|
|
1460
1511
|
symbol = _.expand(symbol);
|
|
1461
|
-
|
|
1512
|
+
|
|
1462
1513
|
//separate the coefficient since all we care about are symbols containing dx
|
|
1463
|
-
var coeff = symbol.stripVar(dx);
|
|
1514
|
+
var coeff = symbol.stripVar(dx);
|
|
1464
1515
|
//now get only those that apply
|
|
1465
1516
|
var cfsymbol = _.divide(symbol.clone(), coeff.clone()); //a coeff free symbol
|
|
1466
1517
|
//peform a correction for stripVar. This is a serious TODO!
|
|
@@ -1468,32 +1519,34 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1468
1519
|
cfsymbol = _.multiply(cfsymbol, coeff);
|
|
1469
1520
|
coeff = new Symbol(1);
|
|
1470
1521
|
}
|
|
1471
|
-
|
|
1522
|
+
|
|
1472
1523
|
//if we only have one symbol left then let's not waste time. Just pull the integral
|
|
1473
1524
|
//and let the chips fall where they may
|
|
1474
1525
|
if(cfsymbol.group !== CB) {
|
|
1475
|
-
if(cfsymbol.equals(1)) {
|
|
1526
|
+
if(cfsymbol.equals(1)) {
|
|
1476
1527
|
return __.integrate(_.expand(symbol), dx, depth);
|
|
1477
1528
|
}
|
|
1478
|
-
|
|
1529
|
+
|
|
1479
1530
|
//only factor for multivariate which are polynomials
|
|
1480
1531
|
if(cfsymbol.clone().toLinear().isPoly(true) && core.Utils.variables(cfsymbol).length > 1) {
|
|
1481
1532
|
cfsymbol = core.Algebra.Factor.factor(cfsymbol);
|
|
1482
1533
|
}
|
|
1483
|
-
|
|
1534
|
+
|
|
1484
1535
|
retval = __.integrate(cfsymbol, dx, depth);
|
|
1485
1536
|
}
|
|
1486
|
-
else {
|
|
1537
|
+
else {
|
|
1487
1538
|
//we collect the symbols and sort them descending group, descending power, descending alpabethically
|
|
1488
|
-
var symbols = cfsymbol.collectSymbols().sort(function(a, b) {
|
|
1489
|
-
if(a.group === b.group)
|
|
1539
|
+
var symbols = cfsymbol.collectSymbols().sort(function (a, b) {
|
|
1540
|
+
if(a.group === b.group) {
|
|
1490
1541
|
if(Number(a.power) === Number(b.power))
|
|
1491
|
-
if(a < b)
|
|
1492
|
-
|
|
1542
|
+
if(a < b)
|
|
1543
|
+
return 1; //I want sin first
|
|
1544
|
+
else
|
|
1545
|
+
return -1;
|
|
1493
1546
|
return b.power - a.power; //descending power
|
|
1494
1547
|
}
|
|
1495
1548
|
return b.group - a.group; //descending groups
|
|
1496
|
-
}).map(function(x) {
|
|
1549
|
+
}).map(function (x) {
|
|
1497
1550
|
var unwrapped = Symbol.unwrapSQRT(x, true);
|
|
1498
1551
|
if(unwrapped.fname === EXP) {
|
|
1499
1552
|
return _.parse(format('({1})*e^({0})', unwrapped.args[0], unwrapped.multiplier));
|
|
@@ -1501,7 +1554,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1501
1554
|
return unwrapped;
|
|
1502
1555
|
});
|
|
1503
1556
|
var l = symbols.length;
|
|
1504
|
-
if(symbol.power < 0) {
|
|
1557
|
+
if(symbol.power < 0) {
|
|
1505
1558
|
if(l === 2) {
|
|
1506
1559
|
return __.integrate(_.expand(symbol), dx, depth, opt);
|
|
1507
1560
|
}
|
|
@@ -1514,25 +1567,27 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1514
1567
|
try {
|
|
1515
1568
|
retval = __.integration.u_substitution(symbols, dx);
|
|
1516
1569
|
}
|
|
1517
|
-
catch(e){/* failed :`(
|
|
1570
|
+
catch(e) {/* failed :`(*/
|
|
1571
|
+
;
|
|
1572
|
+
}
|
|
1518
1573
|
|
|
1519
|
-
if(!retval) {
|
|
1574
|
+
if(!retval) {
|
|
1520
1575
|
//no success with u substitution so let's try known combinations
|
|
1521
1576
|
//are they two functions
|
|
1522
1577
|
var g1 = symbols[0].group,
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1578
|
+
g2 = symbols[1].group,
|
|
1579
|
+
sym1 = symbols[0],
|
|
1580
|
+
sym2 = symbols[1],
|
|
1581
|
+
fn1 = sym1.fname,
|
|
1582
|
+
fn2 = sym2.fname;
|
|
1528
1583
|
//reset the symbol minus the coeff
|
|
1529
1584
|
symbol = _.multiply(sym1.clone(), sym2.clone());
|
|
1530
|
-
if(g1 === FN && g2 === FN) {
|
|
1531
|
-
if(fn1 === LOG || fn2 === LOG) {
|
|
1585
|
+
if(g1 === FN && g2 === FN) {
|
|
1586
|
+
if(fn1 === LOG || fn2 === LOG) {
|
|
1532
1587
|
retval = __.integration.by_parts(symbol.clone(), dx, depth, opt);
|
|
1533
1588
|
}
|
|
1534
|
-
else {
|
|
1535
|
-
symbols.sort(function(a, b) {
|
|
1589
|
+
else {
|
|
1590
|
+
symbols.sort(function (a, b) {
|
|
1536
1591
|
return b.fname > a.fname;
|
|
1537
1592
|
});
|
|
1538
1593
|
var arg1 = sym1.args[0];
|
|
@@ -1542,7 +1597,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1542
1597
|
|
|
1543
1598
|
var decomp = __.integration.decompose_arg(arg1, dx);
|
|
1544
1599
|
x = decomp[1],
|
|
1545
|
-
|
|
1600
|
+
a = decomp[0];
|
|
1546
1601
|
if(!x.isLinear()) //again... linear arguments only wrt x
|
|
1547
1602
|
__.integration.stop();
|
|
1548
1603
|
|
|
@@ -1550,12 +1605,12 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1550
1605
|
//make sure we can integrate FN & FN
|
|
1551
1606
|
var arg2 = sym2.args[0];
|
|
1552
1607
|
//make sure that their argument matches
|
|
1553
|
-
if(arg1.equals(arg2)) {
|
|
1554
|
-
if(fn1 === SIN && fn2 === COS || fn1 === COS && fn2 === SIN) {
|
|
1608
|
+
if(arg1.equals(arg2)) {
|
|
1609
|
+
if(fn1 === SIN && fn2 === COS || fn1 === COS && fn2 === SIN) {
|
|
1555
1610
|
if(sym1.power.lessThan(0))
|
|
1556
1611
|
__.integration.stop();//we don't know how to handle, sin(x)^n/cos(x)^m where m > n, yet
|
|
1557
1612
|
//if it's in the form sin(x)^n*cos(x)^n then we can just return tan(x)^n which we know how to integrate
|
|
1558
|
-
if(fn1 === SIN && sym1.power.add(sym2.power).equals(0)) {
|
|
1613
|
+
if(fn1 === SIN && sym1.power.add(sym2.power).equals(0)) {
|
|
1559
1614
|
sym1.fname = TAN;
|
|
1560
1615
|
sym1.updateHash();
|
|
1561
1616
|
retval = __.integrate(sym1, dx, depth);
|
|
@@ -1563,64 +1618,66 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1563
1618
|
else {
|
|
1564
1619
|
if(even(sym1.power) && fn2 === COS && sym2.power.lessThan(0)) {
|
|
1565
1620
|
//transform sin^(2*n) to (1-cos^2)^n
|
|
1566
|
-
var n = Number(sym1.power)/2,
|
|
1567
|
-
|
|
1621
|
+
var n = Number(sym1.power) / 2,
|
|
1622
|
+
new_sym = _.parse(format('(1-cos({0})^2)^({1})', sym1.args[0], n));
|
|
1568
1623
|
retval = __.integrate(_.expand(_.multiply(new_sym, sym2.clone())), dx, depth, opt);
|
|
1569
1624
|
}
|
|
1570
1625
|
else if(even(sym1.power) && fn2 === SIN && sym2.power.lessThan(0)) {
|
|
1571
1626
|
//transform cos^(2*n) to (1-sin^2)^n
|
|
1572
|
-
var n = Number(sym1.power)/2,
|
|
1573
|
-
|
|
1627
|
+
var n = Number(sym1.power) / 2,
|
|
1628
|
+
new_sym = _.parse(format('(1-sin({0})^2)^({1})', sym1.args[0], n));
|
|
1574
1629
|
retval = __.integrate(_.expand(_.multiply(new_sym, sym2.clone())), dx, depth, opt);
|
|
1575
1630
|
}
|
|
1576
1631
|
else {
|
|
1577
1632
|
var p1_even = core.Utils.even(sym1.power),
|
|
1578
|
-
|
|
1633
|
+
p2_even = core.Utils.even(sym2.power);
|
|
1579
1634
|
retval = new Symbol(0);
|
|
1580
|
-
if(!p1_even || !p2_even) {
|
|
1635
|
+
if(!p1_even || !p2_even) {
|
|
1581
1636
|
var u, r, trans;
|
|
1582
1637
|
//since cos(x) is odd it carries du. If sin was odd then it would be the other way around
|
|
1583
1638
|
//know that p1 satifies the odd portion in this case. If p2 did than it would contain r
|
|
1584
1639
|
if(!p1_even) {
|
|
1585
1640
|
//u = sin(x)
|
|
1586
|
-
u = sym2;
|
|
1641
|
+
u = sym2;
|
|
1642
|
+
r = sym1;
|
|
1587
1643
|
}
|
|
1588
1644
|
else {
|
|
1589
|
-
u = sym1;
|
|
1645
|
+
u = sym1;
|
|
1646
|
+
r = sym2;
|
|
1590
1647
|
}
|
|
1591
1648
|
//get the sign of du. In this case r carries du as stated before and D(cos(x),x) = -sin(x)
|
|
1592
1649
|
var sign = u.fname === COS ? -1 : 1,
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1650
|
+
n = r.power,
|
|
1651
|
+
//remove the du e.g. cos(x)^2*sin(x)^3 dx -> cos(x)^2*sin(x)^2*sin(x). We're left with two
|
|
1652
|
+
//even powers afterwards which can be transformed
|
|
1653
|
+
k = (n - 1) / 2,
|
|
1654
|
+
//make the transformation cos(x)^2 = 1 - sin(x)^2
|
|
1655
|
+
trans = _.parse('(1-' + u.fname + core.Utils.inBrackets(arg1) + '^2)^' + k),
|
|
1656
|
+
sym = _.expand(_.multiply(new Symbol(sign), _.multiply(u.clone(), trans)));
|
|
1600
1657
|
//we can now just loop through and integrate each since it's now just a polynomial with functions
|
|
1601
|
-
sym.each(function(x) {
|
|
1658
|
+
sym.each(function (x) {
|
|
1602
1659
|
retval = _.add(retval, __.integration.poly_integrate(x.clone()));
|
|
1603
1660
|
});
|
|
1604
1661
|
}
|
|
1605
|
-
else {
|
|
1662
|
+
else {
|
|
1606
1663
|
//performs double angle transformation
|
|
1607
|
-
var double_angle = function(symbol) {
|
|
1664
|
+
var double_angle = function (symbol) {
|
|
1608
1665
|
var p = symbol.power,
|
|
1609
|
-
|
|
1666
|
+
k = p / 2, e;
|
|
1610
1667
|
if(symbol.fname === COS)
|
|
1611
|
-
e = '((1/2)+(cos(2*('+symbol.args[0]+'))/2))^'+k;
|
|
1668
|
+
e = '((1/2)+(cos(2*(' + symbol.args[0] + '))/2))^' + k;
|
|
1612
1669
|
else
|
|
1613
|
-
e = '((1/2)-(cos(2*('+symbol.args[0]+'))/2))^'+k;
|
|
1670
|
+
e = '((1/2)-(cos(2*(' + symbol.args[0] + '))/2))^' + k;
|
|
1614
1671
|
|
|
1615
1672
|
return _.parse(e);
|
|
1616
1673
|
};
|
|
1617
1674
|
//they're both even so transform both using double angle identities and we'll just
|
|
1618
1675
|
//be able to integrate by the sum of integrals
|
|
1619
1676
|
var a = double_angle(sym1),
|
|
1620
|
-
|
|
1621
|
-
|
|
1677
|
+
b = double_angle(sym2),
|
|
1678
|
+
t = _.multiply(a, b);
|
|
1622
1679
|
var sym = _.expand(t);
|
|
1623
|
-
sym.each(function(x) {
|
|
1680
|
+
sym.each(function (x) {
|
|
1624
1681
|
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
1625
1682
|
});
|
|
1626
1683
|
return _.multiply(retval, coeff);
|
|
@@ -1629,16 +1686,16 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1629
1686
|
}
|
|
1630
1687
|
}
|
|
1631
1688
|
//tan(x)*sec(x)^n
|
|
1632
|
-
else if(fn1 === SEC && fn2 === TAN && x.isLinear() && sym2.isLinear()) {
|
|
1689
|
+
else if(fn1 === SEC && fn2 === TAN && x.isLinear() && sym2.isLinear()) {
|
|
1633
1690
|
retval = _.parse(format('sec({0})^({1})/({1})', sym1.args[0], sym1.power));
|
|
1634
1691
|
}
|
|
1635
|
-
else if(fn1 === TAN && fn2 === SEC && x.isLinear()) {
|
|
1692
|
+
else if(fn1 === TAN && fn2 === SEC && x.isLinear()) {
|
|
1636
1693
|
//remaining: tan(x)^3*sec(x)^6
|
|
1637
1694
|
if(sym1.isLinear() && sym2.isLinear()) {
|
|
1638
1695
|
retval = _.divide(_.symfunction(SEC, [arg1.clone()]), a);
|
|
1639
1696
|
}
|
|
1640
1697
|
else if(even(sym1.power)) {
|
|
1641
|
-
var p = Number(sym1.power)/2;
|
|
1698
|
+
var p = Number(sym1.power) / 2;
|
|
1642
1699
|
//transform tangent
|
|
1643
1700
|
var t = _.parse(format('(sec({0})^2-1)^({1})', sym1.args[0], p));
|
|
1644
1701
|
retval = __.integrate(_.expand(_.multiply(t, sym2)), dx, depth);
|
|
@@ -1661,14 +1718,14 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1661
1718
|
var t = _.multiply(sym1.fnTransform(), sym2);
|
|
1662
1719
|
retval = __.integrate(_.expand(t), dx, depth);
|
|
1663
1720
|
}
|
|
1664
|
-
else {
|
|
1721
|
+
else {
|
|
1665
1722
|
var t = _.multiply(sym1.fnTransform(), sym2.fnTransform());
|
|
1666
1723
|
retval = __.integrate(_.expand(t), dx, depth);
|
|
1667
1724
|
}
|
|
1668
1725
|
}
|
|
1669
1726
|
//TODO: In progress
|
|
1670
1727
|
else if((fn1 === SIN || fn1 === COS) && (fn2 === SIN || fn2 === COS)) {
|
|
1671
|
-
|
|
1728
|
+
|
|
1672
1729
|
if(sym1.isLinear() && sym2.isLinear()) {
|
|
1673
1730
|
//if in the form cos(a*x)*sin(b*x)
|
|
1674
1731
|
if(sym1.args[0].isLinear() && sym2.args[0].isLinear()) {
|
|
@@ -1682,7 +1739,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1682
1739
|
bx = sym1.args[0];
|
|
1683
1740
|
ax = sym2.args[0];
|
|
1684
1741
|
}
|
|
1685
|
-
|
|
1742
|
+
|
|
1686
1743
|
//make the transformation
|
|
1687
1744
|
f = _.parse(format('(sin(({1})+({0}))+sin(({1})-({0})))/2', ax.toString(), bx.toString()));
|
|
1688
1745
|
|
|
@@ -1696,7 +1753,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1696
1753
|
}
|
|
1697
1754
|
else {
|
|
1698
1755
|
var transformed = new Symbol(1);
|
|
1699
|
-
symbols.map(function(sym) {
|
|
1756
|
+
symbols.map(function (sym) {
|
|
1700
1757
|
var s = sym.fnTransform();
|
|
1701
1758
|
transformed = _.multiply(transformed, s);
|
|
1702
1759
|
});
|
|
@@ -1715,9 +1772,9 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1715
1772
|
|
|
1716
1773
|
}
|
|
1717
1774
|
}
|
|
1718
|
-
else if(g1 === FN && g2 === S) {
|
|
1775
|
+
else if(g1 === FN && g2 === S) {
|
|
1719
1776
|
var sym1_is_linear = sym1.isLinear();
|
|
1720
|
-
if(sym1.fname === COS && sym1_is_linear && sym2.power.equals(-1))
|
|
1777
|
+
if(sym1.fname === COS && sym1_is_linear && sym2.power.equals(-1))
|
|
1721
1778
|
retval = _.symfunction('Ci', [sym1.args[0]]);
|
|
1722
1779
|
else if(sym1.fname === COS && sym2.power.equals(-1)) {
|
|
1723
1780
|
retval = __.integrate(_.multiply(sym1.fnTransform(), sym2.clone()), dx, depth);
|
|
@@ -1744,18 +1801,18 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1744
1801
|
else if(sym1.fname === 'erf') {
|
|
1745
1802
|
if(sym2.power.equals(1)) {
|
|
1746
1803
|
var dc = __.integration.decompose_arg(sym1.args[0], dx),
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1804
|
+
a_ = dc[0],
|
|
1805
|
+
x_ = dc[1],
|
|
1806
|
+
arg = sym1.args[0].toString();
|
|
1750
1807
|
retval = _.parse(format('(e^(-(({2}))^2)*(sqrt(pi)*e^((({2}))^2)*(2*({0})^2*({1})^2-3)*erf(({2}))+2*({0})*({1})-2))/(4*sqrt(pi)*({0})^2)', a_, x_, arg))
|
|
1751
1808
|
}
|
|
1752
1809
|
}
|
|
1753
|
-
else {
|
|
1810
|
+
else {
|
|
1754
1811
|
//since group S is guaranteed convergence we need not worry about tracking depth of integration
|
|
1755
1812
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1756
1813
|
}
|
|
1757
1814
|
}
|
|
1758
|
-
else if(g1 === EX && g2 === S) {
|
|
1815
|
+
else if(g1 === EX && g2 === S) {
|
|
1759
1816
|
var x = fn1 === LOG ? __.integration.decompose_arg(sym1.args[0], dx)[1] : null;
|
|
1760
1817
|
if(sym1.isE() && (sym1.power.group === S || sym1.power.group === CB) && sym2.power.equals(-1)) {
|
|
1761
1818
|
retval = _.symfunction('Ei', [sym1.power.clone()]);
|
|
@@ -1778,7 +1835,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1778
1835
|
factor.power = new Frac(pc);
|
|
1779
1836
|
sym2 = _.divide(sym2, factor.clone()); //reduce the denominator
|
|
1780
1837
|
var t = new Symbol(0);
|
|
1781
|
-
sym1.each(function(x) {
|
|
1838
|
+
sym1.each(function (x) {
|
|
1782
1839
|
t = _.add(t, _.divide(x.clone(), factor.clone()));
|
|
1783
1840
|
});
|
|
1784
1841
|
t.multiplier = sym1.multiplier;
|
|
@@ -1789,31 +1846,31 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1789
1846
|
}
|
|
1790
1847
|
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1791
1848
|
}
|
|
1792
|
-
else if(g1 === CP && g2 === S) {
|
|
1849
|
+
else if(g1 === CP && g2 === S) {
|
|
1793
1850
|
var f = sym1.clone().toLinear(),
|
|
1794
|
-
|
|
1851
|
+
f_is_linear = core.Algebra.degree(f, _.parse(dx)).equals(1);
|
|
1795
1852
|
//handle cases x^(2*n)/sqrt(1-x^2)
|
|
1796
|
-
if(sym1.power.equals(-1/2)) {
|
|
1853
|
+
if(sym1.power.equals(-1 / 2)) {
|
|
1797
1854
|
var decomp = __.integration.decompose_arg(sym1.clone().toLinear(), dx);
|
|
1798
1855
|
var a = decomp[0].negate(),
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1856
|
+
x = decomp[1],
|
|
1857
|
+
b = decomp[3],
|
|
1858
|
+
p1 = Number(sym1.power),
|
|
1859
|
+
p2 = Number(sym2.power);
|
|
1803
1860
|
if(isInt(p2) && core.Utils.even(p2) && x.power.equals(2)) {
|
|
1804
1861
|
//if the substitution
|
|
1805
|
-
var c = _.divide(_.multiply(_.pow(b.clone(), new Symbol(2)),
|
|
1806
|
-
|
|
1807
|
-
|
|
1862
|
+
var c = _.divide(_.multiply(_.pow(b.clone(), new Symbol(2)),
|
|
1863
|
+
_.symfunction(SQRT, [_.divide(b.clone(), a.clone())])),
|
|
1864
|
+
_.pow(a.clone(), new Symbol(2)));
|
|
1808
1865
|
c = _.multiply(c, _.symfunction(SQRT, [b]).invert());
|
|
1809
1866
|
var dummy = _.parse('sin(u)');
|
|
1810
1867
|
dummy.power = dummy.power.multiply(sym2.power);
|
|
1811
1868
|
var integral = __.integrate(dummy, 'u', depth);
|
|
1812
|
-
var bksub = _.parse(ASIN+'('+SQRT+'('+a+'/'+b+')*'+dx+')');
|
|
1869
|
+
var bksub = _.parse(ASIN + '(' + SQRT + '(' + a + '/' + b + ')*' + dx + ')');
|
|
1813
1870
|
retval = _.multiply(c, integral.sub(new Symbol('u'), bksub));
|
|
1814
|
-
}
|
|
1815
|
-
else if(p1 === -1/2) {
|
|
1816
|
-
var u_transform = function(f, u) {
|
|
1871
|
+
}
|
|
1872
|
+
else if(p1 === -1 / 2) {
|
|
1873
|
+
var u_transform = function (f, u) {
|
|
1817
1874
|
var integral = _.parse(__.integrate(f, dx, depth, opt).sub(dx, format(u, dx)));
|
|
1818
1875
|
if(!integral.hasIntegral())
|
|
1819
1876
|
return integral;
|
|
@@ -1822,58 +1879,58 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1822
1879
|
retval = u_transform(
|
|
1823
1880
|
_.expand(_.expand(_.pow(_.multiply(sym1.invert(), sym2.invert()), new Symbol(2)))).invert(),
|
|
1824
1881
|
'sqrt(1-1/({0})^2)'
|
|
1825
|
-
|
|
1882
|
+
);
|
|
1826
1883
|
}
|
|
1827
1884
|
else if(p2 === -2) {
|
|
1828
1885
|
//apply transformation to see if it matches asin(x)
|
|
1829
1886
|
retval = u_transform(
|
|
1830
1887
|
_.sqrt(_.expand(_.divide(_.pow(symbol, new Symbol(2)).invert(), _.pow(new Symbol(dx), new Symbol(2))).negate())).invert(),
|
|
1831
1888
|
'sqrt(1-1/({0})^2)'
|
|
1832
|
-
|
|
1889
|
+
);
|
|
1833
1890
|
}
|
|
1834
1891
|
}
|
|
1835
1892
|
}
|
|
1836
|
-
else if(sym1.power.equals(-1) && sym2.isLinear() && f_is_linear) {
|
|
1893
|
+
else if(sym1.power.equals(-1) && sym2.isLinear() && f_is_linear) {
|
|
1837
1894
|
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1838
1895
|
}
|
|
1839
|
-
else if(!sym1.power.lessThan(0) && isInt(sym1.power)) {
|
|
1896
|
+
else if(!sym1.power.lessThan(0) && isInt(sym1.power)) {
|
|
1840
1897
|
//sum of integrals
|
|
1841
1898
|
var expanded = _.expand(sym1);
|
|
1842
1899
|
retval = new Symbol(0);
|
|
1843
|
-
expanded.each(function(x) {
|
|
1900
|
+
expanded.each(function (x) {
|
|
1844
1901
|
if(x.group === PL) {
|
|
1845
|
-
x.each(function(y) {
|
|
1902
|
+
x.each(function (y) {
|
|
1846
1903
|
retval = _.add(retval, __.integrate(_.multiply(sym2.clone(), y), dx, depth));
|
|
1847
1904
|
});
|
|
1848
1905
|
}
|
|
1849
|
-
else
|
|
1906
|
+
else
|
|
1850
1907
|
retval = _.add(retval, __.integrate(_.multiply(sym2.clone(), x), dx, depth));
|
|
1851
1908
|
});
|
|
1852
1909
|
}
|
|
1853
|
-
else if(sym1.power.lessThan(-2)) {
|
|
1910
|
+
else if(sym1.power.lessThan(-2)) {
|
|
1854
1911
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1855
1912
|
}
|
|
1856
|
-
else if(sym1.power.lessThan(0) && sym2.power.greaterThan(1)) {
|
|
1913
|
+
else if(sym1.power.lessThan(0) && sym2.power.greaterThan(1)) {
|
|
1857
1914
|
var decomp = __.integration.decompose_arg(sym1.clone().toLinear(), dx),
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1915
|
+
a = decomp[0].negate(),
|
|
1916
|
+
x = decomp[1],
|
|
1917
|
+
b = decomp[3],
|
|
1918
|
+
fn = sym1.clone().toLinear();
|
|
1862
1919
|
|
|
1863
|
-
if(x.group !== PL && x.isLinear()) {
|
|
1920
|
+
if(x.group !== PL && x.isLinear()) {
|
|
1864
1921
|
var p = Number(sym2.power),
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1922
|
+
du = '_u_',
|
|
1923
|
+
u = new Symbol(du),
|
|
1924
|
+
//pull the integral with the subsitution
|
|
1925
|
+
U = _.expand(_.divide(_.pow(_.subtract(u.clone(), b.clone()), new Symbol(p)), u.clone())),
|
|
1926
|
+
scope = {};
|
|
1870
1927
|
|
|
1871
1928
|
//generate a scope for resubbing the symbol
|
|
1872
1929
|
scope[du] = fn;
|
|
1873
1930
|
var U2 = _.parse(U, scope);
|
|
1874
1931
|
retval = __.integrate(U2, dx, 0);
|
|
1875
1932
|
}
|
|
1876
|
-
else if(sym2.power.greaterThan(x.power) || sym2.power.equals(x.power)) {
|
|
1933
|
+
else if(sym2.power.greaterThan(x.power) || sym2.power.equals(x.power)) {
|
|
1877
1934
|
|
|
1878
1935
|
//factor out coefficients
|
|
1879
1936
|
var factors = new core.Algebra.Classes.Factors();
|
|
@@ -1882,11 +1939,11 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1882
1939
|
//it assumed that the result will be of group CB
|
|
1883
1940
|
if(div.group !== CB) {
|
|
1884
1941
|
retval = new Symbol(0);
|
|
1885
|
-
div.each(function(t) {
|
|
1942
|
+
div.each(function (t) {
|
|
1886
1943
|
retval = _.add(retval, __.integrate(t, dx, depth));
|
|
1887
1944
|
});
|
|
1888
1945
|
//put back the factors
|
|
1889
|
-
factors.each(function(factor) {
|
|
1946
|
+
factors.each(function (factor) {
|
|
1890
1947
|
retval = _.divide(retval, factor);
|
|
1891
1948
|
});
|
|
1892
1949
|
|
|
@@ -1897,16 +1954,16 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1897
1954
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1898
1955
|
}
|
|
1899
1956
|
}
|
|
1900
|
-
else
|
|
1957
|
+
else
|
|
1901
1958
|
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1902
1959
|
}
|
|
1903
|
-
else {
|
|
1960
|
+
else {
|
|
1904
1961
|
//handle cases such as (1-x^2)^(n/2)*x^(m) where n is odd ___ cracking knuckles... This can get a little hairy
|
|
1905
|
-
if(sym1.power.den.equals(2)) {
|
|
1962
|
+
if(sym1.power.den.equals(2)) {
|
|
1906
1963
|
//assume the function is in the form (a^2-b*x^n)^(m/2)
|
|
1907
1964
|
var dc = __.integration.decompose_arg(sym1.clone().toLinear(), dx),
|
|
1908
|
-
|
|
1909
|
-
|
|
1965
|
+
//using the above definition
|
|
1966
|
+
a = dc[3], x = dc[1], b = dc[0], bx = dc[2];
|
|
1910
1967
|
if(x.power.equals(2) && b.lessThan(0)) { //if n is even && b is negative
|
|
1911
1968
|
//make a equal 1 so we can do a trig sub
|
|
1912
1969
|
if(!a.equals(1)) { //divide a out of everything
|
|
@@ -1914,14 +1971,14 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1914
1971
|
coeff = _.multiply(coeff, _.pow(a, new Symbol(2)));
|
|
1915
1972
|
}
|
|
1916
1973
|
var u = dx;
|
|
1917
|
-
var c = _.divide(_.pow(b.clone().negate(), new Symbol(1/2)), _.pow(a, new Symbol(1/2))),
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1974
|
+
var c = _.divide(_.pow(b.clone().negate(), new Symbol(1 / 2)), _.pow(a, new Symbol(1 / 2))),
|
|
1975
|
+
du = _.symfunction(COS, [new Symbol(u)]),
|
|
1976
|
+
cosn = _.pow(_.symfunction(COS, [new Symbol(u)]), new Symbol(sym1.power.num)),
|
|
1977
|
+
X = _.pow(_.symfunction(SIN, [new Symbol(u)]), new Symbol(sym2.power)),
|
|
1978
|
+
val = _.multiply(_.multiply(cosn, du), X),
|
|
1979
|
+
integral = __.integrate(val, u, depth);
|
|
1980
|
+
//but remember that u = asin(sqrt(b)*a*x)
|
|
1981
|
+
retval = integral.sub(u, _.symfunction(ASIN, [_.multiply(new Symbol(dx), c)]));
|
|
1925
1982
|
}
|
|
1926
1983
|
else {
|
|
1927
1984
|
retval = __.integration.partial_fraction(symbol, dx, depth, opt);
|
|
@@ -1933,28 +1990,30 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1933
1990
|
}
|
|
1934
1991
|
|
|
1935
1992
|
}
|
|
1936
|
-
else if(sym1.isComposite() && sym2.isComposite()) {
|
|
1993
|
+
else if(sym1.isComposite() && sym2.isComposite()) {
|
|
1937
1994
|
//sum of integrals
|
|
1938
1995
|
retval = new Symbol(0);
|
|
1939
1996
|
if(sym1.power.greaterThan(0) && sym2.power.greaterThan(0)) {
|
|
1940
1997
|
//combine and pull the integral of each
|
|
1941
1998
|
var sym = _.expand(symbol);
|
|
1942
|
-
sym.each(function(x) {
|
|
1999
|
+
sym.each(function (x) {
|
|
1943
2000
|
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
1944
2001
|
}, true);
|
|
1945
2002
|
}
|
|
1946
2003
|
else {
|
|
1947
2004
|
var p1 = Number(sym1.power),
|
|
1948
|
-
|
|
2005
|
+
p2 = Number(sym2.power);
|
|
1949
2006
|
if(p1 < 0 && p2 > 0) {
|
|
1950
2007
|
//swap
|
|
1951
|
-
var t = sym1;
|
|
2008
|
+
var t = sym1;
|
|
2009
|
+
sym1 = sym2;
|
|
2010
|
+
sym2 = t;
|
|
1952
2011
|
}
|
|
1953
2012
|
if(p1 === -1 && p2 === -1) {
|
|
1954
2013
|
retval = __.integration.partial_fraction(symbol, dx);
|
|
1955
2014
|
}
|
|
1956
2015
|
else {
|
|
1957
|
-
sym1.each(function(x) {
|
|
2016
|
+
sym1.each(function (x) {
|
|
1958
2017
|
var k = _.multiply(x, sym2.clone());
|
|
1959
2018
|
var integral = __.integrate(k, dx, depth);
|
|
1960
2019
|
retval = _.add(retval, integral);
|
|
@@ -1965,7 +2024,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1965
2024
|
else if(g1 === CP && symbols[0].power.greaterThan(0)) {
|
|
1966
2025
|
sym1 = _.expand(sym1);
|
|
1967
2026
|
retval = new Symbol(0);
|
|
1968
|
-
sym1.each(function(x) {
|
|
2027
|
+
sym1.each(function (x) {
|
|
1969
2028
|
retval = _.add(retval, __.integrate(_.multiply(x, sym2.clone()), dx, depth));
|
|
1970
2029
|
}, true);
|
|
1971
2030
|
}
|
|
@@ -1975,12 +2034,14 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1975
2034
|
}
|
|
1976
2035
|
else if(g1 === FN && g2 === CP || g2 === FN && g1 === CP) {
|
|
1977
2036
|
if(g2 === FN && g1 === CP) {
|
|
1978
|
-
var t = sym1;
|
|
2037
|
+
var t = sym1;
|
|
2038
|
+
sym1 = sym2;
|
|
2039
|
+
sym2 = t; //swap
|
|
1979
2040
|
}
|
|
1980
2041
|
var du, sym2_clone, p, q, sa, sb;
|
|
1981
2042
|
du = Symbol.unwrapSQRT(__.diff(sym1.clone(), dx), true);
|
|
1982
2043
|
sym2_clone = Symbol.unwrapSQRT(sym2, true);
|
|
1983
|
-
if(du.power.equals(sym2_clone.power)) {
|
|
2044
|
+
if(du.power.equals(sym2_clone.power)) {
|
|
1984
2045
|
p = new Symbol(sym2.power);
|
|
1985
2046
|
sa = du.clone().toLinear();
|
|
1986
2047
|
sb = sym2.clone().toLinear();
|
|
@@ -1994,58 +2055,58 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
1994
2055
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1995
2056
|
}
|
|
1996
2057
|
}
|
|
1997
|
-
else {
|
|
2058
|
+
else {
|
|
1998
2059
|
var syma = sym1.clone().toLinear();
|
|
1999
2060
|
var symb = sym2.clone().toLinear();
|
|
2000
|
-
if(g1 === EX && g2 === EX && sym1.power.contains(dx) && sym2.power.contains(dx)
|
|
2061
|
+
if(g1 === EX && g2 === EX && sym1.power.contains(dx) && sym2.power.contains(dx)
|
|
2001
2062
|
&& !syma.contains(dx) && !symb.contains(dx)) {
|
|
2002
2063
|
retval = _.parse(format('(({0})^(({2})*({4}))*({1})^(({3})*({4})))/(log(({0})^({2}))+log(({1})^({3})))',
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2064
|
+
syma.toString(),
|
|
2065
|
+
symb.toString(),
|
|
2066
|
+
sym1.power.multiplier.toString(),
|
|
2067
|
+
sym2.power.multiplier.toString(),
|
|
2068
|
+
dx
|
|
2069
|
+
));
|
|
2009
2070
|
}
|
|
2010
|
-
else
|
|
2071
|
+
else
|
|
2011
2072
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
2012
2073
|
}
|
|
2013
2074
|
}
|
|
2014
2075
|
}
|
|
2015
|
-
else if(l === 3 && (symbols[2].group === S && symbols[2].power.lessThan(2) || symbols[0].group === CP)) {
|
|
2076
|
+
else if(l === 3 && (symbols[2].group === S && symbols[2].power.lessThan(2) || symbols[0].group === CP)) {
|
|
2016
2077
|
var first = symbols[0];
|
|
2017
2078
|
if(first.group === CP) { //TODO {support higher powers of x in the future}
|
|
2018
2079
|
if(first.power.greaterThan(1))
|
|
2019
2080
|
first = _.expand(first);
|
|
2020
2081
|
var r = _.multiply(symbols[1], symbols[2]);
|
|
2021
2082
|
retval = new Symbol(0);
|
|
2022
|
-
first.each(function(x) {
|
|
2083
|
+
first.each(function (x) {
|
|
2023
2084
|
var t = _.multiply(x, r.clone());
|
|
2024
2085
|
var intg = __.integrate(t, dx, depth);
|
|
2025
2086
|
retval = _.add(retval, intg);
|
|
2026
2087
|
}, true);
|
|
2027
2088
|
}
|
|
2028
|
-
else {
|
|
2089
|
+
else {
|
|
2029
2090
|
//try integration by parts although technically it will never work
|
|
2030
2091
|
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
2031
2092
|
}
|
|
2032
2093
|
|
|
2033
2094
|
}
|
|
2034
|
-
else if(all_functions(symbols)) {
|
|
2095
|
+
else if(all_functions(symbols)) {
|
|
2035
2096
|
var t = new Symbol(1);
|
|
2036
|
-
for(var i=0,l=symbols.length; i<l; i++) {
|
|
2097
|
+
for(var i = 0, l = symbols.length; i < l; i++) {
|
|
2037
2098
|
t = _.multiply(t, symbols[i].fnTransform());
|
|
2038
2099
|
}
|
|
2039
2100
|
t = _.expand(t);
|
|
2040
2101
|
retval = __.integrate(t, dx, depth);
|
|
2041
2102
|
}
|
|
2042
|
-
else {
|
|
2103
|
+
else {
|
|
2043
2104
|
//one more go
|
|
2044
2105
|
var transformed = trigTransform(symbols);
|
|
2045
2106
|
retval = __.integrate(_.expand(transformed), dx, depth);
|
|
2046
2107
|
}
|
|
2047
2108
|
}
|
|
2048
|
-
|
|
2109
|
+
|
|
2049
2110
|
}
|
|
2050
2111
|
|
|
2051
2112
|
retval = _.multiply(retval, coeff);
|
|
@@ -2055,19 +2116,19 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2055
2116
|
return retval;
|
|
2056
2117
|
}
|
|
2057
2118
|
|
|
2058
|
-
catch(error){
|
|
2119
|
+
catch(error) {
|
|
2059
2120
|
//do nothing if it's a NoIntegralFound error otherwise let it bubble
|
|
2060
|
-
if(!(error instanceof NoIntegralFound || error instanceof core.exceptions.DivisionByZero))
|
|
2121
|
+
if(!(error instanceof NoIntegralFound || error instanceof core.exceptions.DivisionByZero))
|
|
2061
2122
|
throw error;
|
|
2062
|
-
}
|
|
2123
|
+
}
|
|
2063
2124
|
|
|
2064
2125
|
//no symbol found so we return the integral again
|
|
2065
2126
|
return _.symfunction('integrate', [original_symbol, dt]);
|
|
2066
2127
|
}, false);
|
|
2067
2128
|
},
|
|
2068
|
-
defint: function(symbol, from, to, dx) {
|
|
2129
|
+
defint: function (symbol, from, to, dx) {
|
|
2069
2130
|
dx = dx || 'x'; //make x the default variable of integration
|
|
2070
|
-
var get_value = function(integral, vars, point) {
|
|
2131
|
+
var get_value = function (integral, vars, point) {
|
|
2071
2132
|
try {
|
|
2072
2133
|
return _.parse(integral, vars);
|
|
2073
2134
|
}
|
|
@@ -2077,54 +2138,54 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2077
2138
|
return lim;
|
|
2078
2139
|
}
|
|
2079
2140
|
};
|
|
2080
|
-
|
|
2141
|
+
|
|
2081
2142
|
var vars = core.Utils.variables(symbol),
|
|
2082
|
-
|
|
2143
|
+
hasTrig = symbol.hasTrig();
|
|
2083
2144
|
var retval, integral;
|
|
2084
|
-
|
|
2145
|
+
|
|
2085
2146
|
// Fix #593 - Only assume the first variable if dx is not defined.
|
|
2086
2147
|
if(vars.length === 1 && !dx)
|
|
2087
2148
|
dx = vars[0];
|
|
2088
|
-
|
|
2149
|
+
|
|
2089
2150
|
if(!hasTrig) {
|
|
2090
2151
|
integral = __.integrate(symbol, dx);
|
|
2091
2152
|
}
|
|
2092
|
-
|
|
2093
|
-
if(!hasTrig && !integral.hasIntegral()) {
|
|
2153
|
+
|
|
2154
|
+
if(!hasTrig && !integral.hasIntegral()) {
|
|
2094
2155
|
var upper = {},
|
|
2095
|
-
|
|
2096
|
-
|
|
2156
|
+
lower = {},
|
|
2157
|
+
a, b;
|
|
2097
2158
|
upper[dx] = to;
|
|
2098
2159
|
lower[dx] = from;
|
|
2099
|
-
|
|
2100
|
-
a = get_value(integral, upper, to, dx);
|
|
2160
|
+
|
|
2161
|
+
a = get_value(integral, upper, to, dx);
|
|
2101
2162
|
b = get_value(integral, lower, from, dx);
|
|
2102
2163
|
retval = _.subtract(a, b);
|
|
2103
2164
|
}
|
|
2104
2165
|
else if(vars.length === 1 && from.isConstant() && to.isConstant()) {
|
|
2105
|
-
|
|
2106
|
-
var f = core.Utils.build(symbol);
|
|
2107
|
-
|
|
2166
|
+
|
|
2167
|
+
var f = core.Utils.build(symbol);
|
|
2168
|
+
retval = new Symbol(core.Math2.num_integrate(f, Number(from), Number(to)));
|
|
2108
2169
|
}
|
|
2109
|
-
else
|
|
2110
|
-
retval = _.symfunction('defint', [symbol, from
|
|
2170
|
+
else
|
|
2171
|
+
retval = _.symfunction('defint', [symbol, from, to, dx]);
|
|
2111
2172
|
return retval;
|
|
2112
2173
|
},
|
|
2113
|
-
|
|
2174
|
+
|
|
2114
2175
|
Limit: {
|
|
2115
|
-
interval: function(start, end) {
|
|
2176
|
+
interval: function (start, end) {
|
|
2116
2177
|
return _.parse(format('[{0}, {1}]', start, end));
|
|
2117
2178
|
},
|
|
2118
|
-
diverges: function() {
|
|
2179
|
+
diverges: function () {
|
|
2119
2180
|
return __.Limit.interval('-Infinity', 'Infinity');
|
|
2120
2181
|
},
|
|
2121
|
-
divide: function(f, g, x, lim, depth) {
|
|
2182
|
+
divide: function (f, g, x, lim, depth) {
|
|
2122
2183
|
if(depth++ > Settings.max_lim_depth) {
|
|
2123
2184
|
return;
|
|
2124
2185
|
}
|
|
2125
2186
|
|
|
2126
2187
|
var fin = f.clone(), gin = g.clone();
|
|
2127
|
-
|
|
2188
|
+
|
|
2128
2189
|
//But first a little "cheating". x/|x| ends up in an infinite loop since the d/dx |x| -> x/|x|
|
|
2129
2190
|
//To break this loop we simply provide the answer. Keep in mind that currently limit only provides
|
|
2130
2191
|
//the two-sided limit.
|
|
@@ -2135,29 +2196,29 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2135
2196
|
|
|
2136
2197
|
if(lim.isInfinity)
|
|
2137
2198
|
return _.multiply(new Symbol(sign), new Symbol(lim_sign));
|
|
2138
|
-
|
|
2199
|
+
|
|
2139
2200
|
else if(lim.equals(0)) {
|
|
2140
2201
|
var fm = _.parse(f.multiplier);
|
|
2141
2202
|
var gm = _.parse(g.multiplier);
|
|
2142
|
-
return _.divide(_.multiply(fm,__.Limit.interval('-1', '1')), gm);
|
|
2203
|
+
return _.divide(_.multiply(fm, __.Limit.interval('-1', '1')), gm);
|
|
2143
2204
|
}
|
|
2144
2205
|
else {
|
|
2145
2206
|
//TODO: Support more limits
|
|
2146
2207
|
__.Limit.diverges();
|
|
2147
2208
|
}
|
|
2148
2209
|
}
|
|
2149
|
-
|
|
2150
|
-
var isInfinity = function(L) {
|
|
2210
|
+
|
|
2211
|
+
var isInfinity = function (L) {
|
|
2151
2212
|
if(core.Utils.isVector(L)) {
|
|
2152
|
-
for(var i=0; i<L.elements.length; i++)
|
|
2213
|
+
for(var i = 0; i < L.elements.length; i++)
|
|
2153
2214
|
if(!L.elements[i].isInfinity)
|
|
2154
2215
|
return false;
|
|
2155
2216
|
return true;
|
|
2156
2217
|
}
|
|
2157
|
-
return L.isInfinity;
|
|
2218
|
+
return L.isInfinity;
|
|
2158
2219
|
};
|
|
2159
2220
|
|
|
2160
|
-
var equals = function(L, v) {
|
|
2221
|
+
var equals = function (L, v) {
|
|
2161
2222
|
if(core.Utils.isVector(L)) {
|
|
2162
2223
|
return false;
|
|
2163
2224
|
}
|
|
@@ -2179,17 +2240,17 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2179
2240
|
var t_symbol = _.expand(_.divide(ft, gt));
|
|
2180
2241
|
f = t_symbol.getNum();
|
|
2181
2242
|
g = t_symbol.getDenom();
|
|
2182
|
-
|
|
2243
|
+
|
|
2183
2244
|
}
|
|
2184
2245
|
}
|
|
2185
|
-
while(indeterminate)
|
|
2246
|
+
while(indeterminate)
|
|
2186
2247
|
|
|
2187
2248
|
//REMEMBER:
|
|
2188
2249
|
//- 1/cos(x)
|
|
2189
2250
|
//n/0 is still possible since we only checked for 0/0
|
|
2190
2251
|
var den_is_zero = lim2.equals(0);
|
|
2191
2252
|
var p = Number(gin.power);
|
|
2192
|
-
|
|
2253
|
+
|
|
2193
2254
|
if(lim.isConstant(true) && den_is_zero) {
|
|
2194
2255
|
retval = Symbol.infinity(core.Utils.even(p) && lim1.lessThan(0) ? -1 : undefined);
|
|
2195
2256
|
}
|
|
@@ -2199,15 +2260,15 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2199
2260
|
else {
|
|
2200
2261
|
retval = _.divide(lim1, lim2);
|
|
2201
2262
|
}
|
|
2202
|
-
|
|
2263
|
+
|
|
2203
2264
|
return retval;
|
|
2204
2265
|
},
|
|
2205
|
-
rewriteToLog: function(symbol) {
|
|
2266
|
+
rewriteToLog: function (symbol) {
|
|
2206
2267
|
var p = symbol.power.clone();
|
|
2207
2268
|
symbol.toLinear();
|
|
2208
|
-
return _.pow(new Symbol('e'), _.multiply(p, _.symfunction(Settings.LOG+'', [symbol])));
|
|
2269
|
+
return _.pow(new Symbol('e'), _.multiply(p, _.symfunction(Settings.LOG + '', [symbol])));
|
|
2209
2270
|
},
|
|
2210
|
-
getSubbed: function(f, x, lim) {
|
|
2271
|
+
getSubbed: function (f, x, lim) {
|
|
2211
2272
|
var retval;
|
|
2212
2273
|
//1. rewrite EX with base e
|
|
2213
2274
|
if(f.group === EX) {
|
|
@@ -2221,45 +2282,46 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2221
2282
|
//Nope. No go, so just return the unsubbed function so we can test the limit instead.
|
|
2222
2283
|
retval = f;
|
|
2223
2284
|
}
|
|
2224
|
-
|
|
2285
|
+
|
|
2225
2286
|
return retval;
|
|
2226
2287
|
},
|
|
2227
|
-
isInterval: function(limit) {
|
|
2288
|
+
isInterval: function (limit) {
|
|
2228
2289
|
return core.Utils.isVector(limit);
|
|
2229
2290
|
},
|
|
2230
|
-
isConvergent: function(limit) {
|
|
2291
|
+
isConvergent: function (limit) {
|
|
2231
2292
|
//it's not convergent if it lies on the interval -Infinity to Infinity
|
|
2232
|
-
if(
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2293
|
+
if(
|
|
2294
|
+
//It lies on the interval -Infinity to Infinity
|
|
2295
|
+
__.Limit.isInterval(limit) && limit.elements[0].isInfinity && limit.elements[1].isInfinity ||
|
|
2296
|
+
//We weren't able to calculate the limit
|
|
2297
|
+
limit.containsFunction('limit')
|
|
2298
|
+
) {
|
|
2238
2299
|
return false; //Then no
|
|
2239
2300
|
}
|
|
2240
2301
|
return true; //It is
|
|
2241
2302
|
},
|
|
2242
|
-
limit: function(symbol, x, lim, depth) {
|
|
2303
|
+
limit: function (symbol, x, lim, depth) {
|
|
2243
2304
|
//Simplify the symbol
|
|
2244
2305
|
if(symbol.isLinear() && symbol.isComposite()) {
|
|
2245
|
-
|
|
2306
|
+
|
|
2246
2307
|
//Apply sum of limits
|
|
2247
2308
|
var limit = new Symbol(0);
|
|
2248
|
-
symbol.each(function(s) {
|
|
2309
|
+
symbol.each(function (s) {
|
|
2249
2310
|
limit = _.add(limit, __.Limit.limit(s, x, lim, depth));
|
|
2250
2311
|
}, true);
|
|
2251
|
-
|
|
2312
|
+
|
|
2252
2313
|
return limit;
|
|
2253
|
-
}
|
|
2254
|
-
|
|
2314
|
+
}
|
|
2315
|
+
;
|
|
2316
|
+
|
|
2255
2317
|
symbol = core.Algebra.Simplify.simplify(symbol);
|
|
2256
|
-
|
|
2318
|
+
|
|
2257
2319
|
depth = depth || 1;
|
|
2258
|
-
|
|
2320
|
+
|
|
2259
2321
|
if(depth++ > Settings.max_lim_depth) {
|
|
2260
2322
|
return;
|
|
2261
2323
|
}
|
|
2262
|
-
|
|
2324
|
+
|
|
2263
2325
|
//store the multiplier
|
|
2264
2326
|
var m = _.parse(symbol.multiplier);
|
|
2265
2327
|
//strip the multiplier
|
|
@@ -2276,18 +2338,20 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2276
2338
|
var point = {};
|
|
2277
2339
|
point[x] = lim;
|
|
2278
2340
|
//lim x as x->c = c where c
|
|
2279
|
-
|
|
2341
|
+
|
|
2280
2342
|
try {
|
|
2281
|
-
|
|
2343
|
+
|
|
2282
2344
|
//evaluate the function at the given limit
|
|
2283
2345
|
var t = _.parse(symbol.sub(x, lim), point);
|
|
2284
2346
|
|
|
2285
2347
|
//a constant or infinity is known so we're done
|
|
2286
2348
|
if(t.isConstant(true) || t.isInfinity)
|
|
2287
2349
|
retval = t;
|
|
2288
|
-
|
|
2350
|
+
|
|
2351
|
+
}
|
|
2352
|
+
catch(e) { /*Nothing. Maybe we tried to divide by zero.*/
|
|
2289
2353
|
}
|
|
2290
|
-
|
|
2354
|
+
;
|
|
2291
2355
|
|
|
2292
2356
|
if(!retval) {
|
|
2293
2357
|
//split the symbol in the numerator and the denominator
|
|
@@ -2318,23 +2382,23 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2318
2382
|
retval = _.pow(lim_base, lim_pow);
|
|
2319
2383
|
}
|
|
2320
2384
|
}
|
|
2321
|
-
else if(symbol.group === FN && symbol.args.length === 1
|
|
2385
|
+
else if(symbol.group === FN && symbol.args.length === 1) {
|
|
2322
2386
|
var evaluates;
|
|
2323
2387
|
//Squeeze theorem lim f(g(x)) = lim f(lim g))
|
|
2324
2388
|
var arg = __.Limit.limit(symbol.args[0], x, lim, depth);
|
|
2325
2389
|
if(core.Utils.isVector(arg)) {
|
|
2326
2390
|
//get the limit over that interval
|
|
2327
|
-
retval = arg.map(function(e) {
|
|
2391
|
+
retval = arg.map(function (e) {
|
|
2328
2392
|
var clone = symbol.clone();
|
|
2329
2393
|
clone.args[0] = e;
|
|
2330
2394
|
return __.Limit.limit(_.symfunction(symbol.fname, [e]), x, lim, depth);
|
|
2331
2395
|
});
|
|
2332
|
-
|
|
2396
|
+
|
|
2333
2397
|
return _.multiply(m, retval);
|
|
2334
2398
|
}
|
|
2335
2399
|
//if the argument is constant then we're done
|
|
2336
2400
|
else if(arg.isConstant(true)) {
|
|
2337
|
-
|
|
2401
|
+
|
|
2338
2402
|
//double check that it evaluates
|
|
2339
2403
|
var trial = _.symfunction(symbol.fname, [arg]);
|
|
2340
2404
|
//trial evaluation
|
|
@@ -2343,7 +2407,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2343
2407
|
evaluates = true;
|
|
2344
2408
|
}
|
|
2345
2409
|
catch(e) {
|
|
2346
|
-
|
|
2410
|
+
|
|
2347
2411
|
evaluates = false;
|
|
2348
2412
|
}
|
|
2349
2413
|
}
|
|
@@ -2353,7 +2417,7 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2353
2417
|
else {
|
|
2354
2418
|
//if the limit converges. We'll deal with non-convergent ones later
|
|
2355
2419
|
if(__.Limit.isConvergent(arg)) {
|
|
2356
|
-
if(symbol.fname === LOG) {
|
|
2420
|
+
if(symbol.fname === LOG) {
|
|
2357
2421
|
switch(arg.toString()) {
|
|
2358
2422
|
//lim -> 0
|
|
2359
2423
|
case '0':
|
|
@@ -2400,16 +2464,16 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2400
2464
|
else {
|
|
2401
2465
|
//odd ones don't
|
|
2402
2466
|
retval = __.Limit.diverges();
|
|
2403
|
-
}
|
|
2467
|
+
}
|
|
2404
2468
|
}
|
|
2405
2469
|
}
|
|
2406
|
-
else if(symbol.group === CB) {
|
|
2407
|
-
|
|
2470
|
+
else if(symbol.group === CB) {
|
|
2471
|
+
|
|
2408
2472
|
var lim1, lim2;
|
|
2409
2473
|
//loop through all the symbols
|
|
2410
2474
|
//thus => lim f*g*h = lim (f*g)*h = (lim f*g)*(lim h)
|
|
2411
2475
|
//symbols of lower groups are generally easier to differentiatee so get them to the right by first sorting
|
|
2412
|
-
var symbols = symbol.collectSymbols().sort(function(a, b) {
|
|
2476
|
+
var symbols = symbol.collectSymbols().sort(function (a, b) {
|
|
2413
2477
|
return a.group - b.group;
|
|
2414
2478
|
});
|
|
2415
2479
|
|
|
@@ -2423,16 +2487,16 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2423
2487
|
var g = symbols.pop();
|
|
2424
2488
|
//get the limit of g
|
|
2425
2489
|
lim2 = evaluate(__.Limit.limit(g, x, lim, depth));
|
|
2426
|
-
|
|
2490
|
+
|
|
2427
2491
|
//if the limit is in indeterminate form aplly L'Hospital by inverting g and then f/(1/g)
|
|
2428
|
-
if((lim1.isInfinity || !__.Limit.isConvergent(lim1) && lim2.equals(0) || lim1.equals(0) && __.Limit.isConvergent(lim2))) {
|
|
2492
|
+
if((lim1.isInfinity || !__.Limit.isConvergent(lim1) && lim2.equals(0) || lim1.equals(0) && __.Limit.isConvergent(lim2))) {
|
|
2429
2493
|
if(g.containsFunction(LOG)) {
|
|
2430
2494
|
//swap them
|
|
2431
2495
|
g = [f, f = g][0];
|
|
2432
2496
|
}
|
|
2433
2497
|
//invert the symbol
|
|
2434
2498
|
g.invert();
|
|
2435
|
-
|
|
2499
|
+
|
|
2436
2500
|
// Product of infinities
|
|
2437
2501
|
if(lim1.isInfinity && lim2.isInfinity) {
|
|
2438
2502
|
lim1 = Symbol.infinity()
|
|
@@ -2452,21 +2516,21 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2452
2516
|
//Done, lim1 is the limit we're looking for
|
|
2453
2517
|
retval = lim1;
|
|
2454
2518
|
}
|
|
2455
|
-
else if(symbol.isComposite()) {
|
|
2519
|
+
else if(symbol.isComposite()) {
|
|
2456
2520
|
var _lim;
|
|
2457
2521
|
if(!symbol.isLinear())
|
|
2458
2522
|
symbol = _.expand(symbol);
|
|
2459
2523
|
//Apply lim f+g = (lim f)+(lim g)
|
|
2460
2524
|
retval = new Symbol(0);
|
|
2461
|
-
|
|
2462
|
-
var symbols = symbol.collectSymbols().sort(function(a, b) {
|
|
2525
|
+
|
|
2526
|
+
var symbols = symbol.collectSymbols().sort(function (a, b) {
|
|
2463
2527
|
return b.group - a.group;
|
|
2464
2528
|
});
|
|
2465
2529
|
|
|
2466
2530
|
var _symbols = [];
|
|
2467
2531
|
//Analyze the functions first
|
|
2468
2532
|
var fns = new Symbol(0);
|
|
2469
|
-
for(var i=0, l=symbols.length; i<l; i++) {
|
|
2533
|
+
for(var i = 0, l = symbols.length; i < l; i++) {
|
|
2470
2534
|
var sym = symbols[i].clone();
|
|
2471
2535
|
if(sym.group === FN || sym.group === CB && sym.hasFunc()) {
|
|
2472
2536
|
fns = _.add(fns, sym);
|
|
@@ -2475,13 +2539,13 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2475
2539
|
_symbols.push(sym);
|
|
2476
2540
|
}
|
|
2477
2541
|
_symbols.unshift(fns);
|
|
2478
|
-
|
|
2542
|
+
|
|
2479
2543
|
//make sure that we didn't just repackage the exact same symbol
|
|
2480
2544
|
if(_symbols.length !== 1) {
|
|
2481
2545
|
symbols = _symbols;
|
|
2482
2546
|
}
|
|
2483
|
-
|
|
2484
|
-
for(var i=0, l=symbols.length; i<l; i++) {
|
|
2547
|
+
|
|
2548
|
+
for(var i = 0, l = symbols.length; i < l; i++) {
|
|
2485
2549
|
var sym = symbols[i];
|
|
2486
2550
|
//If the addition of the limits is undefined then the limit diverges so return -infinity to infinity
|
|
2487
2551
|
try {
|
|
@@ -2490,46 +2554,47 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2490
2554
|
catch(e) {
|
|
2491
2555
|
_lim = __.Limit.diverges();
|
|
2492
2556
|
}
|
|
2493
|
-
|
|
2557
|
+
|
|
2494
2558
|
try {
|
|
2495
2559
|
retval = _.add(retval, _lim);
|
|
2496
2560
|
}
|
|
2497
2561
|
catch(e) {
|
|
2498
2562
|
if(depth++ > Settings.max_lim_depth) {
|
|
2499
2563
|
return;
|
|
2500
|
-
}
|
|
2564
|
+
}
|
|
2565
|
+
;
|
|
2501
2566
|
retval = __.Limit.limit(__.diff(symbol, x), x, lim, depth);
|
|
2502
2567
|
}
|
|
2503
2568
|
}
|
|
2504
|
-
}
|
|
2569
|
+
}
|
|
2505
2570
|
}
|
|
2506
2571
|
else {
|
|
2507
2572
|
retval = __.Limit.divide(num, den, x, lim, depth);
|
|
2508
|
-
}
|
|
2573
|
+
}
|
|
2509
2574
|
}
|
|
2510
2575
|
}
|
|
2511
2576
|
|
|
2512
2577
|
//if we still don't have a solution
|
|
2513
2578
|
if(!retval)
|
|
2514
2579
|
//return it symbolically
|
|
2515
|
-
retval = _.symfunction('limit', [symbol, x, lim]);
|
|
2580
|
+
retval = _.symfunction('limit', [symbol, x, lim]);
|
|
2516
2581
|
}
|
|
2517
2582
|
catch(e) {
|
|
2518
2583
|
//if all else fails return the symbolic function
|
|
2519
|
-
retval = _.symfunction('limit', [symbol, x, lim]);
|
|
2584
|
+
retval = _.symfunction('limit', [symbol, x, lim]);
|
|
2520
2585
|
}
|
|
2521
|
-
|
|
2586
|
+
|
|
2522
2587
|
return _.multiply(m, retval);
|
|
2523
2588
|
}
|
|
2524
2589
|
},
|
|
2525
2590
|
Fresnel: {
|
|
2526
|
-
S: function(x) {
|
|
2591
|
+
S: function (x) {
|
|
2527
2592
|
if(x.isConstant(true)) {
|
|
2528
2593
|
return __.defint(_.parse('sin(pi*x^2/2)'), Symbol(0), x, 'x');
|
|
2529
2594
|
}
|
|
2530
2595
|
return _.symfunction('S', arguments);
|
|
2531
2596
|
},
|
|
2532
|
-
C: function(x) {
|
|
2597
|
+
C: function (x) {
|
|
2533
2598
|
if(x.isConstant(true)) {
|
|
2534
2599
|
return __.defint(_.parse('cos(pi*x^2/2)'), Symbol(0), x, 'x');
|
|
2535
2600
|
}
|
|
@@ -2537,58 +2602,74 @@ if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
|
2537
2602
|
}
|
|
2538
2603
|
}
|
|
2539
2604
|
};
|
|
2540
|
-
|
|
2605
|
+
|
|
2541
2606
|
nerdamer.register([
|
|
2542
2607
|
{
|
|
2543
2608
|
name: 'diff',
|
|
2544
2609
|
visible: true,
|
|
2545
|
-
numargs: [1,3],
|
|
2546
|
-
build: function(){
|
|
2610
|
+
numargs: [1, 3],
|
|
2611
|
+
build: function () {
|
|
2612
|
+
return __.diff;
|
|
2613
|
+
}
|
|
2547
2614
|
},
|
|
2548
2615
|
{
|
|
2549
2616
|
name: 'sum',
|
|
2550
2617
|
visible: true,
|
|
2551
2618
|
numargs: 4,
|
|
2552
|
-
build: function(){
|
|
2619
|
+
build: function () {
|
|
2620
|
+
return __.sum;
|
|
2621
|
+
}
|
|
2553
2622
|
},
|
|
2554
2623
|
{
|
|
2555
2624
|
name: 'product',
|
|
2556
2625
|
visible: true,
|
|
2557
2626
|
numargs: 4,
|
|
2558
|
-
build: function(){
|
|
2627
|
+
build: function () {
|
|
2628
|
+
return __.product;
|
|
2629
|
+
}
|
|
2559
2630
|
},
|
|
2560
2631
|
{
|
|
2561
2632
|
name: 'integrate',
|
|
2562
2633
|
visible: true,
|
|
2563
2634
|
numargs: [1, 2],
|
|
2564
|
-
build: function() {
|
|
2635
|
+
build: function () {
|
|
2636
|
+
return __.integrate;
|
|
2637
|
+
}
|
|
2565
2638
|
},
|
|
2566
2639
|
{
|
|
2567
2640
|
name: 'defint',
|
|
2568
2641
|
visible: true,
|
|
2569
2642
|
numargs: [3, 4],
|
|
2570
|
-
build: function() {
|
|
2643
|
+
build: function () {
|
|
2644
|
+
return __.defint;
|
|
2645
|
+
}
|
|
2571
2646
|
},
|
|
2572
2647
|
{
|
|
2573
2648
|
name: 'S',
|
|
2574
2649
|
visible: true,
|
|
2575
2650
|
numargs: 1,
|
|
2576
|
-
build: function() {
|
|
2651
|
+
build: function () {
|
|
2652
|
+
return __.Fresnel.S;
|
|
2653
|
+
}
|
|
2577
2654
|
},
|
|
2578
2655
|
{
|
|
2579
2656
|
name: 'C',
|
|
2580
2657
|
visible: true,
|
|
2581
2658
|
numargs: 1,
|
|
2582
|
-
build: function() {
|
|
2659
|
+
build: function () {
|
|
2660
|
+
return __.Fresnel.C;
|
|
2661
|
+
}
|
|
2583
2662
|
},
|
|
2584
2663
|
{
|
|
2585
2664
|
name: 'limit',
|
|
2586
2665
|
visible: true,
|
|
2587
2666
|
numargs: [3, 4],
|
|
2588
|
-
build: function() {
|
|
2667
|
+
build: function () {
|
|
2668
|
+
return __.Limit.limit;
|
|
2669
|
+
}
|
|
2589
2670
|
}
|
|
2590
2671
|
]);
|
|
2591
2672
|
//link registered functions externally
|
|
2592
|
-
nerdamer.
|
|
2593
|
-
|
|
2594
|
-
})();
|
|
2673
|
+
nerdamer.updateAPI();
|
|
2674
|
+
|
|
2675
|
+
})();
|