nerdamer 1.1.13 → 2.0.0-rc.1

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