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/Solve.js DELETED
@@ -1,1783 +0,0 @@
1
- /*
2
- * Author : Martin Donk
3
- * Website : http://www.nerdamer.com
4
- * Email : martin.r.donk@gmail.com
5
- * Source : https://github.com/jiggzson/nerdamer
6
- */
7
- /* global module */
8
-
9
- if((typeof module) !== 'undefined') {
10
- var nerdamer = require('./nerdamer.core.js');
11
- require('./Calculus.js');
12
- require('./Algebra.js');
13
- }
14
-
15
- (function () {
16
- //handle imports
17
- var core = nerdamer.getCore(),
18
- _ = core.PARSER,
19
- _A = core.Algebra,
20
- _C = core.Calculus,
21
- explode = _C.integration.decompose_arg,
22
- evaluate = core.Utils.evaluate,
23
- remove = core.Utils.remove,
24
- format = core.Utils.format,
25
- build = core.Utils.build,
26
- knownVariable = core.Utils.knownVariable,
27
- Symbol = core.Symbol,
28
- isSymbol = core.Utils.isSymbol,
29
- variables = core.Utils.variables,
30
- S = core.groups.S,
31
- PL = core.groups.PL,
32
- CB = core.groups.CB,
33
- CP = core.groups.CP,
34
- FN = core.groups.FN,
35
- Settings = core.Settings,
36
- range = core.Utils.range,
37
- isArray = core.Utils.isArray;
38
-
39
-
40
- // The search radius for the roots
41
- core.Settings.SOLVE_RADIUS = 1000;
42
- // The maximum number to fish for on each side of the zero
43
- core.Settings.ROOTS_PER_SIDE = 10;
44
- // Covert the number to multiples of pi if possible
45
- core.Settings.make_pi_conversions = false;
46
- // The step size
47
- core.Settings.STEP_SIZE = 0.1;
48
- // The epsilon size
49
- core.Settings.EPSILON = 1e-13;
50
- //the maximum iterations for Newton's method
51
- core.Settings.MAX_NEWTON_ITERATIONS = 200;
52
- //the maximum number of time non-linear solve tries another jump point
53
- core.Settings.MAX_NON_LINEAR_TRIES = 12;
54
- //the amount of iterations the function will start to jump at
55
- core.Settings.NON_LINEAR_JUMP_AT = 50;
56
- //the size of the jump
57
- core.Settings.NON_LINEAR_JUMP_SIZE = 100;
58
- //the original starting point for nonlinear solving
59
- core.Settings.NON_LINEAR_START = 0.01;
60
- //When points are generated as starting points for Newton's method, they are sliced into small
61
- //slices to make sure that we have convergence on the right point. This defines the
62
- //size of the slice
63
- core.Settings.NEWTON_SLICES = 200;
64
- //The epsilon used in Newton's iteration
65
- core.Settings.NEWTON_EPSILON = Number.EPSILON * 2;
66
- //The distance in which two solutions are deemed the same
67
- core.Settings.SOLUTION_PROXIMITY = 1e-14;
68
- //Indicate wheter to filter the solutions are not
69
- core.Settings.FILTER_SOLUTIONS = true;
70
- //the maximum number of recursive calls
71
- core.Settings.MAX_SOLVE_DEPTH = 10;
72
- // The tolerance that's considered close enough to zero
73
- core.Settings.ZERO_EPSILON = 1e-9;
74
- // The maximum iteration for the bisection method incase of some JS strangeness
75
- core.Settings.MAX_BISECTION_ITER = 2000;
76
- // The tolerance for the bisection method
77
- core.Settings.BI_SECTION_EPSILON = 1e-12;
78
-
79
-
80
- core.Symbol.prototype.hasTrig = function () {
81
- return this.containsFunction(['cos', 'sin', 'tan', 'cot', 'csc', 'sec']);
82
- };
83
-
84
- core.Symbol.prototype.hasNegativeTerms = function () {
85
- if(this.isComposite()) {
86
- for(var x in this.symbols) {
87
- var sym = this.symbols[x];
88
- if(sym.group === PL && sym.hasNegativeTerms() || this.symbols[x].power.lessThan(0))
89
- return true;
90
- }
91
- }
92
- return false;
93
- };
94
-
95
- /* nerdamer version 0.7.x and up allows us to make better use of operator overloading
96
- * As such we can have this data type be supported completely outside of the core.
97
- * This is an equation that has a left hand side and a right hand side
98
- */
99
- function Equation(lhs, rhs) {
100
- if(rhs.isConstant() && lhs.isConstant() && !lhs.equals(rhs) || lhs.equals(core.Settings.IMAGINARY) && rhs.isConstant(true) || rhs.equals(core.Settings.IMAGINARY) && lhs.isConstant(true))
101
- throw new core.exceptions.NerdamerValueError(lhs.toString() + ' does not equal ' + rhs.toString());
102
- this.LHS = lhs; //left hand side
103
- this.RHS = rhs; //right and side
104
- }
105
- ;
106
-
107
- //UTILS ##!!
108
-
109
- Equation.prototype = {
110
- toString: function () {
111
- return this.LHS.toString() + '=' + this.RHS.toString();
112
- },
113
- text: function (option) {
114
- return this.LHS.text(option) + '=' + this.RHS.text(option);
115
- },
116
- toLHS: function (expand) {
117
- expand = typeof expand === 'undefined' ? true : false;
118
- var eqn;
119
- if(!expand) {
120
- eqn = this.clone();
121
- }
122
- else {
123
- eqn = this.removeDenom();
124
- }
125
- var a = eqn.LHS;
126
- var b = eqn.RHS;
127
-
128
- if(a.isConstant(true) && !b.isConstant(true)) {
129
- // Swap them to avoid confusing parser and cause an infinite loop
130
- [a, b] = [b, a];
131
- }
132
- var _t = _.subtract(a, b);
133
- var retval = expand ? _.expand(_t) : _t;
134
-
135
- // Quick workaround for issue #636
136
- // This basically borrows the removeDenom method from the Equation class.
137
- // TODO: Make this function a stand-alone function
138
- retval = new Equation(retval, new Symbol(0)).removeDenom().LHS;
139
-
140
- return retval;
141
- },
142
- removeDenom: function () {
143
- var a = this.LHS.clone();
144
- var b = this.RHS.clone();
145
- //remove the denominator on both sides
146
- var den = _.multiply(a.getDenom(), b.getDenom());
147
- a = _.expand(_.multiply(a, den.clone()));
148
- b = _.expand(_.multiply(b, den));
149
- //swap the groups
150
- if(b.group === CP && b.group !== CP) {
151
- var t = a;
152
- a = b;
153
- b = t; //swap
154
- }
155
-
156
- //scan to eliminate denominators
157
- if(a.group === CB) {
158
- var t = new Symbol(a.multiplier),
159
- newRHS = b.clone();
160
- a.each(function (y) {
161
- if(y.power.lessThan(0))
162
- newRHS = _.divide(newRHS, y);
163
- else
164
- t = _.multiply(t, y);
165
- });
166
- a = t;
167
- b = newRHS;
168
-
169
- }
170
- else if(a.group === CP) {
171
- //the logic: loop through each and if it has a denominator then multiply it out on both ends
172
- //and then start over
173
- for(var x in a.symbols) {
174
- var sym = a.symbols[x];
175
- if(sym.group === CB) {
176
- for(var y in sym.symbols) {
177
- var sym2 = sym.symbols[y];
178
- if(sym2.power.lessThan(0)) {
179
- return new Equation(
180
- _.expand(_.multiply(sym2.clone().toLinear(), a)),
181
- _.expand(_.multiply(sym2.clone().toLinear(), b))
182
- );
183
- }
184
- }
185
- }
186
- }
187
- }
188
-
189
- return new Equation(a, b);
190
- },
191
- clone: function () {
192
- return new Equation(this.LHS.clone(), this.RHS.clone());
193
- },
194
- sub: function (x, y) {
195
- var clone = this.clone();
196
- clone.LHS = clone.LHS.sub(x.clone(), y.clone());
197
- clone.RHS = clone.RHS.sub(x.clone(), y.clone());
198
- return clone;
199
- },
200
- isZero: function () {
201
- return core.Utils.evaluate(this.toLHS()).equals(0);
202
- },
203
- latex: function (option) {
204
- return [this.LHS.latex(option), this.RHS.latex(option)].join('=');
205
- }
206
- };
207
- //overwrite the equals function
208
- _.equals = function (a, b) {
209
- return new Equation(a, b);
210
- };
211
-
212
- // Extend simplify
213
- (function () {
214
- var simplify = _.functions.simplify[0];
215
- _.functions.simplify[0] = function (symbol) {
216
- if(symbol instanceof Equation) {
217
- symbol.LHS = simplify(symbol.LHS);
218
- symbol.RHS = simplify(symbol.RHS);
219
- return symbol;
220
- }
221
- // Just call the original simplify
222
- return simplify(symbol);
223
- };
224
- })();
225
-
226
- /**
227
- * Sets two expressions equal
228
- * @param {Symbol} symbol
229
- * @returns {Expression}
230
- */
231
- core.Expression.prototype.equals = function (symbol) {
232
- if(symbol instanceof core.Expression)
233
- symbol = symbol.symbol; //grab the symbol if it's an expression
234
- var eq = new Equation(this.symbol, symbol);
235
- return eq;
236
- };
237
-
238
- core.Expression.prototype.solveFor = function (x) {
239
- var symbol;
240
- if(this.symbol instanceof Equation) {
241
- //exit right away if we already have the answer
242
- //check the LHS
243
- if(this.symbol.LHS.isConstant() && this.symbol.RHS.equals(x))
244
- return new core.Expression(this.symbol.LHS);
245
-
246
- //check the RHS
247
- if(this.symbol.RHS.isConstant() && this.symbol.LHS.equals(x))
248
- return new core.Expression(this.symbol.RHS);
249
-
250
- //otherwise just bring it to LHS
251
- symbol = this.symbol.toLHS();
252
- }
253
- else {
254
- symbol = this.symbol;
255
- }
256
-
257
- return solve(symbol, x).map(function (x) {
258
- return new core.Expression(x);
259
- });
260
- };
261
-
262
- core.Expression.prototype.expand = function () {
263
- if(this.symbol instanceof Equation) {
264
- var clone = this.symbol.clone();
265
- clone.RHS = _.expand(clone.RHS);
266
- clone.LHS = _.expand(clone.LHS);
267
- return new core.Expression(clone);
268
- }
269
- return new core.Expression(_.expand(this.symbol));
270
- };
271
-
272
- core.Expression.prototype.variables = function () {
273
- if(this.symbol instanceof Equation)
274
- return core.Utils.arrayUnique(variables(this.symbol.LHS).concat(variables(this.symbol.RHS)));
275
- return variables(this.symbol);
276
- };
277
-
278
-
279
-
280
- var setEq = function (a, b) {
281
- return _.equals(a, b);
282
- };
283
-
284
- //link the Equation class back to the core
285
- core.Equation = Equation;
286
-
287
- //Loops through an array and attempts to fails a test. Stops if manages to fail.
288
- var checkAll = core.Utils.checkAll = function (args, test) {
289
- for(var i = 0; i < args.length; i++)
290
- if(test(args[i]))
291
- return false;
292
- return true;
293
- };
294
-
295
- //version solve
296
- var __ = core.Solve = {
297
- version: '2.0.3',
298
- solutions: [],
299
- solve: function (eq, variable) {
300
- var solution = solve(eq, String(variable));
301
- return new core.Vector(solution);
302
- //return new core.Vector(solve(eq.toString(), variable ? variable.toString() : variable));
303
- },
304
- /**
305
- * Brings the equation to LHS. A string can be supplied which will be converted to an Equation
306
- * @param {Equation|String} eqn
307
- * @returns {Symbol}
308
- */
309
- toLHS: function (eqn, expand) {
310
- if(isSymbol(eqn))
311
- return eqn;
312
- //If it's an equation then call its toLHS function instead
313
- if(!(eqn instanceof Equation)) {
314
- var es = eqn.split('=');
315
- //convert falsey values to zero
316
- es[1] = es[1] || '0';
317
- eqn = new Equation(_.parse(es[0]), _.parse(es[1]));
318
- }
319
- return eqn.toLHS(expand);
320
- },
321
- // getSystemVariables: function(eqns) {
322
- // vars = variables(eqns[0], null, null, true);
323
- //
324
- // //get all variables
325
- // for (var i = 1, l=eqns.length; i < l; i++)
326
- // vars = vars.concat(variables(eqns[i]));
327
- // //remove duplicates
328
- // vars = core.Utils.arrayUnique(vars).sort();
329
- //
330
- // //done
331
- // return vars;
332
- // },
333
- /**
334
- * Solve a set of circle equations.
335
- * @param {Symbol[]} eqns
336
- * @returns {Array}
337
- */
338
- solveCircle: function (eqns, vars) {
339
- // Convert the variables to symbols
340
- var svars = vars.map(function (x) {
341
- return _.parse(x)
342
- });
343
-
344
- var deg = [];
345
-
346
- var solutions = [];
347
-
348
- // Get the degree for the equations
349
- for(var i = 0; i < eqns.length; i++) {
350
- var d = [];
351
- for(var j = 0; j < svars.length; j++) {
352
- d.push(Number(core.Algebra.degree(eqns[i], svars[j])));
353
- }
354
- // Store the total degree
355
- d.push(core.Utils.arraySum(d, true));
356
- deg.push(d);
357
- }
358
-
359
- var a = eqns[0];
360
- var b = eqns[1];
361
-
362
- if(deg[0][2] > deg[1][2]) {
363
- [b, a] = [a, b];
364
- [deg[1], deg[0]] = [deg[0], deg[1]];
365
- }
366
-
367
- // Only solve it's truly a circle
368
- if(deg[0][0] === 1 && deg[0][2] === 2 && deg[1][0] === 2 && deg[1][2] === 4) {
369
- // For clarity we'll refer to the variables as x and y
370
- var x = vars[0];
371
- var y = vars[1];
372
-
373
- // We can now get the two points for y
374
- var y_points = solve(_.parse(b, knownVariable(x, solve(_.parse(a), x)[0])), y).map(function (x) {
375
- return x.toString();
376
- });
377
-
378
- // Since we now know y we can get the two x points from the first equation
379
- var x_points = [
380
- solve(_.parse(a, knownVariable(y, y_points[0])))[0].toString()
381
- ];
382
-
383
- if(y_points[1]) {
384
- x_points.push(solve(_.parse(a, knownVariable(y, y_points[1])))[0].toString());
385
- }
386
-
387
- if(Settings.SOLUTIONS_AS_OBJECT) {
388
- var solutions = {};
389
- solutions[x] = x_points;
390
- solutions[y] = y_points;
391
- }
392
- else {
393
- y_points.unshift(y);
394
- x_points.unshift(x);
395
- solutions = [x_points, y_points];
396
- }
397
- }
398
-
399
- return solutions;
400
- },
401
- /**
402
- * Solve a system of nonlinear equations
403
- * @param {Symbol[]} eqns The array of equations
404
- * @param {number} tries The maximum number of tries
405
- * @param {number} start The starting point where to start looking for solutions
406
- * @returns {Array}
407
- */
408
- solveNonLinearSystem: function (eqns, tries, start) {
409
- if(tries < 0) {
410
- return [];//can't find a solution
411
- }
412
-
413
- start = typeof start === 'undefined' ? core.Settings.NON_LINEAR_START : start;
414
-
415
- //the maximum number of times to jump
416
- var max_tries = core.Settings.MAX_NON_LINEAR_TRIES;
417
-
418
- //halfway through the tries
419
- var halfway = Math.floor(max_tries / 2);
420
-
421
- //initialize the number of tries to 10 if not specified
422
- tries = typeof tries === 'undefined' ? max_tries : tries;
423
-
424
- //a point at which we check to see if we're converging. By inspection it seems that we can
425
- //use around 20 iterations to see if we're converging. If not then we retry a jump of x
426
- var jump_at = core.Settings.NON_LINEAR_JUMP_AT;
427
-
428
- //we jump by this many points at each pivot point
429
- var jump = core.Settings.NON_LINEAR_JUMP_SIZE;
430
-
431
- //used to check if we actually found a solution or if we gave up. Assume we will find a solution.
432
- var found = true;
433
-
434
- var create_subs = function (vars, matrix) {
435
- return vars.map(function (x, i) {
436
- return Number(matrix.get(i, 0));
437
- });
438
- };
439
-
440
- var vars = core.Utils.arrayGetVariables(eqns);
441
- var jacobian = core.Matrix.jacobian(eqns, vars, function (x) {
442
- return build(x, vars);
443
- }, true);
444
-
445
- var max_iter = core.Settings.MAX_NEWTON_ITERATIONS;
446
- var o, y, iters, xn1, norm, lnorm, xn, d;
447
-
448
- var f_eqns = eqns.map(function (eq) {
449
- return build(eq, vars);
450
- });
451
-
452
- var J = jacobian.map(function (e) {
453
- return build(e, vars);
454
- }, true);
455
- //initial values
456
- xn1 = core.Matrix.cMatrix(0, vars);
457
-
458
- //initialize the c matrix with something close to 0.
459
- var c = core.Matrix.cMatrix(start, vars);
460
-
461
- iters = 0;
462
-
463
- //start of algorithm
464
- do {
465
- //if we've reached the max iterations then exit
466
- if(iters > max_iter) {
467
- break;
468
- found = false;
469
- }
470
-
471
- //set the substitution object
472
- o = create_subs(vars, c);
473
-
474
- //set xn
475
- xn = c.clone();
476
-
477
- //make all the substitutions for each of the equations
478
- f_eqns.forEach(function (f, i) {
479
- c.set(i, 0, f.apply(null, o));
480
- });
481
-
482
- var m = new core.Matrix();
483
- J.each(function (fn, i, j) {
484
- var ans = fn.apply(null, o);
485
- m.set(i, j, ans);
486
- });
487
-
488
- m = m.invert();
489
-
490
- //preform the elimination
491
- y = _.multiply(m, c).negate();
492
-
493
- //the callback is to avoid overflow in the coeffient denonimator
494
- //it converts it to a decimal and then back to a fraction. Some precision
495
- //is lost be it's better than overflow.
496
- d = y.subtract(xn1, function (x) {
497
- return _.parse(Number(x));
498
- });
499
-
500
- xn1 = xn.add(y, function (x) {
501
- return _.parse(Number(x));
502
- });
503
-
504
- //move c is now xn1
505
- c = xn1;
506
-
507
- //get the norm
508
-
509
- //the expectation is that we're converging to some answer as this point regardless of where we start
510
- //this may have to be adjusted at some point because of erroneous assumptions
511
- if(iters >= jump_at) {
512
- //check the norm. If the norm is greater than one then it's time to try another point
513
- if(norm > 1) {
514
- //reset the start point at halway
515
- if(tries === halfway)
516
- start = 0;
517
- var sign = tries > halfway ? 1 : -1; //which side are we incrementing
518
- //we increment +n at one side and -n at the other.
519
- n = (tries % Math.floor(halfway)) + 1;
520
- //adjust the start point
521
- start += (sign * n * jump);
522
- //call restart
523
- return __.solveNonLinearSystem(eqns, --tries, start);
524
- }
525
- }
526
- lnorm = norm;
527
- iters++;
528
- norm = d.max();
529
-
530
- //exit early. Revisit if we get bugs
531
- if(Number(norm) === Number(lnorm)) {
532
- break;
533
- }
534
- }
535
- while(Number(norm) >= Number.EPSILON)
536
-
537
- //return a blank set if nothing was found;
538
- if(!found)
539
- return [];
540
-
541
- //return c since that's the answer
542
- return __.systemSolutions(c, vars, true, function (x) {
543
- return core.Utils.round(Number(x), 14);
544
- });
545
- },
546
- systemSolutions: function (result, vars, expand_result, callback) {
547
- var solutions = core.Settings.SOLUTIONS_AS_OBJECT ? {} : [];
548
-
549
- result.each(function (e, idx) {
550
- var solution = (expand_result ? _.expand(e) : e).valueOf();
551
- if(callback)
552
- solution = callback.call(e, solution);
553
- var variable = vars[idx];
554
- if(core.Settings.SOLUTIONS_AS_OBJECT) {
555
- solutions[variable] = solution;
556
- }
557
- else
558
- solutions.push([variable, solution]); /*NO*/
559
- });
560
- //done
561
- return solutions;
562
- },
563
- /**
564
- * Solves a system of equations by substitution. This is useful when
565
- * no distinct solution exists. e.g. a line, plane, etc.
566
- * @param {Array} eqns
567
- * @returns {Array}
568
- */
569
- solveSystemBySubstitution: function (eqns) {
570
- // Assume at least 2 equations. The function variables will just return an empty array if undefined is provided
571
- var vars_a = variables(eqns[0]);
572
- var vars_b = variables(eqns[1]);
573
- // Check if it's a circle equation
574
- if(eqns.length === 2 && vars_a.length === 2 && core.Utils.arrayEqual(vars_a, vars_b)) {
575
- return __.solveCircle(eqns, vars_a);
576
- }
577
-
578
- return []; // return an empty set
579
- },
580
-
581
- //https://www.lakeheadu.ca/sites/default/files/uploads/77/docs/RemaniFinal.pdf
582
- /**
583
- * Solves a systems of equations
584
- * @param {Array} eqns An array of equations
585
- * @param {Array} var_array An array of variables
586
- * @returns {Array|object}
587
- */
588
- solveSystem: function (eqns, var_array) {
589
- //check if a var_array was specified
590
- //nerdamer.clearVars();// this deleted ALL variables: not what we want
591
- //parse all the equations to LHS. Remember that they come in as strings
592
- for(var i = 0; i < eqns.length; i++)
593
- eqns[i] = __.toLHS(eqns[i]);
594
-
595
- var l = eqns.length,
596
- m = new core.Matrix(),
597
- c = new core.Matrix(),
598
- expand_result = false,
599
- vars;
600
-
601
- if(typeof var_array === 'undefined') {
602
- //check to make sure that all the equations are linear
603
- if(!_A.allLinear(eqns)) {
604
- try {
605
- return __.solveNonLinearSystem(eqns);
606
- }
607
- catch(e) {
608
- if(e instanceof core.exceptions.DivisionByZero) {
609
- return __.solveSystemBySubstitution(eqns);
610
- }
611
- }
612
- }
613
-
614
- vars = core.Utils.arrayGetVariables(eqns);
615
-
616
- // If the system only has one variable then we solve for the first one and
617
- // then test the remaining equations with that solution. If any of the remaining
618
- // equation fails then the system has no solution
619
- if(vars.length === 1) {
620
- var n = 0,
621
- sol, e;
622
- do {
623
- var e = eqns[n].clone();
624
-
625
- if(n > 0) {
626
- e = e.sub(vars[0], sol[0]);
627
- }
628
-
629
- sol = solve(e, vars[0]);
630
- // Skip the first one
631
- if(n === 0)
632
- continue;
633
- }
634
- while(++n < eqns.length)
635
-
636
- // Format the output
637
- var solutions;
638
- if(Settings.SOLUTIONS_AS_OBJECT) {
639
- solutions = {};
640
- solutions[vars[0]] = sol;
641
- }
642
- else if(sol.length === 0) {
643
- solutions = sol; // No solutions
644
- }
645
- else {
646
- solutions = [vars[0], sol];
647
- }
648
-
649
- return solutions;
650
- }
651
-
652
- // Deal with redundant equations as expressed in #562
653
- // The fix is to remove all but the number of equations equal to the number
654
- // of variables. We then solve those and then evaluate the remaining equations
655
- // with those solutions. If the all equal true then those are just redundant
656
- // equations and we can return the solution set.
657
- if(vars.length < eqns.length) {
658
- var reduced = [];
659
- var n = eqns.length;
660
- for(var i = 0; i < n - 1; i++) {
661
- reduced.push(_.parse(eqns[i]));
662
- }
663
-
664
- var knowns = {};
665
- var solutions = __.solveSystem(reduced, vars);
666
- // The solutions may have come back as an array
667
- if(Array.isArray(solutions)) {
668
- solutions.forEach(function (sol) {
669
- knowns[sol[0]] = sol[1];
670
- });
671
- }
672
- else {
673
- knowns = solutions;
674
- }
675
-
676
- // Start by assuming they will all evaluate to zero. If even one fails
677
- // then all zero will be false
678
- var all_zero = true;
679
- // Check if the last solution evalutes to zero given these solutions
680
- for(var i = n - 1; i < n; i++) {
681
- if(!_.parse(eqns[i], knowns).equals(0)) {
682
- all_zero = false;
683
- }
684
- }
685
-
686
- if(all_zero) {
687
- return solutions;
688
- }
689
- }
690
-
691
- // deletes only the variables of the linear equations in the nerdamer namespace
692
- for(var i = 0; i < vars.length; i++) {
693
- nerdamer.setVar(vars[i], "delete");
694
- }
695
- // TODO: move this to cMatrix or something similar
696
- // populate the matrix
697
- for(var i = 0; i < l; i++) {
698
- var e = eqns[i]; //store the expression
699
- // Iterate over the columns
700
- for(var j = 0; j < vars.length; j++) {
701
- var v = vars[j];
702
- var coeffs = [];
703
- e.each(function (x) {
704
- if(x.contains(v)) {
705
- coeffs = coeffs.concat(x.coeffs());
706
- }
707
- });
708
-
709
- var cf = core.Utils.arraySum(coeffs);
710
- m.set(i, j, cf);
711
- }
712
-
713
- //strip the variables from the symbol so we're left with only the zeroth coefficient
714
- //start with the symbol and remove each variable and its coefficient
715
- var num = e.clone();
716
- vars.map(function (e) {
717
- num = num.stripVar(e, true);
718
- });
719
- c.set(i, 0, num.negate());
720
- }
721
- }
722
- else {
723
- /**
724
- * The idea is that we loop through each equation and then expand it. Afterwards we loop
725
- * through each term and see if and check to see if it matches one of the variables.
726
- * When a match is found we mark it. No other match should be found for that term. If it
727
- * is we stop since it's not linear.
728
- */
729
- vars = var_array;
730
- expand_result = true;
731
- for(i = 0; i < l; i++) {
732
- //prefill
733
- c.set(i, 0, new Symbol(0));
734
- var e = _.expand(eqns[i]).collectSymbols(); //expand and store
735
- //go trough each of the variables
736
- for(var j = 0; j < var_array.length; j++) {
737
- m.set(i, j, new Symbol(0));
738
- var v = var_array[j];
739
- //go through the terms and sort the variables
740
- for(var k = 0; k < e.length; k++) {
741
- var term = e[k],
742
- check = false;
743
- for(var z = 0; z < var_array.length; z++) {
744
- //check to see if terms contain multiple variables
745
- if(term.contains(var_array[z])) {
746
- if(check)
747
- core.err('Multiple variables found for term ' + term);
748
- check = true;
749
- }
750
- }
751
- //we made sure that every term contains one variable so it's safe to assume that if the
752
- //variable is found then the remainder is the coefficient.
753
- if(term.contains(v)) {
754
- var tparts = explode(remove(e, k), v);
755
- m.set(i, j, _.add(m.get(i, j), tparts[0]));
756
- }
757
- }
758
- }
759
- //all the remaining terms go to the c matrix
760
- for(k = 0; k < e.length; k++) {
761
- c.set(i, 0, _.add(c.get(i, 0), e[k]));
762
- }
763
- }
764
- //consider case (a+b)*I+u
765
- }
766
-
767
- //check if the system has a distinct solution
768
- if(vars.length !== eqns.length || m.determinant().equals(0)) {
769
- // solve the system by hand
770
- //return __.solveSystemBySubstitution(eqns, vars, m, c);
771
- throw new core.exceptions.SolveError('System does not have a distinct solution');
772
- }
773
-
774
- // Use M^-1*c to solve system
775
- m = m.invert();
776
- var result = m.multiply(c);
777
- //correct the sign as per issue #410
778
- if(core.Utils.isArray(var_array))
779
- result.each(function (x) {
780
- return x.negate();
781
- });
782
-
783
- return __.systemSolutions(result, vars, expand_result);
784
- },
785
- /**
786
- * The quadratic function but only one side.
787
- * @param {Symbol} c
788
- * @param {Symbol} b
789
- * @param {Symbol} a
790
- * @returns {Symbol}
791
- */
792
- quad: function (c, b, a) {
793
- var discriminant = _.subtract(_.pow(b.clone(), Symbol(2)), _.multiply(_.multiply(a.clone(), c.clone()), Symbol(4)))/*b^2 - 4ac*/;
794
- // Fix for #608
795
- discriminant = _.expand(discriminant);
796
- var det = _.pow(discriminant, Symbol(0.5));
797
- var den = _.parse(_.multiply(new Symbol(2), a.clone()));
798
- var retval = [
799
- _.parse(format('(-({0})+({1}))/({2})', b, det, den)),
800
- _.parse(format('(-({0})-({1}))/({2})', b, det, den))
801
- ];
802
-
803
- return retval;
804
- },
805
- /**
806
- * The cubic equation
807
- * http://math.stackexchange.com/questions/61725/is-there-a-systematic-way-of-solving-cubic-equations
808
- * @param {Symbol} d_o
809
- * @param {Symbol} c_o
810
- * @param {Symbol} b_o
811
- * @param {Symbol} a_o
812
- * @returns {Array}
813
- */
814
- cubic: function (d_o, c_o, b_o, a_o) {
815
- //convert everything to text
816
- var a = a_o.text(), b = b_o.text(), c = c_o.text(), d = d_o.text();
817
-
818
- var t = `(-(${b})^3/(27*(${a})^3)+(${b})*(${c})/(6*(${a})^2)-(${d})/(2*(${a})))`;
819
- var u = `((${c})/(3*(${a}))-(${b})^2/(9*(${a})^2))`;
820
- var v = `(${b})/(3*(${a}))`;
821
- var x = `((${t})+sqrt((${t})^2+(${u})^3))^(1/3)+((${t})-sqrt((${t})^2+(${u})^3))^(1/3)-(${v})`;
822
-
823
- // Convert a to one
824
- var w = '1/2+sqrt(3)/2*i'; // Cube root of unity
825
-
826
- return [
827
- _.parse(x),
828
- _.parse(`(${x})(${w})`),
829
- _.parse(`(${x})(${w})^2`)
830
- ];
831
- },
832
- /**
833
- * The quartic equation
834
- * @param {Symbol} e
835
- * @param {Symbol} d
836
- * @param {Symbol} c
837
- * @param {Symbol} b
838
- * @param {Symbol} a
839
- * @returns {Array}
840
- */
841
- quartic: function (e, d, c, b, a) {
842
- var scope = {};
843
- core.Utils.arrayUnique(variables(a).concat(variables(b))
844
- .concat(variables(c)).concat(variables(d)).concat(variables(e)))
845
- .map(function (x) {
846
- scope[x] = 1;
847
- });
848
- a = a.toString();
849
- b = b.toString();
850
- c = c.toString();
851
- d = d.toString();
852
- e = e.toString();
853
- var p, q, D, D0, D1, Q, x1, x2, x3, x4;
854
- /*var D = core.Utils.block('PARSE2NUMBER', function() {
855
- return _.parse(format("256*({0})^3*({4})^3-192*({0})^2*({1})*({3})*({4})^2-128*({0})^2*({2})^2*({4})^2+144*({0})^2*({2})*({3})^2*({4})"+
856
- "-27*({0})^2*({3})^4+144*({0})*({1})^2*({2})*({4})^2-6*({0})*({1})^2*({3})^2*({4})-80*({0})*({1})*({2})^2*({3})*({4})+18*({0})*({1})*({2})*({3})^3"+
857
- "+16*({0})*({2})^4*({4})-4*({0})*({2})^3*({3})^2-27*({1})^4*({4})^2+18*({1})^3*({2})*({3})*({4})-4*({1})^3*({3})^3-4*({1})^2*({2})^3*({4})+({1})^2*({2})^2*({3})^2",
858
- a, b, c, d, e), scope);
859
- });*/
860
-
861
- p = _.parse(format("(8*({0})*({2})-3*({1})^2)/(8*({0})^2)", a, b, c)).toString(); //a, b, c
862
- q = _.parse(format("(({1})^3-4*({0})*({1})*({2})+8*({0})^2*({3}))/(8*({0})^3)", a, b, c, d)).toString();//a, b, c, d, e
863
- D0 = _.parse(format("12*({0})*({4})-3*({1})*({3})+({2})^2", a, b, c, d, e)).toString(); //a, b, c, d, e
864
- D1 = _.parse(format("2*({2})^3-9*({1})*({2})*({3})+27*({1})^2*({4})+27*({0})*({3})^2-72*({0})*({2})*({4})", a, b, c, d, e)).toString(); //a, b, c, d, e
865
- Q = _.parse(format("((({1})+(({1})^2-4*({0})^3)^(1/2))/2)^(1/3)", D0, D1)).toString(); //D0, D1
866
- S = _.parse(format("(1/2)*(-(2/3)*({1})+(1/(3*({0}))*(({2})+(({3})/({2})))))^(1/2)", a, p, Q, D0)).toString(); //a, p, Q, D0
867
- x1 = _.parse(format("-(({1})/(4*({0})))-({4})+(1/2)*sqrt(-4*({4})^2-2*({2})+(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
868
- x2 = _.parse(format("-(({1})/(4*({0})))-({4})-(1/2)*sqrt(-4*({4})^2-2*({2})+(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
869
- x3 = _.parse(format("-(({1})/(4*({0})))+({4})+(1/2)*sqrt(-4*({4})^2-2*({2})-(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
870
- x4 = _.parse(format("-(({1})/(4*({0})))+({4})-(1/2)*sqrt(-4*({4})^2-2*({2})-(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
871
- return [x1, x2, x3, x4];
872
- },
873
- /**
874
- * Breaks the equation up in its factors and tries to solve the smaller parts
875
- * @param {Symbol} symbol
876
- * @param {String} solve_for
877
- * @returns {Array}
878
- */
879
- divideAndConquer: function (symbol, solve_for) {
880
- var sols = [];
881
- //see if we can solve the factors
882
- var factors = core.Algebra.Factor.factor(symbol);
883
- if(factors.group === CB) {
884
- factors.each(function (x) {
885
- x = Symbol.unwrapPARENS(x);
886
- sols = sols.concat(solve(x, solve_for));
887
- });
888
- }
889
- return sols;
890
- },
891
- /**
892
- * Attempts to solve the equation assuming it's a polynomial with numeric coefficients
893
- * @param {Symbol} eq
894
- * @param {String} solve_for
895
- * @returns {Array}
896
- */
897
- csolve: function (eq, solve_for) {
898
- return core.Utils.block('IGNORE_E', function () {
899
- var f, p, pn, n, pf, r, theta, sr, sp, roots;
900
- roots = [];
901
- f = core.Utils.decompose_fn(eq, solve_for, true);
902
- if(f.x.group === S) {
903
- p = _.parse(f.x.power);
904
- pn = Number(p);
905
- n = _.pow(_.divide(f.b.negate(), f.a), p.invert());
906
- pf = Symbol.toPolarFormArray(n);
907
- r = pf[0];
908
- theta = pf[1];
909
- sr = r.toString();
910
- sp = p.toString();
911
- var k, root, str;
912
- for(var i = 0; i < pn; i++) {
913
- k = i;
914
- str = format('({0})*e^(2*{1}*pi*{2}*{3})', sr, k, p, core.Settings.IMAGINARY);
915
- root = _.parse(str);
916
- roots.push(root);
917
- }
918
- }
919
- return roots;
920
- }, true);
921
- },
922
- /**
923
- * Generates starting points for the Newton solver given an expression at zero.
924
- * It beings by check if zero is a good point and starts expanding by a provided step size.
925
- * Builds on the fact that if the sign changes over an interval then a zero
926
- * must exist on that interval
927
- * @param {Symbol} symbol
928
- * @param {Number} step
929
- * @param {Array} points
930
- * @returns {Array}
931
- */
932
- getPoints: function (symbol, step, points) {
933
- step = step || 0.01;
934
- points = points || [];
935
- var f = build(symbol);
936
- var x0 = 0;
937
-
938
- var start = Math.round(x0),
939
- last = f(start),
940
- last_sign = last / Math.abs(last),
941
- rside = core.Settings.ROOTS_PER_SIDE, // the max number of roots on right side
942
- lside = rside; // the max number of roots on left side
943
- // check around the starting point
944
- points.push(Math.floor(start / 2)); //half way from zero might be a good start
945
- points.push(Math.abs(start)); //|f(0)| could be a good start
946
- points.push(start);//|f(0)| could be a good start
947
- //adjust for log. A good starting point to include for log is 0.1
948
- symbol.each(function (x) {
949
- if(x.containsFunction(core.Settings.LOG))
950
- points.push(0.1);
951
- });
952
-
953
- var left = range(-core.Settings.SOLVE_RADIUS, start, step),
954
- right = range(start, core.Settings.SOLVE_RADIUS, step);
955
-
956
- var test_side = function (side, num_roots) {
957
- var xi, val, sign;
958
- var hits = [];
959
- for(var i = 0, l = side.length; i < l; i++) {
960
- xi = side[i]; //the point being evaluated
961
- val = f(xi);
962
- sign = val / Math.abs(val);
963
- //Don't add non-numeric values
964
- if(isNaN(val) || !isFinite(val) || hits.length > num_roots) {
965
- continue;
966
- }
967
-
968
- //compare the signs. The have to be different if they cross a zero
969
- if(sign !== last_sign) {
970
- hits.push(xi); //take note of the possible zero location
971
- }
972
- last_sign = sign;
973
- }
974
-
975
- points = points.concat(hits);
976
- };
977
-
978
- test_side(left, lside);
979
- test_side(right, rside);
980
-
981
- return points;
982
- },
983
- /**
984
- * Implements the bisection method. Returns undefined in no solution is found
985
- * @param {number} point
986
- * @param {function} f
987
- * @returns {undefined | number}
988
- */
989
- bisection: function (point, f) {
990
- var left = point - 1;
991
- var right = point + 1;
992
- // First test if this point is even worth evaluating. It should
993
- // be crossing the x axis so the signs should be different
994
- if(Math.sign(f(left)) !== Math.sign(f(right))) {
995
- var safety = 0;
996
-
997
- var epsilon, middle;
998
-
999
- do {
1000
- epsilon = Math.abs(right - left);
1001
- // Safety against an infinite loop
1002
- if(safety++ > core.Settings.MAX_BISECTION_ITER || isNaN(epsilon)) {
1003
- return;
1004
- }
1005
- // Calculate the middle point
1006
- middle = (left + right) / 2;
1007
-
1008
- if(f(left) * f(middle) > 0) {
1009
- left = middle;
1010
- }
1011
- else {
1012
- right = middle;
1013
- }
1014
- }
1015
- while(epsilon >= Settings.EPSILON);
1016
-
1017
- var solution = (left + right) / 2;
1018
-
1019
- // Test the solution to make sure that it's within tolerance
1020
- var x_point = f(solution);
1021
-
1022
- if(!isNaN(x_point) && Math.abs(x_point) <= core.Settings.BI_SECTION_EPSILON) {
1023
- // Returns too many junk solutions if not rounded at 13th place.
1024
- return core.Utils.round(solution, 13);
1025
- }
1026
- }
1027
- },
1028
- /**
1029
- * Implements Newton's iterations. Returns undefined if no solutions if found
1030
- * @param {number} point
1031
- * @param {function} f
1032
- * @param {function} fp
1033
- * @returns {undefined|number}
1034
- */
1035
- Newton: function (point, f, fp) {
1036
- var maxiter = core.Settings.MAX_NEWTON_ITERATIONS,
1037
- iter = 0;
1038
- //first try the point itself. If it's zero viola. We're done
1039
- var x0 = point, x;
1040
- do {
1041
- var fx0 = f(x0); //store the result of the function
1042
- //if the value is zero then we're done because 0 - (0/d f(x0)) = 0
1043
- if(x0 === 0 && fx0 === 0) {
1044
- x = 0;
1045
- break;
1046
- }
1047
-
1048
- iter++;
1049
- if(iter > maxiter)
1050
- return; //naximum iterations reached
1051
-
1052
- x = x0 - fx0 / fp(x0);
1053
- var e = Math.abs(x - x0);
1054
- x0 = x;
1055
- }
1056
- while(e > Settings.NEWTON_EPSILON)
1057
-
1058
- //check if the number is indeed zero. 1e-13 seems to give the most accurate results
1059
- if(Math.abs(f(x)) <= Settings.EPSILON)
1060
- return x;
1061
- },
1062
- rewrite: function (rhs, lhs, for_variable) {
1063
- lhs = lhs || new Symbol(0);
1064
- if(rhs.isComposite() && rhs.isLinear()) {
1065
- //try to isolate the square root
1066
- //container for the square roots
1067
- var sqrts = [];
1068
- //all else
1069
- var rem = [];
1070
- rhs.each(function (x) {
1071
- x = x.clone();
1072
- if(x.fname === 'sqrt' && x.contains(for_variable)) {
1073
- sqrts.push(x);
1074
- }
1075
- else {
1076
- rem.push(x);
1077
- }
1078
- }, true);
1079
-
1080
- if(sqrts.length === 1) {
1081
- //move the remainder to the RHS
1082
- lhs = _.expand(_.pow(_.subtract(lhs, core.Utils.arraySum(rem)), new Symbol(2)));
1083
- //square both sides
1084
- rhs = _.expand(_.pow(Symbol.unwrapSQRT(sqrts[0]), new Symbol(2)));
1085
- }
1086
- }
1087
- else {
1088
- rhs = Symbol.unwrapSQRT(_.expand(rhs)); //expand the term expression go get rid of quotients when possible
1089
- }
1090
-
1091
- var c = 0, //a counter to see if we have all terms with the variable
1092
- l = rhs.length;
1093
- //try to rewrite the whole thing
1094
- if(rhs.group === CP && rhs.contains(for_variable) && rhs.isLinear()) {
1095
- rhs.distributeMultiplier();
1096
- var t = new Symbol(0);
1097
- //first bring all the terms containing the variable to the lhs
1098
- rhs.each(function (x) {
1099
- if(x.contains(for_variable)) {
1100
- c++;
1101
- t = _.add(t, x.clone());
1102
- }
1103
- else
1104
- lhs = _.subtract(lhs, x.clone());
1105
- });
1106
- rhs = t;
1107
-
1108
- //if not all the terms contain the variable so it's in the form
1109
- //a*x^2+x
1110
- if(c !== l) {
1111
- return __.rewrite(rhs, lhs, for_variable);
1112
- }
1113
- else {
1114
- return [rhs, lhs];
1115
- }
1116
- }
1117
- else if(rhs.group === CB && rhs.contains(for_variable) && rhs.isLinear()) {
1118
- if(rhs.multiplier.lessThan(0)) {
1119
- rhs.multiplier = rhs.multiplier.multiply(new core.Frac(-1));
1120
- lhs.multiplier = lhs.multiplier.multiply(new core.Frac(-1));
1121
- }
1122
- if(lhs.equals(0))
1123
- return new Symbol(0);
1124
- else {
1125
- var t = new Symbol(1);
1126
- rhs.each(function (x) {
1127
- if(x.contains(for_variable))
1128
- t = _.multiply(t, x.clone());
1129
- else
1130
- lhs = _.divide(lhs, x.clone());
1131
- });
1132
- rhs = t;
1133
- return __.rewrite(rhs, lhs, for_variable);
1134
-
1135
- }
1136
- }
1137
- else if(!rhs.isLinear() && rhs.contains(for_variable)) {
1138
- var p = _.parse(rhs.power.clone().invert());
1139
- rhs = _.pow(rhs, p.clone());
1140
- lhs = _.pow(_.expand(lhs), p.clone());
1141
- return __.rewrite(rhs, lhs, for_variable);
1142
- }
1143
- else if(rhs.group === FN || rhs.group === S || rhs.group === PL) {
1144
- return [rhs, lhs];
1145
- }
1146
- },
1147
- sqrtSolve: function (symbol, v) {
1148
- var sqrts = new Symbol(0);
1149
- var rem = new Symbol(0);
1150
- if(symbol.isComposite()) {
1151
- symbol.each(function (x) {
1152
- if(x.fname === 'sqrt' && x.contains(v)) {
1153
- sqrts = _.add(sqrts, x.clone());
1154
- }
1155
- else {
1156
- rem = _.add(rem, x.clone());
1157
- }
1158
- });
1159
- //quick and dirty ATM
1160
- if(!sqrts.equals(0)) {
1161
- var t = _.expand(_.multiply(_.parse(symbol.multiplier), _.subtract(_.pow(rem, new Symbol(2)), _.pow(sqrts, new Symbol(2)))));
1162
- //square both sides
1163
- var solutions = solve(t, v);
1164
- //test the points. The dumb way of getting the answers
1165
- solutions = solutions.filter(function (e) {
1166
- if(e.isImaginary())
1167
- return e;
1168
- var subs = {};
1169
- subs[v] = e;
1170
- var point = evaluate(symbol, subs);
1171
- if(point.equals(0))
1172
- return e;
1173
- });
1174
- return solutions;
1175
- }
1176
- }
1177
- }
1178
- };
1179
-
1180
- /*
1181
- *
1182
- * @param {String[]|String|Equation} eqns
1183
- * @param {String} solve_for
1184
- * @param {Array} solutions
1185
- * @param {Number} depth
1186
- * @param {String|Equation} fn
1187
- * @returns {Array}
1188
- */
1189
- var solve = function (eqns, solve_for, solutions, depth, fn) {
1190
- depth = depth || 0;
1191
-
1192
- if(depth++ > Settings.MAX_SOLVE_DEPTH) {
1193
- return solutions;
1194
- }
1195
-
1196
- //make preparations if it's an Equation
1197
- if(eqns instanceof Equation) {
1198
- //if it's zero then we're done
1199
- if(eqns.isZero()) {
1200
- return [new Symbol(0)];
1201
- }
1202
- //if the lhs = x then we're done
1203
- if(eqns.LHS.equals(solve_for) && !eqns.RHS.contains(solve_for)) {
1204
- return [eqns.RHS];
1205
- }
1206
- //if the rhs = x then we're done
1207
- if(eqns.RHS.equals(solve_for) && !eqns.LHS.contains(solve_for)) {
1208
- return [eqns.LHS];
1209
- }
1210
- }
1211
-
1212
- //unwrap the vector since what we want are the elements
1213
- if(eqns instanceof core.Vector)
1214
- eqns = eqns.elements;
1215
- solve_for = solve_for || 'x'; //assumes x by default
1216
- //If it's an array then solve it as a system of equations
1217
- if(isArray(eqns)) {
1218
- return __.solveSystem.apply(undefined, arguments);
1219
- }
1220
-
1221
- // Parse out functions. Fix for issue #300
1222
- // eqns = core.Utils.evaluate(eqns);
1223
- solutions = solutions || [];
1224
- //mark existing solutions as not to have duplicates
1225
- var existing = {};
1226
-
1227
- // Easy fail. If it's a rational function and the denominator is zero
1228
- // the we're done. Issue #555
1229
- var known = {};
1230
- known[solve_for] = 0;
1231
- if(isSymbol(eqns) && evaluate(eqns.getDenom(), known).equals(0) === true) {
1232
- return solutions;
1233
- }
1234
-
1235
- // Is usued to add solutions to set.
1236
- // TODO: Set is now implemented and should be utilized
1237
- var add_to_result = function (r, has_trig) {
1238
- var r_is_symbol = isSymbol(r);
1239
- if(r === undefined || typeof r === 'number' && isNaN(r))
1240
- return;
1241
- if(isArray(r)) {
1242
- r.forEach(function (sol) {
1243
- add_to_result(sol);
1244
- });
1245
- }
1246
- else {
1247
- if(r.valueOf() !== 'null') {
1248
- // Call the pre-add function if defined. This could be useful for rounding
1249
- if(typeof core.Settings.PRE_ADD_SOLUTION === 'function') {
1250
- r = core.Settings.PRE_ADD_SOLUTION(r);
1251
- }
1252
-
1253
- if(!r_is_symbol) {
1254
- r = _.parse(r);
1255
- }
1256
- // try to convert the number to multiples of pi
1257
- if(core.Settings.make_pi_conversions && has_trig) {
1258
- var temp = _.divide(r.clone(), new Symbol(Math.PI)),
1259
- m = temp.multiplier,
1260
- a = Math.abs(m.num),
1261
- b = Math.abs(m.den);
1262
- if(a < 10 && b < 10)
1263
- r = _.multiply(temp, new Symbol('pi'));
1264
- }
1265
-
1266
- // And check if we get a number otherwise we might be throwing out symbolic solutions.
1267
- var r_str = r.toString();
1268
-
1269
- if(!existing[r_str]) {
1270
- solutions.push(r);
1271
- }
1272
- // Mark the answer as seen
1273
- existing[r_str] = true;
1274
- }
1275
- }
1276
- };
1277
-
1278
- // Maybe we get lucky. Try the point at the function. If it works we have a point
1279
- // If not it failed
1280
- if(eqns.group === S && eqns.contains(solve_for)) {
1281
- try {
1282
- var o = {};
1283
- o[solve_for] = 0;
1284
- evaluate(fn, o, 'numer');
1285
- add_to_result(new Symbol(0));
1286
- }
1287
- catch(e) {
1288
- // Do nothing;
1289
- }
1290
-
1291
- return solutions;
1292
- }
1293
- if(eqns.group === CB) {
1294
- // It suffices to solve for the numerator
1295
- var num = eqns.getNum();
1296
-
1297
- if(num.group === CB) {
1298
- var sf = String(solve_for); //everything else belongs to the coeff
1299
- //get the denominator and make sure it doesn't have x since we don't know how to solve for those
1300
- num.each(function (x) {
1301
- if(x.contains(sf))
1302
- solve(x, solve_for, solutions, depth, eqns);
1303
- });
1304
-
1305
- return solutions;
1306
- }
1307
-
1308
- return solve(num, solve_for, solutions, depth, fn);
1309
- }
1310
-
1311
- if(eqns.group === FN && eqns.fname === 'sqrt') {
1312
- eqns = _.pow(Symbol.unwrapSQRT(eqns), new Symbol(2));
1313
- }
1314
- //pass in false to not expand equations such as (x+y)^5.
1315
- //It suffices to solve for the numerator since there's no value in the denominator which yields a zero for the function
1316
- var eq = (core.Utils.isSymbol(eqns) ? eqns : __.toLHS(eqns, false)).getNum(),
1317
- vars = core.Utils.variables(eq), //get a list of all the variables
1318
- numvars = vars.length;//how many variables are we dealing with
1319
-
1320
- //it sufficient to solve (x+y) if eq is (x+y)^n since 0^n
1321
- if(core.Utils.isInt(eq.power) && eq.power > 0) {
1322
- eq = _.parse(eq).toLinear();
1323
- }
1324
-
1325
- //if we're dealing with a single variable then we first check if it's a
1326
- //polynomial (including rationals).If it is then we use the Jenkins-Traubb algorithm.
1327
- //Don't waste time
1328
- if(eq.group === S || eq.group === CB && eq.contains(solve_for)) {
1329
- return [new Symbol(0)];
1330
- }
1331
- //force to polynomial. We go through each and then we look at what it would
1332
- //take for its power to be an integer
1333
- //if the power is a fractional we divide by the fractional power
1334
- var fractionals = {},
1335
- cfact;
1336
-
1337
- var correct_denom = function (symbol) {
1338
- symbol = _.expand(symbol, {
1339
- expand_denominator: true,
1340
- expand_functions: true
1341
- });
1342
- var original = symbol.clone(); //preserve the original
1343
-
1344
- if(symbol.symbols) {
1345
- for(var x in symbol.symbols) {
1346
- var sym = symbol.symbols[x];
1347
-
1348
- //get the denominator of the sub-symbol
1349
- var den = sym.getDenom();
1350
-
1351
- if(!den.isConstant(true) && symbol.isComposite()) {
1352
- var t = new Symbol(0);
1353
- symbol.each(function (e) {
1354
- t = _.add(t, _.multiply(e, den.clone()));
1355
- });
1356
-
1357
- return correct_denom(_.multiply(_.parse(symbol.multiplier), t));
1358
- }
1359
-
1360
- var parts = explode(sym, solve_for);
1361
- var is_sqrt = parts[1].fname === core.Settings.SQRT;
1362
- var v = Symbol.unwrapSQRT(parts[1]);
1363
- var p = v.power.clone();
1364
- //circular logic with sqrt. Since sqrt(x) becomes x^(1/2) which then becomes sqrt(x), this continues forever
1365
- //this needs to be terminated if p = 1/2
1366
- if(!isSymbol(p) && !p.equals(1 / 2)) {
1367
- if(p.den.gt(1)) {
1368
- if(is_sqrt) {
1369
- symbol = _.subtract(symbol, sym.clone());
1370
- symbol = _.add(symbol, _.multiply(parts[0].clone(), v));
1371
- return correct_denom(symbol);
1372
- }
1373
- var c = fractionals[p.den];
1374
- fractionals[p.den] = c ? c++ : 1;
1375
- }
1376
- else if(p.sign() === -1) {
1377
- var factor = _.parse(solve_for + '^' + Math.abs(p)); //this
1378
- //unwrap the symbol's denoniator
1379
- symbol.each(function (y, index) {
1380
- if(y.contains(solve_for)) {
1381
- symbol.symbols[index] = _.multiply(y, factor.clone());
1382
- }
1383
- });
1384
- fractionals = {};
1385
- return correct_denom(_.parse(symbol));
1386
- }
1387
- else if(sym.group === PL) {
1388
- var min_p = core.Utils.arrayMin(core.Utils.keys(sym.symbols));
1389
- if(min_p < 0) {
1390
- var factor = _.parse(solve_for + '^' + Math.abs(min_p));
1391
- var corrected = new Symbol(0);
1392
- original.each(function (x) {
1393
- corrected = _.add(corrected, _.multiply(x.clone(), factor.clone()));
1394
- }, true);
1395
- return corrected;
1396
- }
1397
- }
1398
- }
1399
- }
1400
- }
1401
-
1402
- return symbol;
1403
- };
1404
-
1405
-
1406
- //separate the equation
1407
- var separate = function (eq) {
1408
- var lhs = new Symbol(0),
1409
- rhs = new Symbol(0);
1410
- eq.each(function (x) {
1411
- if(x.contains(solve_for, true))
1412
- lhs = _.add(lhs, x.clone());
1413
- else
1414
- rhs = _.subtract(rhs, x.clone());
1415
- });
1416
- return [lhs, rhs];
1417
- };
1418
-
1419
- __.inverseFunctionSolve = function (name, lhs, rhs) {
1420
- //ax+b comes back as [a, x, ax, b];
1421
- var parts = explode(lhs.args[0], solve_for);
1422
- //check if x is by itself
1423
- var x = parts[1];
1424
- if(x.group === S) {
1425
- return _.divide(_.symfunction(name, [_.divide(rhs, _.parse(lhs.multiplier))]), parts[0]);
1426
- }
1427
-
1428
- };
1429
-
1430
- //first remove any denominators
1431
- eq = correct_denom(eq);
1432
-
1433
- if(eq.equals(0))
1434
- return [eq];
1435
- //correct fractionals. I can only handle one type right now
1436
- var fkeys = core.Utils.keys(fractionals);
1437
- if(fkeys.length === 1) {
1438
- //make a note of the factor
1439
- cfact = fkeys[0];
1440
- eq.each(function (x, index) {
1441
- if(x.contains(solve_for)) {
1442
- var parts = explode(x, solve_for);
1443
- var v = parts[1];
1444
- var p = v.power;
1445
- if(p.den.gt(1)) {
1446
- v.power = p.multiply(new core.Frac(cfact));
1447
- eq.symbols[index] = _.multiply(v, parts[0]);
1448
- }
1449
- }
1450
- });
1451
- eq = _.parse(eq);
1452
- }
1453
-
1454
- //try for nested sqrts as per issue #486
1455
- add_to_result(__.sqrtSolve(eq, solve_for));
1456
-
1457
- //polynomial single variable
1458
- if(numvars === 1) {
1459
- if(eq.isPoly(true)) {
1460
- //try to factor and solve
1461
- var factors = new core.Algebra.Classes.Factors();
1462
-
1463
- core.Algebra.Factor.factor(eq, factors);
1464
- //if the equation has more than one symbolic factor then solve those individually
1465
- if(factors.getNumberSymbolics() > 1) {
1466
- for(var x in factors.factors) {
1467
- add_to_result(solve(factors.factors[x], solve_for));
1468
- }
1469
- }
1470
- else {
1471
- var coeffs = core.Utils.getCoeffs(eq, solve_for),
1472
- deg = coeffs.length - 1,
1473
- was_calculated = false;
1474
- if(vars[0] === solve_for) {
1475
- //check to see if all the coefficients are constant
1476
- if(checkAll(coeffs, function (x) {
1477
- return x.group !== core.groups.N;
1478
- })) {
1479
- var roots = core.Algebra.proots(eq);
1480
- //if all the roots are integers then return those
1481
- if(checkAll(roots, function (x) {
1482
- return !core.Utils.isInt(x);
1483
- })) {
1484
- //roots have been calculates
1485
- was_calculated = true;
1486
- roots.map(function (x) {
1487
- add_to_result(new Symbol(x));
1488
- });
1489
- }
1490
- }
1491
-
1492
- if(!was_calculated) {
1493
- eqns = _.parse(eqns);
1494
- if(eqns instanceof core.Equation)
1495
- eqns = eqns.toLHS();
1496
-
1497
- //we can solve algebraically for degrees 1, 2, 3. The remainder we switch to Jenkins-
1498
- if(deg === 1)
1499
- add_to_result(_.divide(coeffs[0], coeffs[1].negate()));
1500
- else if(deg === 2) {
1501
- add_to_result(_.expand(__.quad.apply(undefined, coeffs)));
1502
- }
1503
-
1504
- else if(deg === 3) {
1505
- var solutions = []; //set to blank
1506
- //first try to factor and solve
1507
- var factored = core.Algebra.Factor.factor(eqns);
1508
-
1509
- //if it was successfully factored
1510
- var solutions = [];
1511
- if(solutions.length > 0)
1512
- add_to_result(solutions);
1513
- else
1514
- add_to_result(__.cubic.apply(undefined, coeffs));
1515
- }
1516
-
1517
- else {
1518
- /*
1519
- var sym_roots = csolve(eq, solve_for);
1520
- if(sym_roots.length === 0)
1521
- sym_roots = divnconsolve(eq, solve_for);
1522
- if(sym_roots.length > 0)
1523
- add_to_result(sym_roots);
1524
- else
1525
- */
1526
- _A.proots(eq).map(add_to_result);
1527
- }
1528
- }
1529
- }
1530
- }
1531
- }
1532
- else {
1533
- try {
1534
- // Attempt Newton
1535
- // Since it's not a polynomial then we'll try to look for a solution using Newton's method
1536
- var has_trig = eq.hasTrig();
1537
- // we get all the points where a possible zero might exist.
1538
- var points1 = __.getPoints(eq, 0.1);
1539
- var points2 = __.getPoints(eq, 0.05);
1540
- var points3 = __.getPoints(eq, 0.01);
1541
- var points = core.Utils.arrayUnique(points1.concat(points2).concat(points3)).sort(function (a, b) {
1542
- return a - b;
1543
- });
1544
- var i, point, solution;
1545
-
1546
- // Compile the function
1547
- var f = build(eq.clone());
1548
-
1549
- // First try to eliminate some points using bisection
1550
- var t_points = [];
1551
- for(i = 0; i < points.length; i++) {
1552
- point = points[i];
1553
-
1554
- // See if there's a solution at this point
1555
- solution = __.bisection(point, f);
1556
-
1557
- // If there's no solution then add it to the array for further investigation
1558
- if(typeof solution === 'undefined') {
1559
- t_points.push(point);
1560
- continue;
1561
- }
1562
-
1563
- // Add the solution to the solution set
1564
- add_to_result(solution, has_trig);
1565
- }
1566
-
1567
- // Reset the points to the remaining points
1568
- points = t_points;
1569
-
1570
- // Build the derivative and compile a function
1571
- var d = _C.diff(eq.clone());
1572
- var fp = build(d);
1573
- for(i = 0; i < points.length; i++) {
1574
- point = points[i];
1575
-
1576
- add_to_result(__.Newton(point, f, fp), has_trig);
1577
- }
1578
- solutions.sort();
1579
- }
1580
- catch(e) {
1581
- console.log(e);
1582
- }
1583
- }
1584
- }
1585
- else {
1586
- //The idea here is to go through the equation and collect the coefficients
1587
- //place them in an array and call the quad or cubic function to get the results
1588
- if(!eq.hasFunc(solve_for) && eq.isComposite()) {
1589
- try {
1590
- var factored = core.Algebra.Factor.factor(eq.clone());
1591
-
1592
- if(factored.group === CB) {
1593
- factored.each(function (x) {
1594
- add_to_result(solve(x, solve_for));
1595
- });
1596
- }
1597
- else {
1598
- var coeffs = core.Utils.getCoeffs(eq, solve_for);
1599
-
1600
- var l = coeffs.length,
1601
- deg = l - 1; //the degree of the polynomial
1602
- //get the denominator and make sure it doesn't have x
1603
-
1604
- //handle the problem based on the degree
1605
- switch(deg) {
1606
- case 0:
1607
- var separated = separate(eq);
1608
- var lhs = separated[0],
1609
- rhs = separated[1];
1610
-
1611
- if(lhs.group === core.groups.EX) {
1612
- var log = core.Settings.LOG;
1613
- var expr_str = `${log}((${rhs})/(${lhs.multiplier}))/${log}(${lhs.value})/${lhs.power.multiplier}`;
1614
- add_to_result(_.parse(expr_str));
1615
- }
1616
- break;
1617
- case 1:
1618
- //nothing to do but to return the quotient of the constant and the LT
1619
- //e.g. 2*x-1
1620
- add_to_result(_.divide(coeffs[0], coeffs[1].negate()));
1621
- break;
1622
- case 2:
1623
- add_to_result(__.quad.apply(undefined, coeffs));
1624
- break;
1625
- case 3:
1626
- add_to_result(__.cubic.apply(undefined, coeffs));
1627
- break;
1628
- case 4:
1629
- add_to_result(__.quartic.apply(undefined, coeffs));
1630
- break;
1631
- default:
1632
- add_to_result(__.csolve(eq, solve_for));
1633
- if(solutions.length === 0)
1634
- add_to_result(__.divideAndConquer(eq, solve_for));
1635
- }
1636
-
1637
- if(solutions.length === 0) {
1638
- //try factoring
1639
- add_to_result(solve(factored, solve_for, solutions, depth));
1640
- }
1641
- }
1642
-
1643
- }
1644
- catch(e) { /*something went wrong. EXITING*/
1645
- ;
1646
- }
1647
- }
1648
- else {
1649
- try {
1650
- var rw = __.rewrite(eq, null, solve_for);
1651
- var lhs = rw[0];
1652
- var rhs = rw[1];
1653
- if(lhs.group === FN) {
1654
- if(lhs.fname === 'abs') {
1655
- add_to_result([rhs.clone(), rhs.negate()]);
1656
- }
1657
- else if(lhs.fname === 'sin') {
1658
- //asin
1659
- add_to_result(__.inverseFunctionSolve('asin', lhs, rhs));
1660
- }
1661
- else if(lhs.fname === 'cos') {
1662
- //asin
1663
- add_to_result(__.inverseFunctionSolve('acos', lhs, rhs));
1664
- }
1665
- else if(lhs.fname === 'tan') {
1666
- //asin
1667
- add_to_result(__.inverseFunctionSolve('atan', lhs, rhs));
1668
- }
1669
- else if(lhs.fname === core.Settings.LOG) {
1670
- //ax+b comes back as [a, x, ax, b];
1671
- var parts = explode(lhs.args[0], solve_for);
1672
- //check if x is by itself
1673
- var x = parts[1];
1674
- if(x.group === S) {
1675
- rhs = _.divide(_.subtract(_.pow(lhs.args.length > 1 ? lhs.args[1] : new Symbol('e'), _.divide(rhs, _.parse(lhs.multiplier))), parts[3]), parts[0]);
1676
- var eq = new Equation(x, rhs).toLHS();
1677
- add_to_result(solve(eq, solve_for));
1678
- }
1679
- }
1680
- else
1681
- add_to_result(_.subtract(lhs, rhs));
1682
- }
1683
- else {
1684
- var neq = new Equation(lhs, rhs).toLHS(); //create a new equation
1685
-
1686
- if(neq.equals(eq))
1687
- throw new Error('Stopping. No stop condition exists');
1688
- add_to_result(solve(neq, solve_for));
1689
- }
1690
- }
1691
- catch(error) {
1692
- //Let's try this another way
1693
- try {
1694
- //1. if the symbol is in the form a*b*c*... then the solution is zero if
1695
- //either a or b or c is zero.
1696
- if(eq.group === CB)
1697
- add_to_result(0);
1698
- else if(eq.group === CP) {
1699
- var separated = separate(eq);
1700
- var lhs = separated[0],
1701
- rhs = separated[1];
1702
-
1703
- //reduce the equation
1704
- if(lhs.group === core.groups.EX && lhs.value === solve_for) {
1705
- //change the base of both sides
1706
- var p = lhs.power.clone().invert();
1707
- add_to_result(_.pow(rhs, p));
1708
- }
1709
- }
1710
- }
1711
- catch(error) {
1712
- ;
1713
- }
1714
- }
1715
- }
1716
- }
1717
-
1718
- if(cfact) {
1719
- solutions = solutions.map(function (x) {
1720
- return _.pow(x, new Symbol(cfact));
1721
- });
1722
- }
1723
-
1724
- // Perform some cleanup but don't do it agains arrays, etc
1725
- // Check it actually evaluates to zero
1726
- if(isSymbol(eqns)) {
1727
- var knowns = {};
1728
- solutions = solutions.filter(function (x) {
1729
- try {
1730
- knowns[solve_for] = x;
1731
- var zero = Number(evaluate(eqns, knowns));
1732
-
1733
- // Allow symbolic answers
1734
- if(isNaN(zero)) {
1735
- return true;
1736
- }
1737
- return true;
1738
- }
1739
- catch(e) {
1740
- return false;
1741
- }
1742
- });
1743
- }
1744
-
1745
- return solutions;
1746
- };
1747
-
1748
- //Register the functions for external use
1749
- nerdamer.register([
1750
- {
1751
- name: 'solveEquations',
1752
- parent: 'nerdamer',
1753
- numargs: -1,
1754
- visible: true,
1755
- build: function () {
1756
- return solve; //comment out to return a vector
1757
- /*
1758
- return function() {
1759
- return core.Utils.convertToVector(solve.apply(null, arguments));
1760
- };
1761
- */
1762
- }
1763
- },
1764
- {
1765
- name: 'solve',
1766
- parent: 'Solve',
1767
- numargs: 2,
1768
- visible: true,
1769
- build: function () {
1770
- return core.Solve.solve;
1771
- }
1772
- },
1773
- {
1774
- name: 'setEquation',
1775
- parent: 'Solve',
1776
- visible: true,
1777
- build: function () {
1778
- return setEq;
1779
- }
1780
- }
1781
- ]);
1782
- nerdamer.updateAPI();
1783
- })();