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/Algebra.js DELETED
@@ -1,4568 +0,0 @@
1
- /*
2
- * Author : Martin Donk
3
- * Website : http://www.nerdamer.com
4
- * Email : martin.r.donk@gmail.com
5
- * License : MIT
6
- * Source : https://github.com/jiggzson/nerdamer
7
- */
8
-
9
- /* global module, Function */
10
-
11
- if((typeof module) !== 'undefined') {
12
- var nerdamer = require('./nerdamer.core.js');
13
- require('./Calculus.js');
14
- }
15
-
16
- (function () {
17
- "use strict";
18
-
19
- /*shortcuts*/
20
- var core = nerdamer.getCore(),
21
- _ = core.PARSER,
22
- N = core.groups.N,
23
- P = core.groups.P,
24
- S = core.groups.S,
25
- EX = core.groups.EX,
26
- FN = core.groups.FN,
27
- PL = core.groups.PL,
28
- CP = core.groups.CP,
29
- CB = core.groups.CB,
30
- keys = core.Utils.keys,
31
- even = core.Utils.even,
32
- variables = core.Utils.variables,
33
- format = core.Utils.format,
34
- round = core.Utils.round,
35
- Frac = core.Frac,
36
- isInt = core.Utils.isInt,
37
- Symbol = core.Symbol,
38
- CONST_HASH = core.Settings.CONST_HASH,
39
- math = core.Utils.importFunctions(),
40
- evaluate = core.Utils.evaluate;
41
- //*************** CLASSES ***************//
42
- /**
43
- * Converts a symbol into an equivalent polynomial arrays of
44
- * the form [[coefficient_1, power_1],[coefficient_2, power_2], ... ]
45
- * Univariate polymials only.
46
- * @param {Symbol|Number} symbol
47
- * @param {String} variable The variable name of the polynomial
48
- * @param {int} order
49
- */
50
- function Polynomial(symbol, variable, order) {
51
- if(core.Utils.isSymbol(symbol)) {
52
- this.parse(symbol);
53
- this.variable = this.variable || variable;
54
- }
55
- else if(!isNaN(symbol)) {
56
- order = order || 0;
57
- if(variable === undefined)
58
- throw new core.exceptions.InvalidVariableNameError('Polynomial expects a variable name when creating using order');
59
- this.coeffs = [];
60
- this.coeffs[order] = symbol;
61
- this.fill(symbol);
62
- }
63
- else if(typeof symbol === 'string') {
64
- this.parse(_.parse(symbol));
65
- }
66
- }
67
- /**
68
- * Creates a Polynomial given an array of coefficients
69
- * @param {int[]} arr
70
- * @param {String} variable
71
- * @returns {Polynomial}
72
- */
73
- Polynomial.fromArray = function (arr, variable) {
74
- if(typeof variable === 'undefined')
75
- throw new core.exceptions.InvalidVariableNameError('A variable name must be specified when creating polynomial from array');
76
- var p = new Polynomial();
77
- p.coeffs = arr;
78
- p.variable = variable;
79
- return p;
80
- };
81
-
82
- Polynomial.fit = function (c1, c2, n, base, p, variable) {
83
- //after having looped through and mod 10 the number to get the matching factor
84
- var terms = new Array(p + 1),
85
- t = n - c2;
86
- terms[0] = c2; //the constants is assumed to be correct
87
- //constant for x^p is also assumed know so add
88
- terms[p] = c1;
89
- t -= c1 * Math.pow(base, p);
90
- //start fitting
91
- for(var i = p - 1; i > 0; i--) {
92
- var b = Math.pow(base, i), //we want as many wholes as possible
93
- q = t / b,
94
- sign = Math.sign(q);
95
- var c = sign * Math.floor(Math.abs(q));
96
- t -= c * b;
97
- terms[i] = c;
98
- }
99
- if(t !== 0)
100
- return null;
101
- for(var i = 0; i < terms.length; i++)
102
- terms[i] = new Frac(terms[i]);
103
-
104
- return Polynomial.fromArray(terms, variable);
105
- };
106
-
107
- Polynomial.prototype = {
108
- /**
109
- * Converts Symbol to Polynomial
110
- * @param {Symbol} symbol
111
- * @param {Array} c - a collector array
112
- * @returns {Polynomial}
113
- */
114
- parse: function (symbol, c) {
115
- this.variable = variables(symbol)[0];
116
- if(!symbol.isPoly())
117
- throw core.exceptions.NerdamerTypeError('Polynomial Expected! Received ' + core.Utils.text(symbol));
118
- c = c || [];
119
- if(!symbol.power.absEquals(1))
120
- symbol = _.expand(symbol);
121
-
122
- if(symbol.group === core.groups.N) {
123
- c[0] = symbol.multiplier;
124
- }
125
- else if(symbol.group === core.groups.S) {
126
- c[symbol.power.toDecimal()] = symbol.multiplier;
127
- }
128
- else {
129
- for(var x in symbol.symbols) {
130
- var sub = symbol.symbols[x],
131
- p = sub.power;
132
- if(core.Utils.isSymbol(p))
133
- throw new core.exceptions.NerdamerTypeError('power cannot be a Symbol');
134
-
135
- p = sub.group === N ? 0 : p.toDecimal();
136
- if(sub.symbols) {
137
- this.parse(sub, c);
138
- }
139
- else {
140
- c[p] = sub.multiplier;
141
- }
142
- }
143
- }
144
-
145
- this.coeffs = c;
146
-
147
- this.fill();
148
- },
149
- /**
150
- * Fills in the holes in a polynomial with zeroes
151
- * @param {Number} x - The number to fill the holes with
152
- */
153
- fill: function (x) {
154
- x = Number(x) || 0;
155
- var l = this.coeffs.length;
156
- for(var i = 0; i < l; i++) {
157
- if(this.coeffs[i] === undefined) {
158
- this.coeffs[i] = new Frac(x);
159
- }
160
- }
161
- return this;
162
- },
163
- /**
164
- * Removes higher order zeros or a specific coefficient
165
- * @returns {Array}
166
- */
167
- trim: function () {
168
- var l = this.coeffs.length;
169
- while(l--) {
170
- var c = this.coeffs[l];
171
- var equalsZero = c.equals(0);
172
- if(c && equalsZero) {
173
- if(l === 0)
174
- break;
175
- this.coeffs.pop();
176
- }
177
- else
178
- break;
179
- }
180
-
181
- return this;
182
- },
183
- /*
184
- * Returns polynomial mod p **currently fails**
185
- * @param {Number} p
186
- * @returns {Polynomial}
187
- */
188
- modP: function (p) {
189
- var l = this.coeffs.length;
190
- for(var i = 0; i < l; i++) {
191
- var c = this.coeffs[i];
192
- if(c < 0) { //go borrow
193
- var b; //a coefficient > 0
194
- for(var j = i; j < l; j++) {//starting from where we left off
195
- if(this.coeffs[j] > 0) {
196
- b = this.coeffs[j];
197
- break;
198
- }
199
- }
200
-
201
- if(b) { //if such a coefficient exists
202
- for(j; j > i; j--) { //go down the line and adjust using p
203
- this.coeffs[j] = this.coeffs[j].subtract(new Frac(1));
204
- this.coeffs[j - 1] = this.coeffs[j - 1].add(new Frac(p));
205
- }
206
- c = this.coeffs[i]; //reset c
207
- }
208
- }
209
-
210
- var d = c.mod(p);
211
- var w = c.subtract(d).divide(p);
212
- if(!w.equals(0)) {
213
- var up_one = i + 1;
214
- var next = this.coeffs[up_one] || new Frac(0);
215
- next = next.add(w);
216
- this.coeffs[up_one] = new Frac(next);
217
- this.coeffs[i] = new Frac(d);
218
- }
219
- }
220
-
221
- return this;
222
- },
223
- /**
224
- * Adds together 2 polynomials
225
- * @param {Polynomial} poly
226
- */
227
- add: function (poly) {
228
- var l = Math.max(this.coeffs.length, poly.coeffs.length);
229
- for(var i = 0; i < l; i++) {
230
- var a = (this.coeffs[i] || new Frac(0)),
231
- b = (poly.coeffs[i] || new Frac(0));
232
- this.coeffs[i] = a.add(b);
233
- }
234
- return this;
235
- },
236
- /**
237
- * Adds together 2 polynomials
238
- * @param {Polynomial} poly
239
- */
240
- subtract: function (poly) {
241
- var l = Math.max(this.coeffs.length, poly.coeffs.length);
242
- for(var i = 0; i < l; i++) {
243
- var a = (this.coeffs[i] || new Frac(0)),
244
- b = (poly.coeffs[i] || new Frac(0));
245
- this.coeffs[i] = a.subtract(b);
246
- }
247
- return this;
248
- },
249
- divide: function (poly) {
250
- var variable = this.variable,
251
- dividend = core.Utils.arrayClone(this.coeffs),
252
- divisor = core.Utils.arrayClone(poly.coeffs),
253
- n = dividend.length,
254
- mp = divisor.length - 1,
255
- quotient = [];
256
-
257
- //loop through the dividend
258
- for(var i = 0; i < n; i++) {
259
- var p = n - (i + 1);
260
- //get the difference of the powers
261
- var d = p - mp;
262
- //get the quotient of the coefficients
263
- var q = dividend[p].divide(divisor[mp]);
264
-
265
- if(d < 0)
266
- break;//the divisor is not greater than the dividend
267
- //place it in the quotient
268
- quotient[d] = q;
269
-
270
- for(var j = 0; j <= mp; j++) {
271
- //reduce the dividend
272
- dividend[j + d] = dividend[j + d].subtract((divisor[j].multiply(q)));
273
- }
274
- }
275
-
276
- //clean up
277
- var p1 = Polynomial.fromArray(dividend, variable || 'x').trim(), //pass in x for safety
278
- p2 = Polynomial.fromArray(quotient, variable || 'x');
279
- return [p2, p1];
280
- },
281
- multiply: function (poly) {
282
- var l1 = this.coeffs.length, l2 = poly.coeffs.length,
283
- c = []; //array to be returned
284
- for(var i = 0; i < l1; i++) {
285
- var x1 = this.coeffs[i];
286
- for(var j = 0; j < l2; j++) {
287
- var k = i + j, //add the powers together
288
- x2 = poly.coeffs[j],
289
- e = c[k] || new Frac(0); //get the existing term from the new array
290
- c[k] = e.add(x1.multiply(x2)); //multiply the coefficients and add to new polynomial array
291
- }
292
- }
293
- this.coeffs = c;
294
- return this;
295
- },
296
- /**
297
- * Checks if a polynomial is zero
298
- * @returns {Boolean}
299
- */
300
- isZero: function () {
301
- var l = this.coeffs.length;
302
- for(var i = 0; i < l; i++) {
303
- var e = this.coeffs[i];
304
- if(!e.equals(0))
305
- return false;
306
- }
307
- return true;
308
- },
309
- /**
310
- * Substitutes in a number n into the polynomial p(n)
311
- * @param {Number} n
312
- * @returns {Frac}
313
- */
314
- sub: function (n) {
315
- var sum = new Frac(0), l = this.coeffs.length;
316
- for(var i = 0; i < l; i++) {
317
- var t = this.coeffs[i];
318
- if(!t.equals(0))
319
- sum = sum.add(t.multiply(new Frac(Math.pow(n, i))));
320
- }
321
- return sum;
322
- },
323
- /**
324
- * Returns a clone of the polynomial
325
- * @returns {Polynomial}
326
- */
327
- clone: function () {
328
- var p = new Polynomial();
329
- p.coeffs = this.coeffs;
330
- p.variable = this.variable;
331
- return p;
332
- },
333
- /**
334
- * Gets the degree of the polynomial
335
- * @returns {Number}
336
- */
337
- deg: function () {
338
- this.trim();
339
- return this.coeffs.length - 1;
340
- },
341
- /**
342
- * Returns a lead coefficient
343
- * @returns {Frac}
344
- */
345
- lc: function () {
346
- return this.coeffs[this.deg()].clone();
347
- },
348
- /**
349
- * Converts polynomial into a monic polynomial
350
- * @returns {Polynomial}
351
- */
352
- monic: function () {
353
- var lc = this.lc(), l = this.coeffs.length;
354
- for(var i = 0; i < l; i++)
355
- this.coeffs[i] = this.coeffs[i].divide(lc);
356
- return this;
357
- },
358
- /**
359
- * Returns the GCD of two polynomials
360
- * @param {Polynomial} poly
361
- * @returns {Polynomial}
362
- */
363
- gcd: function (poly) {
364
- //get the maximum power of each
365
- var mp1 = this.coeffs.length - 1,
366
- mp2 = poly.coeffs.length - 1,
367
- T;
368
- //swap so we always have the greater power first
369
- if(mp1 < mp2) {
370
- return poly.gcd(this);
371
- }
372
- var a = this;
373
-
374
- while(!poly.isZero()) {
375
- var t = poly.clone();
376
- a = a.clone();
377
- T = a.divide(t);
378
- poly = T[1];
379
- a = t;
380
- }
381
-
382
- var gcd = core.Math2.QGCD.apply(null, a.coeffs);
383
- if(!gcd.equals(1)) {
384
- var l = a.coeffs.length;
385
- for(var i = 0; i < l; i++) {
386
- a.coeffs[i] = a.coeffs[i].divide(gcd);
387
- }
388
- }
389
- return a;
390
- },
391
- /**
392
- * Differentiates the polynomial
393
- * @returns {Polynomial}
394
- */
395
- diff: function () {
396
- var new_array = [], l = this.coeffs.length;
397
- for(var i = 1; i < l; i++)
398
- new_array.push(this.coeffs[i].multiply(new Frac(i)));
399
- this.coeffs = new_array;
400
- return this;
401
- },
402
- /**
403
- * Integrates the polynomial
404
- * @returns {Polynomial}
405
- */
406
- integrate: function () {
407
- var new_array = [0], l = this.coeffs.length;
408
- for(var i = 0; i < l; i++) {
409
- var c = new Frac(i + 1);
410
- new_array[c] = this.coeffs[i].divide(c);
411
- }
412
- this.coeffs = new_array;
413
- return this;
414
- },
415
- /**
416
- * Returns the Greatest common factor of the polynomial
417
- * @param {bool} toPolynomial - true if a polynomial is wanted
418
- * @returns {Frac|Polynomial}
419
- */
420
- gcf: function (toPolynomial) {
421
- //get the first nozero coefficient and returns its power
422
- var fnz = function (a) {
423
- for(var i = 0; i < a.length; i++)
424
- if(!a[i].equals(0))
425
- return i;
426
- },
427
- ca = [];
428
- for(var i = 0; i < this.coeffs.length; i++) {
429
- var c = this.coeffs[i];
430
- if(!c.equals(0) && ca.indexOf(c) === -1)
431
- ca.push(c);
432
- }
433
- var p = [core.Math2.QGCD.apply(undefined, ca), fnz(this.coeffs)].toDecimal();
434
-
435
- if(toPolynomial) {
436
- var parr = [];
437
- parr[p[1] - 1] = p[0];
438
- p = Polynomial.fromArray(parr, this.variable).fill();
439
- }
440
-
441
- return p;
442
- },
443
- /**
444
- * Raises a polynomial P to a power p -> P^p. e.g. (x+1)^2
445
- * @param {bool} incl_img - Include imaginary numbers
446
- */
447
- quad: function (incl_img) {
448
- var roots = [];
449
- if(this.coeffs.length > 3)
450
- throw new Error('Cannot calculate quadratic order of ' + (this.coeffs.length - 1));
451
- if(this.coeffs.length === 0)
452
- throw new Error('Polynomial array has no terms');
453
- var a = this.coeffs[2] || 0, b = this.coeffs[1] || 0, c = this.coeffs[0];
454
- var dsc = b * b - 4 * a * c;
455
- if(dsc < 0 && !incl_img)
456
- return roots;
457
- else {
458
- roots[0] = (-b + Math.sqrt(dsc)) / (2 * a);
459
- roots[1] = (-b - Math.sqrt(dsc)) / (2 * a);
460
- }
461
- return roots;
462
- },
463
- /**
464
- * Makes polynomial square free
465
- * @returns {Array}
466
- */
467
- squareFree: function () {
468
-
469
- var a = this.clone(),
470
- i = 1,
471
- b = a.clone().diff(),
472
- c = a.clone().gcd(b),
473
- w = a.divide(c)[0];
474
- var output = Polynomial.fromArray([new Frac(1)], a.variable);
475
- while(!c.equalsNumber(1)) {
476
- var y = w.gcd(c);
477
- var z = w.divide(y)[0];
478
- //one of the factors may have shown up since it's square but smaller than the
479
- //one where finding
480
- if(!z.equalsNumber(1) && i > 1) {
481
- var t = z.clone();
482
- for(var j = 1; j < i; j++)
483
- t.multiply(z.clone());
484
- z = t;
485
- }
486
- output = output.multiply(z);
487
- i++;
488
- w = y;
489
- c = c.divide(y)[0];
490
- }
491
-
492
- return [output, w, i];
493
- },
494
- /**
495
- * Converts polynomial to Symbol
496
- * @returns {Symbol}
497
- */
498
- toSymbol: function () {
499
- var l = this.coeffs.length,
500
- variable = this.variable;
501
- if(l === 0)
502
- return new core.Symbol(0);
503
- var end = l - 1, str = '';
504
-
505
- for(var i = 0; i < l; i++) {
506
- //place the plus sign for all but the last one
507
- var plus = i === end ? '' : '+',
508
- e = this.coeffs[i];
509
- if(!e.equals(0))
510
- str += (e + '*' + variable + '^' + i + plus);
511
- }
512
- return _.parse(str);
513
- },
514
- /**
515
- * Checks if polynomial is equal to a number
516
- * @param {Number} x
517
- * @returns {Boolean}
518
- */
519
- equalsNumber: function (x) {
520
- this.trim();
521
- return this.coeffs.length === 1 && this.coeffs[0].toDecimal() === String(x);
522
- },
523
- toString: function () {
524
- return this.toSymbol().toString();
525
- }
526
- };
527
-
528
- /**
529
- * TODO
530
- * ===================================================================================
531
- * THIS METHOD HAS A NASTY HIDDEN BUG. IT HAS INCONSISTENT RETURN TYPES PRIMARILY DUE TO
532
- * WRONG ASSUMPTIONS AT THE BEGINNING. THE ASSUMPTION WAS THAT COEFFS WERE ALWAYS GOING BE NUMBERS
533
- * NOT TAKING INTO ACCOUNT THAT IMAGINARY NUMBERS. FIXING THIS BREAKS WAY TOO MANY TESTS
534
- * AT THEM MOMENT WHICH I DON'T HAVE TO FIX
535
- * ===================================================================================
536
- * If the symbols is of group PL or CP it will return the multipliers of each symbol
537
- * as these are polynomial coefficients. CB symbols are glued together by multiplication
538
- * so the symbol multiplier carries the coefficients for all contained symbols.
539
- * For S it just returns it's own multiplier. This function doesn't care if it's a polynomial or not
540
- * @param {Array} c The coefficient array
541
- * @param {boolean} with_order
542
- * @return {Array}
543
- */
544
- Symbol.prototype.coeffs = function (c, with_order) {
545
- if(with_order && !this.isPoly(true))
546
- _.error('Polynomial expected when requesting coefficients with order');
547
- c = c || [];
548
- var s = this.clone().distributeMultiplier();
549
- if(s.isComposite()) {
550
- for(var x in s.symbols) {
551
- var sub = s.symbols[x];
552
- if(sub.isComposite()) {
553
- sub.clone().distributeMultiplier().coeffs(c, with_order);
554
- }
555
- else {
556
- if(with_order)
557
- c[sub.isConstant() ? 0 : sub.power.toDecimal()] = sub.multiplier;
558
- else {
559
- c.push(sub.multiplier);
560
- }
561
- }
562
- }
563
- }
564
- else {
565
- if(with_order)
566
- c[s.isConstant(true) ? 0 : s.power.toDecimal()] = s.multiplier;
567
- else {
568
- if(s.group === CB && s.isImaginary()) {
569
- var m = new Symbol(s.multiplier);
570
- s.each(function (x) {
571
- //add the imaginary part
572
- if(x.isConstant(true) || x.imaginary)
573
- m = _.multiply(m, x);
574
- });
575
- c.push(m);
576
- }
577
- else
578
- c.push(s.multiplier);
579
- }
580
- }
581
- //fill the holes
582
- if(with_order) {
583
- for(var i = 0; i < c.length; i++)
584
- if(c[i] === undefined)
585
- c[i] = new Symbol(0);
586
- }
587
- return c;
588
- };
589
- Symbol.prototype.tBase = function (map) {
590
- if(typeof map === 'undefined')
591
- throw new Error('Symbol.tBase requires a map object!');
592
- var terms = [];
593
- var symbols = this.collectSymbols(null, null, null, true),
594
- l = symbols.length;
595
- for(var i = 0; i < l; i++) {
596
- var symbol = symbols[i],
597
- g = symbol.group,
598
- nterm = new MVTerm(symbol.multiplier, [], map);
599
- if(g === CB) {
600
- for(var x in symbol.symbols) {
601
- var sym = symbol.symbols[x];
602
- nterm.terms[map[x]] = sym.power;
603
- }
604
- }
605
- else {
606
- nterm.terms[map[symbol.value]] = symbol.power;
607
- }
608
-
609
- terms.push(nterm.fill());
610
- nterm.updateCount();
611
- }
612
- return terms;
613
- };
614
- Symbol.prototype.altVar = function (x) {
615
- var m = this.multiplier.toString(), p = this.power.toString();
616
- return (m === '1' ? '' : m + '*') + x + (p === '1' ? '' : '^' + p);
617
- };
618
- /**
619
- * Checks to see if the symbols contain the same variables
620
- * @param {Symbol} symbol
621
- * @returns {Boolean}
622
- */
623
- Symbol.prototype.sameVars = function (symbol) {
624
- if(!(this.symbols || this.group === symbol.group))
625
- return false;
626
- for(var x in this.symbols) {
627
- var a = this.symbols[x], b = symbol.symbols[x];
628
- if(!b)
629
- return false;
630
- if(a.value !== b.value)
631
- return false;
632
- }
633
- return true;
634
- };
635
- /**
636
- * Groups the terms in a symbol with respect to a variable
637
- * For instance the symbol {a*b^2*x^2+a*b*x^2+x+6} returns [6,1,a*b+a*b^2]
638
- * @returns {Factors}
639
- */
640
- Symbol.prototype.groupTerms = function (x) {
641
- x = String(x);
642
- var f, p, egrouped;
643
- var grouped = [];
644
- this.each(function (e) {
645
- if(e.group === PL) {
646
- egrouped = e.groupTerms(x);
647
- for(var i = 0; i < egrouped.length; i++) {
648
- var el = egrouped[i];
649
- if(el)
650
- grouped[i] = el;
651
- }
652
- }
653
- else {
654
- f = core.Utils.decompose_fn(e, x, true);
655
- p = f.x.value === x ? Number(f.x.power) : 0;
656
- //check if there's an existing value
657
- grouped[p] = _.add(grouped[p] || new Symbol(0), f.a);
658
- }
659
- });
660
- return grouped;
661
- };
662
- /**
663
- * Use this to collect Factors
664
- * @returns {Symbol[]}
665
- */
666
- Symbol.prototype.collectFactors = function () {
667
- var factors = [];
668
- if(this.group === CB)
669
- this.each(function (x) {
670
- factors.push(x.clone());
671
- });
672
- else
673
- factors.push(this.clone());
674
- return factors;
675
- };
676
- /**
677
- * A container class for factors
678
- * @returns {Factors}
679
- */
680
- function Factors() {
681
- this.factors = {};
682
- this.length = 0;
683
- }
684
- ;
685
- Factors.prototype.getNumberSymbolics = function () {
686
- var n = 0;
687
- this.each(function (x) {
688
- if(!x.isConstant(true))
689
- n++;
690
- });
691
- return n;
692
- };
693
- /**
694
- * Adds the factors to the factor object
695
- * @param {Symbo} s
696
- * @returns {Factors}
697
- */
698
- Factors.prototype.add = function (s) {
699
- if(s.equals(0))
700
- return this; //nothing to add
701
-
702
- //we don't want to carry -1 as a factor. If a factor already exists,
703
- //then add the minus one to that factor and return.
704
- if(s.equals(-1) && this.length > 0) {
705
- var fo = core.Utils.firstObject(this.factors, null, true);
706
- this.add(_.symfunction(core.Settings.PARENTHESIS, [fo.obj]).negate());
707
- delete this.factors[fo.key];
708
- this.length--;
709
- return this;
710
- }
711
-
712
- if(s.group === CB) {
713
- var factors = this;
714
- if(!s.multiplier.equals(1))
715
- factors.add(new Symbol(s.multiplier));
716
- s.each(function (x) {
717
- factors.add(x);
718
- });
719
- }
720
- else {
721
- if(this.preAdd) //if a preAdd function was defined call it to do prep
722
- s = this.preAdd(s);
723
- if(this.pFactor) //if the symbol isn't linear add back the power
724
- s = _.pow(s, new Symbol(this.pFactor));
725
-
726
- var is_constant = s.isConstant();
727
- if(is_constant && s.equals(1))
728
- return this; //don't add 1
729
- var v = is_constant ? s.value : s.text();
730
- if(v in this.factors) {
731
- this.factors[v] = _.multiply(this.factors[v], s);
732
- //did the addition cancel out the existing factor? If so remove it and decrement the length
733
- if(this.factors[v].equals(1)) {
734
- delete this.factors[v];
735
- this.length--;
736
- }
737
- }
738
- else {
739
- this.factors[v] = s;
740
- this.length++;
741
- }
742
- }
743
- return this;
744
- };
745
- /**
746
- * Converts the factor object to a Symbol
747
- * @returns {Symbol}
748
- */
749
- Factors.prototype.toSymbol = function () {
750
- var factored = new Symbol(1);
751
- var factors = Object.values(this.factors).sort(function (a, b) {
752
- return a.group > b.group;
753
- });
754
-
755
- for(var i = 0, l = factors.length; i < l; i++) {
756
- var f = factors[i];
757
-
758
- //don't wrap group S or FN
759
- var factor = f.power.equals(1) && f.fname !== '' /* don't wrap it twice */ ?
760
- _.symfunction(core.PARENTHESIS, [f]) : f;
761
-
762
- factored = _.multiply(factored, factor);
763
- }
764
- if(factored.fname === '')
765
- factored = Symbol.unwrapPARENS(factored);
766
- return factored;
767
- };
768
- /**
769
- * Merges 2 factor objects into one
770
- * @param {Factor} o
771
- * @returns {Factors}
772
- */
773
- Factors.prototype.merge = function (o) {
774
- for(var x in o) {
775
- if(x in this.factors)
776
- this.factors[x] = _.multiply(this.factors[x], o[x]);
777
- else
778
- this.factors[x] = o[x];
779
- }
780
- return this;
781
- };
782
- /**
783
- * The iterator for the factor object
784
- * @param {Function} f - callback
785
- * @returns {Factor}
786
- */
787
- Factors.prototype.each = function (f) {
788
- for(var x in this.factors) {
789
- var factor = this.factors[x];
790
- if(factor.fname === core.PARENTHESIS && factor.isLinear())
791
- factor = factor.args[0];
792
- f.call(this, factor, x);
793
- }
794
- return this;
795
- };
796
- /**
797
- * Return the number of factors contained in the factor object
798
- * @returns {int}
799
- */
800
- Factors.prototype.count = function () {
801
- return keys(this.factors).length;
802
- };
803
- /**
804
- * Cleans up factors from -1
805
- * @returns {undefined}
806
- */
807
- Factors.prototype.clean = function () {
808
- try {
809
- var h = core.Settings.CONST_HASH;
810
- if(this.factors[h].lessThan(0)) {
811
- if(this.factors[h].equals(-1))
812
- delete this.factors[h];
813
- else
814
- this.factors[h].negate();
815
- this.each(function (x) {
816
- x.negate();
817
- });
818
- }
819
- }
820
- catch(e) {
821
- }
822
- ;
823
- };
824
- Factors.prototype.toString = function () {
825
- return this.toSymbol().toString();
826
- };
827
-
828
- //a wrapper for performing multivariate division
829
- function MVTerm(coeff, terms, map) {
830
- this.terms = terms || [];
831
- this.coeff = coeff;
832
- this.map = map; //careful! all maps are the same object
833
- this.sum = new core.Frac(0);
834
- this.image = undefined;
835
- }
836
- ;
837
- MVTerm.prototype.updateCount = function () {
838
- this.count = this.count || 0;
839
- for(var i = 0; i < this.terms.length; i++) {
840
- if(!this.terms[i].equals(0))
841
- this.count++;
842
- }
843
- return this;
844
- };
845
- MVTerm.prototype.getVars = function () {
846
- var vars = [];
847
- for(var i = 0; i < this.terms.length; i++) {
848
- var term = this.terms[i],
849
- rev_map = this.getRevMap();
850
- if(!term.equals(0))
851
- vars.push(this.rev_map[i]);
852
- }
853
- return vars.join(' ');
854
- };
855
- MVTerm.prototype.len = function () {
856
- if(typeof this.count === 'undefined') {
857
- this.updateCount();
858
- }
859
- return this.count;
860
- };
861
- MVTerm.prototype.toSymbol = function (rev_map) {
862
- rev_map = rev_map || this.getRevMap();
863
- var symbol = new Symbol(this.coeff);
864
- for(var i = 0; i < this.terms.length; i++) {
865
- var v = rev_map[i],
866
- t = this.terms[i];
867
- if(t.equals(0) || v === CONST_HASH)
868
- continue;
869
- var mapped = new Symbol(v);
870
- mapped.power = t;
871
- symbol = _.multiply(symbol, mapped);
872
- }
873
- return symbol;
874
- };
875
- MVTerm.prototype.getRevMap = function () {
876
- if(this.rev_map)
877
- return this.rev_map;
878
- var o = {};
879
- for(var x in this.map)
880
- o[this.map[x]] = x;
881
- this.rev_map = o;
882
- return o;
883
- };
884
- MVTerm.prototype.generateImage = function () {
885
- this.image = this.terms.join(' ');
886
- return this;
887
- },
888
- MVTerm.prototype.getImg = function () {
889
- if(!this.image)
890
- this.generateImage();
891
- return this.image;
892
- },
893
- MVTerm.prototype.fill = function () {
894
- var l = this.map.length;
895
- for(var i = 0; i < l; i++) {
896
- if(typeof this.terms[i] === 'undefined')
897
- this.terms[i] = new core.Frac(0);
898
- else {
899
- this.sum = this.sum.add(this.terms[i]);
900
- }
901
- }
902
- return this;
903
- };
904
- MVTerm.prototype.divide = function (mvterm) {
905
- var c = this.coeff.divide(mvterm.coeff),
906
- l = this.terms.length,
907
- new_mvterm = new MVTerm(c, [], this.map);
908
- for(var i = 0; i < l; i++) {
909
- new_mvterm.terms[i] = this.terms[i].subtract(mvterm.terms[i]);
910
- new_mvterm.sum = new_mvterm.sum.add(new_mvterm.terms[i]);
911
- }
912
- return new_mvterm;
913
- };
914
- MVTerm.prototype.multiply = function (mvterm) {
915
- var c = this.coeff.multiply(mvterm.coeff),
916
- l = this.terms.length,
917
- new_mvterm = new MVTerm(c, [], this.map);
918
- for(var i = 0; i < l; i++) {
919
- new_mvterm.terms[i] = this.terms[i].add(mvterm.terms[i]);
920
- new_mvterm.sum = new_mvterm.sum.add(new_mvterm.terms[i]);
921
- }
922
- return new_mvterm;
923
- };
924
- MVTerm.prototype.isZero = function () {
925
- return this.coeff.equals(0);
926
- };
927
- MVTerm.prototype.toString = function () {
928
- return '{ coeff: ' + this.coeff.toString() + ', terms: [' +
929
- this.terms.join(',') + ']: sum: ' + this.sum.toString() + ', count: ' + this.count + '}';
930
- };
931
-
932
- core.Utils.toMapObj = function (arr) {
933
- var c = 0, o = {};
934
- for(var i = 0; i < arr.length; i++) {
935
- var v = arr[i];
936
- if(typeof o[v] === 'undefined') {
937
- o[v] = c;
938
- c++;
939
- }
940
- }
941
- o.length = c;
942
- return o;
943
- };
944
- core.Utils.filledArray = function (v, n, clss) {
945
- var a = [];
946
- while(n--) {
947
- a[n] = clss ? new clss(v) : v;
948
- }
949
- return a;
950
- };
951
- core.Utils.arrSum = function (arr) {
952
- var sum = 0, l = arr.length;
953
- for(var i = 0; i < l; i++)
954
- sum += arr[i];
955
- return sum;
956
- };
957
- /**
958
- * Determines if 2 arrays have intersecting elements.
959
- * @param {Array} a
960
- * @param {Array} b
961
- * @returns {Boolean} True if a and b have intersecting elements.
962
- */
963
- core.Utils.haveIntersection = function (a, b) {
964
- var t;
965
- if(b.length > a.length)
966
- t = b, b = a, a = t; // indexOf to loop over shorter
967
- return a.some(function (e) {
968
- return b.indexOf(e) > -1;
969
- });
970
- };
971
- /**
972
- * Substitutes out functions as variables so they can be used in regular algorithms
973
- * @param {Symbol} symbol
974
- * @param {Object} map
975
- * @returns {String} The expression string
976
- */
977
- core.Utils.subFunctions = function (symbol, map) {
978
- map = map || {};
979
- var subbed = [];
980
- symbol.each(function (x) {
981
- if(x.group === FN || x.previousGroup === FN) {
982
- //we need a new variable name so why not use one of the existing
983
- var val = core.Utils.text(x, 'hash'), tvar = map[val];
984
- if(!tvar) {
985
- //generate a unique enough name
986
- var t = x.fname + keys(map).length;
987
- map[val] = t;
988
- subbed.push(x.altVar(t));
989
- }
990
- else
991
- subbed.push(x.altVar(tvar));
992
- }
993
- else if(x.group === CB || x.group === PL || x.group === CP) {
994
- subbed.push(core.Utils.subFunctions(x, map));
995
- }
996
- else
997
- subbed.push(x.text());
998
- });
999
- if(symbol.group === CP || symbol.group === PL)
1000
- return symbol.altVar(core.Utils.inBrackets(subbed.join('+')));
1001
- ;
1002
- if(symbol.group === CB)
1003
- return symbol.altVar(core.Utils.inBrackets(subbed.join('*')));
1004
- return symbol.text();
1005
- };
1006
- core.Utils.getFunctionsSubs = function (map) {
1007
- var subs = {};
1008
- //prepare substitutions
1009
- for(var x in map)
1010
- subs[map[x]] = _.parse(x);
1011
- return subs;
1012
- };
1013
-
1014
- var __ = core.Algebra = {
1015
- version: '1.4.6',
1016
- proots: function (symbol, decp) {
1017
- //the roots will be rounded up to 7 decimal places.
1018
- //if this causes trouble you can explicitly pass in a different number of places
1019
- //rarr for polynomial of power n is of format [n, coeff x^n, coeff x^(n-1), ..., coeff x^0]
1020
- decp = decp || 7;
1021
- var zeros = 0;
1022
- var known_roots = [];
1023
- var get_roots = function (rarr, powers, max) {
1024
- var roots = calcroots(rarr, powers, max).concat(known_roots);
1025
- for(var i = 0; i < zeros; i++)
1026
- roots.unshift(0);
1027
- return roots;
1028
- };
1029
-
1030
- if(symbol instanceof Symbol && symbol.isPoly()) {
1031
- symbol.distributeMultiplier();
1032
- //make it so the symbol has a constants as the lowest term
1033
- if(symbol.group === PL) {
1034
- var lowest_pow = core.Utils.arrayMin(keys(symbol.symbols));
1035
- var lowest_symbol = symbol.symbols[lowest_pow].clone().toUnitMultiplier();
1036
- symbol = _.expand(_.divide(symbol, lowest_symbol));
1037
- known_roots.push(0); //add zero since this is a known root
1038
- }
1039
- if(symbol.group === core.groups.S) {
1040
- return [0];
1041
- }
1042
- else if(symbol.group === core.groups.PL) {
1043
- var powers = keys(symbol.symbols),
1044
- minpower = core.Utils.arrayMin(powers),
1045
- symbol = core.PARSER.divide(symbol, core.PARSER.parse(symbol.value + '^' + minpower));
1046
- }
1047
-
1048
- var variable = keys(symbol.symbols).sort().pop(),
1049
- sym = symbol.group === core.groups.PL ? symbol.symbols : symbol.symbols[variable],
1050
- g = sym.group,
1051
- powers = g === S ? [sym.power.toDecimal()] : keys(sym.symbols),
1052
- rarr = [],
1053
- max = core.Utils.arrayMax(powers); //maximum power and degree of polynomial to be solved
1054
-
1055
- // Prepare the data
1056
- for(var i = 1; i <= max; i++) {
1057
- var c = 0; //if there is no power then the hole must be filled with a zero
1058
- if(powers.indexOf(i + '') !== -1) {
1059
- if(g === S) {
1060
- c = sym.multiplier;
1061
- }
1062
- else {
1063
- c = sym.symbols[i].multiplier;
1064
- }
1065
- }
1066
- // Insert the coeffient but from the front
1067
- rarr.unshift(c);
1068
- }
1069
-
1070
- rarr.push(symbol.symbols[CONST_HASH].multiplier);
1071
-
1072
- if(sym.group === S)
1073
- rarr[0] = sym.multiplier;//the symbol maybe of group CP with one variable
1074
-
1075
- return get_roots(rarr, powers, max);
1076
- }
1077
- else if(core.Utils.isArray(symbol)) {
1078
- var parr = symbol;
1079
- var rarr = [],
1080
- powers = [],
1081
- last_power = 0;
1082
- for(var i = 0; i < parr.length; i++) {
1083
-
1084
- var coeff = parr[i][0],
1085
- pow = parr[i][1],
1086
- d = pow - last_power - 1;
1087
- //insert the zeros
1088
- for(var j = 0; j < d; j++)
1089
- rarr.unshift(0);
1090
-
1091
- rarr.unshift(coeff);
1092
- if(pow !== 0)
1093
- powers.push(pow);
1094
- last_power = pow;
1095
- }
1096
- var max = Math.max.apply(undefined, powers);
1097
-
1098
- return get_roots(rarr, powers, max);
1099
- }
1100
- else {
1101
- throw new core.exceptions.NerdamerTypeError('Cannot calculate roots. Symbol must be a polynomial!');
1102
- }
1103
-
1104
- function calcroots(rarr, powers, max) {
1105
- var MAXDEGREE = 100; // Degree of largest polynomial accepted by this script.
1106
-
1107
- // Make a clone of the coefficients before appending the max power
1108
- var p = rarr.slice(0);
1109
-
1110
- // Divide the string up into its individual entries, which--presumably--are separated by whitespace
1111
- rarr.unshift(max);
1112
-
1113
- if(max > MAXDEGREE) {
1114
- throw new core.exceptions.ValueLimitExceededError("This utility accepts polynomials of degree up to " + MAXDEGREE + ". ");
1115
- }
1116
-
1117
- var zeroi = [], // Vector of imaginary components of roots
1118
- degreePar = {}; // degreePar is a dummy variable for passing the parameter POLYDEGREE by reference
1119
- degreePar.Degree = max;
1120
-
1121
- for(i = 0; i < max; i++) {
1122
- zeroi.push(0);
1123
- }
1124
- var zeror = zeroi.slice(0); // Vector of real components of roots
1125
-
1126
- // Find the roots
1127
- //--> Begin Jenkins-Traub
1128
-
1129
- /*
1130
- * A verbatim copy of Mr. David Binner's Jenkins-Traub port
1131
- */
1132
- function QuadSD_ak1(NN, u, v, p, q, iPar) {
1133
- // Divides p by the quadratic 1, u, v placing the quotient in q and the remainder in a, b
1134
- // iPar is a dummy variable for passing in the two parameters--a and b--by reference
1135
- q[0] = iPar.b = p[0];
1136
- q[1] = iPar.a = -(u * iPar.b) + p[1];
1137
-
1138
- for(var i = 2; i < NN; i++) {
1139
- q[i] = -(u * iPar.a + v * iPar.b) + p[i];
1140
- iPar.b = iPar.a;
1141
- iPar.a = q[i];
1142
- }
1143
- return;
1144
- }
1145
-
1146
- function calcSC_ak1(DBL_EPSILON, N, a, b, iPar, K, u, v, qk) {
1147
- // This routine calculates scalar quantities used to compute the next K polynomial and
1148
- // new estimates of the quadratic coefficients.
1149
- // calcSC - integer variable set here indicating how the calculations are normalized
1150
- // to avoid overflow.
1151
- // iPar is a dummy variable for passing in the nine parameters--a1, a3, a7, c, d, e, f, g, and h --by reference
1152
-
1153
- // sdPar is a dummy variable for passing the two parameters--c and d--into QuadSD_ak1 by reference
1154
- var sdPar = new Object(),
1155
- // TYPE = 3 indicates the quadratic is almost a factor of K
1156
- dumFlag = 3;
1157
-
1158
- // Synthetic division of K by the quadratic 1, u, v
1159
- sdPar.b = sdPar.a = 0.0;
1160
- QuadSD_ak1(N, u, v, K, qk, sdPar);
1161
- iPar.c = sdPar.a;
1162
- iPar.d = sdPar.b;
1163
-
1164
- if(Math.abs(iPar.c) <= (100.0 * DBL_EPSILON * Math.abs(K[N - 1]))) {
1165
- if(Math.abs(iPar.d) <= (100.0 * DBL_EPSILON * Math.abs(K[N - 2])))
1166
- return dumFlag;
1167
- }
1168
-
1169
- iPar.h = v * b;
1170
- if(Math.abs(iPar.d) >= Math.abs(iPar.c)) {
1171
- // TYPE = 2 indicates that all formulas are divided by d
1172
- dumFlag = 2;
1173
- iPar.e = a / (iPar.d);
1174
- iPar.f = (iPar.c) / (iPar.d);
1175
- iPar.g = u * b;
1176
- iPar.a3 = (iPar.e) * ((iPar.g) + a) + (iPar.h) * (b / (iPar.d));
1177
- iPar.a1 = -a + (iPar.f) * b;
1178
- iPar.a7 = (iPar.h) + ((iPar.f) + u) * a;
1179
- }
1180
- else {
1181
- // TYPE = 1 indicates that all formulas are divided by c;
1182
- dumFlag = 1;
1183
- iPar.e = a / (iPar.c);
1184
- iPar.f = (iPar.d) / (iPar.c);
1185
- iPar.g = (iPar.e) * u;
1186
- iPar.a3 = (iPar.e) * a + ((iPar.g) + (iPar.h) / (iPar.c)) * b;
1187
- iPar.a1 = -(a * ((iPar.d) / (iPar.c))) + b;
1188
- iPar.a7 = (iPar.g) * (iPar.d) + (iPar.h) * (iPar.f) + a;
1189
- }
1190
- return dumFlag;
1191
- }
1192
-
1193
- function nextK_ak1(DBL_EPSILON, N, tFlag, a, b, iPar, K, qk, qp) {
1194
- // Computes the next K polynomials using the scalars computed in calcSC_ak1
1195
- // iPar is a dummy variable for passing in three parameters--a1, a3, and a7
1196
- var temp;
1197
- if(tFlag == 3) { // Use unscaled form of the recurrence
1198
- K[1] = K[0] = 0.0;
1199
- for(var i = 2; i < N; i++) {
1200
- K[i] = qk[i - 2];
1201
- }
1202
- return;
1203
- }
1204
-
1205
- temp = ((tFlag == 1) ? b : a);
1206
- if(Math.abs(iPar.a1) > (10.0 * DBL_EPSILON * Math.abs(temp))) {
1207
- // Use scaled form of the recurrence
1208
- iPar.a7 /= iPar.a1;
1209
- iPar.a3 /= iPar.a1;
1210
- K[0] = qp[0];
1211
- K[1] = -(qp[0] * iPar.a7) + qp[1];
1212
- for(var i = 2; i < N; i++)
1213
- K[i] = -(qp[i - 1] * iPar.a7) + qk[i - 2] * iPar.a3 + qp[i];
1214
- }
1215
- else {
1216
- // If a1 is nearly zero, then use a special form of the recurrence
1217
- K[0] = 0.0;
1218
- K[1] = -(qp[0] * iPar.a7);
1219
- for(var i = 2; i < N; i++) {
1220
- K[i] = -(qp[i - 1] * iPar.a7) + qk[i - 2] * iPar.a3;
1221
- }
1222
- }
1223
- return;
1224
- }
1225
-
1226
- function newest_ak1(tFlag, iPar, a, a1, a3, a7, b, c, d, f, g, h, u, v, K, N, p) {
1227
- // Compute new estimates of the quadratic coefficients using the scalars computed in calcSC_ak1
1228
- // iPar is a dummy variable for passing in the two parameters--uu and vv--by reference
1229
- // iPar.a = uu, iPar.b = vv
1230
-
1231
- var a4, a5, b1, b2, c1, c2, c3, c4, temp;
1232
- iPar.b = iPar.a = 0.0;// The quadratic is zeroed
1233
-
1234
- if(tFlag != 3) {
1235
- if(tFlag != 2) {
1236
- a4 = a + u * b + h * f;
1237
- a5 = c + (u + v * f) * d;
1238
- }
1239
- else {
1240
- a4 = (a + g) * f + h;
1241
- a5 = (f + u) * c + v * d;
1242
- }
1243
-
1244
- // Evaluate new quadratic coefficients
1245
- b1 = -(K[N - 1] / p[N]);
1246
- b2 = -(K[N - 2] + b1 * p[N - 1]) / p[N];
1247
- c1 = v * b2 * a1;
1248
- c2 = b1 * a7;
1249
- c3 = b1 * b1 * a3;
1250
- c4 = -(c2 + c3) + c1;
1251
- temp = -c4 + a5 + b1 * a4;
1252
- if(temp != 0.0) {
1253
- iPar.a = -((u * (c3 + c2) + v * (b1 * a1 + b2 * a7)) / temp) + u;
1254
- iPar.b = v * (1.0 + c4 / temp);
1255
- }
1256
- }
1257
- return;
1258
- }
1259
-
1260
- function Quad_ak1(a, b1, c, iPar) {
1261
- // Calculates the zeros of the quadratic a*Z^2 + b1*Z + c
1262
- // The quadratic formula, modified to avoid overflow, is used to find the larger zero if the
1263
- // zeros are real and both zeros are complex. The smaller real zero is found directly from
1264
- // the product of the zeros c/a.
1265
-
1266
- // iPar is a dummy variable for passing in the four parameters--sr, si, lr, and li--by reference
1267
-
1268
- var b, d, e;
1269
- iPar.sr = iPar.si = iPar.lr = iPar.li = 0.0;
1270
-
1271
- if(a == 0) {
1272
- iPar.sr = ((b1 != 0) ? -(c / b1) : iPar.sr);
1273
- return;
1274
- }
1275
- if(c == 0) {
1276
- iPar.lr = -(b1 / a);
1277
- return;
1278
- }
1279
-
1280
- // Compute discriminant avoiding overflow
1281
- b = b1 / 2.0;
1282
- if(Math.abs(b) < Math.abs(c)) {
1283
- e = ((c >= 0) ? a : -a);
1284
- e = -e + b * (b / Math.abs(c));
1285
- d = Math.sqrt(Math.abs(e)) * Math.sqrt(Math.abs(c));
1286
- }
1287
- else {
1288
- e = -((a / b) * (c / b)) + 1.0;
1289
- d = Math.sqrt(Math.abs(e)) * (Math.abs(b));
1290
- }
1291
-
1292
- if(e >= 0) {
1293
- // Real zeros
1294
- d = ((b >= 0) ? -d : d);
1295
- iPar.lr = (-b + d) / a;
1296
- iPar.sr = ((iPar.lr != 0) ? (c / (iPar.lr)) / a : iPar.sr);
1297
- }
1298
- else {
1299
- // Complex conjugate zeros
1300
- iPar.lr = iPar.sr = -(b / a);
1301
- iPar.si = Math.abs(d / a);
1302
- iPar.li = -(iPar.si);
1303
- }
1304
- return;
1305
- }
1306
-
1307
- function QuadIT_ak1(DBL_EPSILON, N, iPar, uu, vv, qp, NN, sdPar, p, qk, calcPar, K) {
1308
- // Variable-shift K-polynomial iteration for a quadratic factor converges only if the
1309
- // zeros are equimodular or nearly so.
1310
- // iPar is a dummy variable for passing in the five parameters--NZ, lzi, lzr, szi, and szr--by reference
1311
- // sdPar is a dummy variable for passing the two parameters--a and b--in by reference
1312
- // calcPar is a dummy variable for passing the nine parameters--a1, a3, a7, c, d, e, f, g, and h --in by reference
1313
-
1314
- // qPar is a dummy variable for passing the four parameters--szr, szi, lzr, and lzi--into Quad_ak1 by reference
1315
- var qPar = new Object(),
1316
- ee, mp, omp, relstp, t, u, ui, v, vi, zm,
1317
- i, j = 0, tFlag, triedFlag = 0; // Integer variables
1318
-
1319
- iPar.NZ = 0;// Number of zeros found
1320
- u = uu; // uu and vv are coefficients of the starting quadratic
1321
- v = vv;
1322
-
1323
- do {
1324
- qPar.li = qPar.lr = qPar.si = qPar.sr = 0.0;
1325
- Quad_ak1(1.0, u, v, qPar);
1326
- iPar.szr = qPar.sr;
1327
- iPar.szi = qPar.si;
1328
- iPar.lzr = qPar.lr;
1329
- iPar.lzi = qPar.li;
1330
-
1331
- // Return if roots of the quadratic are real and not close to multiple or nearly
1332
- // equal and of opposite sign.
1333
- if(Math.abs(Math.abs(iPar.szr) - Math.abs(iPar.lzr)) > 0.01 * Math.abs(iPar.lzr))
1334
- break;
1335
-
1336
- // Evaluate polynomial by quadratic synthetic division
1337
-
1338
- QuadSD_ak1(NN, u, v, p, qp, sdPar);
1339
-
1340
- mp = Math.abs(-((iPar.szr) * (sdPar.b)) + (sdPar.a)) + Math.abs((iPar.szi) * (sdPar.b));
1341
-
1342
- // Compute a rigorous bound on the rounding error in evaluating p
1343
-
1344
- zm = Math.sqrt(Math.abs(v));
1345
- ee = 2.0 * Math.abs(qp[0]);
1346
- t = -((iPar.szr) * (sdPar.b));
1347
-
1348
- for(i = 1; i < N; i++) {
1349
- ee = ee * zm + Math.abs(qp[i]);
1350
- }
1351
-
1352
- ee = ee * zm + Math.abs(t + sdPar.a);
1353
- ee = (9.0 * ee + 2.0 * Math.abs(t) - 7.0 * (Math.abs((sdPar.a) + t) + zm * Math.abs((sdPar.b)))) * DBL_EPSILON;
1354
-
1355
- // Iteration has converged sufficiently if the polynomial value is less than 20 times this bound
1356
- if(mp <= 20.0 * ee) {
1357
- iPar.NZ = 2;
1358
- break;
1359
- }
1360
-
1361
- j++;
1362
- // Stop iteration after 20 steps
1363
- if(j > 20)
1364
- break;
1365
- if(j >= 2) {
1366
- if((relstp <= 0.01) && (mp >= omp) && (!triedFlag)) {
1367
- // A cluster appears to be stalling the convergence. Five fixed shift
1368
- // steps are taken with a u, v close to the cluster.
1369
- relstp = ((relstp < DBL_EPSILON) ? Math.sqrt(DBL_EPSILON) : Math.sqrt(relstp));
1370
- u -= u * relstp;
1371
- v += v * relstp;
1372
-
1373
- QuadSD_ak1(NN, u, v, p, qp, sdPar);
1374
- for(i = 0; i < 5; i++) {
1375
- tFlag = calcSC_ak1(DBL_EPSILON, N, sdPar.a, sdPar.b, calcPar, K, u, v, qk);
1376
- nextK_ak1(DBL_EPSILON, N, tFlag, sdPar.a, sdPar.b, calcPar, K, qk, qp);
1377
- }
1378
-
1379
- triedFlag = 1;
1380
- j = 0;
1381
-
1382
- }
1383
- }
1384
- omp = mp;
1385
-
1386
- // Calculate next K polynomial and new u and v
1387
- tFlag = calcSC_ak1(DBL_EPSILON, N, sdPar.a, sdPar.b, calcPar, K, u, v, qk);
1388
- nextK_ak1(DBL_EPSILON, N, tFlag, sdPar.a, sdPar.b, calcPar, K, qk, qp);
1389
- tFlag = calcSC_ak1(DBL_EPSILON, N, sdPar.a, sdPar.b, calcPar, K, u, v, qk);
1390
- newest_ak1(tFlag, sdPar, sdPar.a, calcPar.a1, calcPar.a3, calcPar.a7, sdPar.b, calcPar.c, calcPar.d, calcPar.f, calcPar.g, calcPar.h, u, v, K, N, p);
1391
- ui = sdPar.a;
1392
- vi = sdPar.b;
1393
-
1394
- // If vi is zero, the iteration is not converging
1395
- if(vi != 0) {
1396
- relstp = Math.abs((-v + vi) / vi);
1397
- u = ui;
1398
- v = vi;
1399
- }
1400
- }
1401
- while(vi != 0);
1402
- return;
1403
- }
1404
-
1405
- function RealIT_ak1(DBL_EPSILON, iPar, sdPar, N, p, NN, qp, K, qk) {
1406
- // Variable-shift H-polynomial iteration for a real zero
1407
- // sss - starting iterate = sdPar.a
1408
- // NZ - number of zeros found = iPar.NZ
1409
- // dumFlag - flag to indicate a pair of zeros near real axis, returned to iFlag
1410
-
1411
- var ee, kv, mp, ms, omp, pv, s, t,
1412
- dumFlag, i, j, nm1 = N - 1; // Integer variables
1413
-
1414
- iPar.NZ = j = dumFlag = 0;
1415
- s = sdPar.a;
1416
-
1417
- for(; ; ) {
1418
- pv = p[0];
1419
-
1420
- // Evaluate p at s
1421
- qp[0] = pv;
1422
- for(i = 1; i < NN; i++) {
1423
- qp[i] = pv = pv * s + p[i];
1424
- }
1425
- mp = Math.abs(pv);
1426
-
1427
- // Compute a rigorous bound on the error in evaluating p
1428
- ms = Math.abs(s);
1429
- ee = 0.5 * Math.abs(qp[0]);
1430
- for(i = 1; i < NN; i++) {
1431
- ee = ee * ms + Math.abs(qp[i]);
1432
- }
1433
-
1434
- // Iteration has converged sufficiently if the polynomial value is less than
1435
- // 20 times this bound
1436
- if(mp <= 20.0 * DBL_EPSILON * (2.0 * ee - mp)) {
1437
- iPar.NZ = 1;
1438
- iPar.szr = s;
1439
- iPar.szi = 0.0;
1440
- break;
1441
- }
1442
- j++;
1443
- // Stop iteration after 10 steps
1444
- if(j > 10)
1445
- break;
1446
-
1447
- if(j >= 2) {
1448
- if((Math.abs(t) <= 0.001 * Math.abs(-t + s)) && (mp > omp)) {
1449
- // A cluster of zeros near the real axis has been encountered.
1450
- // Return with iFlag set to initiate a quadratic iteration.
1451
- dumFlag = 1;
1452
- iPar.a = s;
1453
- break;
1454
- } // End if ((fabs(t) <= 0.001*fabs(s - t)) && (mp > omp))
1455
- } //End if (j >= 2)
1456
-
1457
- // Return if the polynomial value has increased significantly
1458
- omp = mp;
1459
-
1460
- // Compute t, the next polynomial and the new iterate
1461
- qk[0] = kv = K[0];
1462
- for(i = 1; i < N; i++) {
1463
- qk[i] = kv = kv * s + K[i];
1464
- }
1465
-
1466
- if(Math.abs(kv) > Math.abs(K[nm1]) * 10.0 * DBL_EPSILON) {
1467
- // Use the scaled form of the recurrence if the value of K at s is non-zero
1468
- t = -(pv / kv);
1469
- K[0] = qp[0];
1470
- for(i = 1; i < N; i++) {
1471
- K[i] = t * qk[i - 1] + qp[i];
1472
- }
1473
- }
1474
- else {
1475
- // Use unscaled form
1476
- K[0] = 0.0;
1477
- for(i = 1; i < N; i++)
1478
- K[i] = qk[i - 1];
1479
- }
1480
-
1481
- kv = K[0];
1482
- for(i = 1; i < N; i++) {
1483
- kv = kv * s + K[i];
1484
- }
1485
- t = ((Math.abs(kv) > (Math.abs(K[nm1]) * 10.0 * DBL_EPSILON)) ? -(pv / kv) : 0.0);
1486
- s += t;
1487
- }
1488
- return dumFlag;
1489
- }
1490
-
1491
- function Fxshfr_ak1(DBL_EPSILON, MDP1, L2, sr, v, K, N, p, NN, qp, u, iPar) {
1492
-
1493
- // Computes up to L2 fixed shift K-polynomials, testing for convergence in the linear or
1494
- // quadratic case. Initiates one of the variable shift iterations and returns with the
1495
- // number of zeros found.
1496
- // L2 limit of fixed shift steps
1497
- // iPar is a dummy variable for passing in the five parameters--NZ, lzi, lzr, szi, and szr--by reference
1498
- // NZ number of zeros found
1499
- var sdPar = new Object(), // sdPar is a dummy variable for passing the two parameters--a and b--into QuadSD_ak1 by reference
1500
- calcPar = new Object(),
1501
- // calcPar is a dummy variable for passing the nine parameters--a1, a3, a7, c, d, e, f, g, and h --into calcSC_ak1 by reference
1502
-
1503
- qk = new Array(MDP1),
1504
- svk = new Array(MDP1),
1505
- a, b, betas, betav, oss, ots, otv, ovv, s, ss, ts, tss, tv, tvv, ui, vi, vv,
1506
- fflag, i, iFlag = 1, j, spass, stry, tFlag, vpass, vtry; // Integer variables
1507
-
1508
- iPar.NZ = 0;
1509
- betav = betas = 0.25;
1510
- oss = sr;
1511
- ovv = v;
1512
-
1513
- //Evaluate polynomial by synthetic division
1514
- sdPar.b = sdPar.a = 0.0;
1515
- QuadSD_ak1(NN, u, v, p, qp, sdPar);
1516
- a = sdPar.a;
1517
- b = sdPar.b;
1518
- calcPar.h = calcPar.g = calcPar.f = calcPar.e = calcPar.d = calcPar.c = calcPar.a7 = calcPar.a3 = calcPar.a1 = 0.0;
1519
- tFlag = calcSC_ak1(DBL_EPSILON, N, a, b, calcPar, K, u, v, qk);
1520
-
1521
- for(j = 0; j < L2; j++) {
1522
- fflag = 1;
1523
-
1524
- // Calculate next K polynomial and estimate v
1525
- nextK_ak1(DBL_EPSILON, N, tFlag, a, b, calcPar, K, qk, qp);
1526
- tFlag = calcSC_ak1(DBL_EPSILON, N, a, b, calcPar, K, u, v, qk);
1527
-
1528
- // Use sdPar for passing in uu and vv instead of defining a brand-new variable.
1529
- // sdPar.a = ui, sdPar.b = vi
1530
- newest_ak1(tFlag, sdPar, a, calcPar.a1, calcPar.a3, calcPar.a7, b, calcPar.c, calcPar.d, calcPar.f, calcPar.g, calcPar.h, u, v, K, N, p);
1531
- ui = sdPar.a;
1532
- vv = vi = sdPar.b;
1533
-
1534
- // Estimate s
1535
- ss = ((K[N - 1] != 0.0) ? -(p[N] / K[N - 1]) : 0.0);
1536
- ts = tv = 1.0;
1537
-
1538
- if((j != 0) && (tFlag != 3)) {
1539
- // Compute relative measures of convergence of s and v sequences
1540
- tv = ((vv != 0.0) ? Math.abs((vv - ovv) / vv) : tv);
1541
- ts = ((ss != 0.0) ? Math.abs((ss - oss) / ss) : ts);
1542
-
1543
- // If decreasing, multiply the two most recent convergence measures
1544
- tvv = ((tv < otv) ? tv * otv : 1.0);
1545
- tss = ((ts < ots) ? ts * ots : 1.0);
1546
-
1547
- // Compare with convergence criteria
1548
- vpass = ((tvv < betav) ? 1 : 0);
1549
- spass = ((tss < betas) ? 1 : 0);
1550
-
1551
- if((spass) || (vpass)) {
1552
-
1553
- // At least one sequence has passed the convergence test.
1554
- // Store variables before iterating
1555
-
1556
- for(i = 0; i < N; i++) {
1557
- svk[i] = K[i];
1558
- }
1559
- s = ss;
1560
-
1561
- // Choose iteration according to the fastest converging sequence
1562
-
1563
- stry = vtry = 0;
1564
-
1565
- for(; ; ) {
1566
- if((fflag && ((fflag = 0) == 0)) && ((spass) && (!vpass || (tss < tvv)))) {
1567
- ;// Do nothing. Provides a quick "short circuit".
1568
- }
1569
- else {
1570
- QuadIT_ak1(DBL_EPSILON, N, iPar, ui, vi, qp, NN, sdPar, p, qk, calcPar, K);
1571
- a = sdPar.a;
1572
- b = sdPar.b;
1573
-
1574
- if((iPar.NZ) > 0)
1575
- return;
1576
-
1577
- // Quadratic iteration has failed. Flag that it has been tried and decrease the
1578
- // convergence criterion
1579
- iFlag = vtry = 1;
1580
- betav *= 0.25;
1581
-
1582
- // Try linear iteration if it has not been tried and the s sequence is converging
1583
- if(stry || (!spass)) {
1584
- iFlag = 0;
1585
- }
1586
- else {
1587
- for(i = 0; i < N; i++)
1588
- K[i] = svk[i];
1589
- }
1590
- }
1591
- //fflag = 0;
1592
- if(iFlag != 0) {
1593
- // Use sdPar for passing in s instead of defining a brand-new variable.
1594
- // sdPar.a = s
1595
- sdPar.a = s;
1596
- iFlag = RealIT_ak1(DBL_EPSILON, iPar, sdPar, N, p, NN, qp, K, qk);
1597
- s = sdPar.a;
1598
-
1599
- if((iPar.NZ) > 0)
1600
- return;
1601
-
1602
- // Linear iteration has failed. Flag that it has been tried and decrease the
1603
- // convergence criterion
1604
- stry = 1;
1605
- betas *= 0.25;
1606
-
1607
- if(iFlag != 0) {
1608
- // If linear iteration signals an almost double real zero, attempt quadratic iteration
1609
- ui = -(s + s);
1610
- vi = s * s;
1611
- continue;
1612
-
1613
- }
1614
- }
1615
-
1616
- // Restore variables
1617
- for(i = 0; i < N; i++)
1618
- K[i] = svk[i];
1619
-
1620
- // Try quadratic iteration if it has not been tried and the v sequence is converging
1621
- if(!vpass || vtry)
1622
- break; // Break out of infinite for loop
1623
-
1624
- }
1625
-
1626
- // Re-compute qp and scalar values to continue the second stage
1627
-
1628
- QuadSD_ak1(NN, u, v, p, qp, sdPar);
1629
- a = sdPar.a;
1630
- b = sdPar.b;
1631
-
1632
- tFlag = calcSC_ak1(DBL_EPSILON, N, a, b, calcPar, K, u, v, qk);
1633
- }
1634
- }
1635
- ovv = vv;
1636
- oss = ss;
1637
- otv = tv;
1638
- ots = ts;
1639
- }
1640
- return;
1641
- }
1642
-
1643
- function rpSolve(degPar, p, zeror, zeroi) {
1644
- var N = degPar.Degree,
1645
- RADFAC = 3.14159265358979323846 / 180, // Degrees-to-radians conversion factor = PI/180
1646
- LB2 = Math.LN2, // Dummy variable to avoid re-calculating this value in loop below
1647
- MDP1 = degPar.Degree + 1,
1648
- K = new Array(MDP1),
1649
- pt = new Array(MDP1),
1650
- qp = new Array(MDP1),
1651
- temp = new Array(MDP1),
1652
- // qPar is a dummy variable for passing the four parameters--sr, si, lr, and li--by reference
1653
- qPar = new Object(),
1654
- // Fxshfr_Par is a dummy variable for passing parameters by reference : NZ, lzi, lzr, szi, szr);
1655
- Fxshfr_Par = new Object(),
1656
- bnd, DBL_EPSILON, df, dx, factor, ff, moduli_max, moduli_min, sc, x, xm,
1657
- aa, bb, cc, sr, t, u, xxx,
1658
- j, jj, l, NM1, NN, zerok;// Integer variables
1659
-
1660
- // Calculate the machine epsilon and store in the variable DBL_EPSILON.
1661
- // To calculate this value, just use existing variables rather than create new ones that will be used only for this code block
1662
- aa = 1.0;
1663
- do {
1664
- DBL_EPSILON = aa;
1665
- aa /= 2;
1666
- bb = 1.0 + aa;
1667
- }
1668
- while(bb > 1.0);
1669
-
1670
- var LO = Number.MIN_VALUE / DBL_EPSILON,
1671
- cosr = Math.cos(94.0 * RADFAC), // = -0.069756474
1672
- sinr = Math.sin(94.0 * RADFAC), // = 0.99756405
1673
- xx = Math.sqrt(0.5), // = 0.70710678
1674
- yy = -xx;
1675
-
1676
- Fxshfr_Par.NZ = j = 0;
1677
- Fxshfr_Par.szr = Fxshfr_Par.szi = Fxshfr_Par.lzr = Fxshfr_Par.lzi = 0.0;
1678
-
1679
- // Remove zeros at the origin, if any
1680
- while(p[N] == 0) {
1681
- zeror[j] = zeroi[j] = 0;
1682
- N--;
1683
- j++;
1684
- }
1685
- NN = N + 1;
1686
-
1687
- // >>>>> Begin Main Loop <<<<<
1688
- while(N >= 1) { // Main loop
1689
- // Start the algorithm for one zero
1690
- if(N <= 2) {
1691
- // Calculate the final zero or pair of zeros
1692
- if(N < 2) {
1693
- zeror[degPar.Degree - 1] = -(p[1] / p[0]);
1694
- zeroi[degPar.Degree - 1] = 0;
1695
- }
1696
- else {
1697
- qPar.li = qPar.lr = qPar.si = qPar.sr = 0.0;
1698
- Quad_ak1(p[0], p[1], p[2], qPar);
1699
- zeror[degPar.Degree - 2] = qPar.sr;
1700
- zeroi[degPar.Degree - 2] = qPar.si;
1701
- zeror[degPar.Degree - 1] = qPar.lr;
1702
- zeroi[degPar.Degree - 1] = qPar.li;
1703
- }
1704
- break;
1705
- }
1706
-
1707
- // Find the largest and smallest moduli of the coefficients
1708
- moduli_max = 0.0;
1709
- moduli_min = Number.MAX_VALUE;
1710
-
1711
- for(i = 0; i < NN; i++) {
1712
- x = Math.abs(p[i]);
1713
- if(x > moduli_max)
1714
- moduli_max = x;
1715
- if((x != 0) && (x < moduli_min))
1716
- moduli_min = x;
1717
- }
1718
-
1719
- // Scale if there are large or very small coefficients
1720
- // Computes a scale factor to multiply the coefficients of the polynomial. The scaling
1721
- // is done to avoid overflow and to avoid undetected underflow interfering with the
1722
- // convergence criterion.
1723
- // The factor is a power of the base.
1724
- sc = LO / moduli_min;
1725
-
1726
- if(((sc <= 1.0) && (moduli_max >= 10)) || ((sc > 1.0) && (Number.MAX_VALUE / sc >= moduli_max))) {
1727
- sc = ((sc == 0) ? Number.MIN_VALUE : sc);
1728
- l = Math.floor(Math.log(sc) / LB2 + 0.5);
1729
- factor = Math.pow(2.0, l);
1730
- if(factor != 1.0) {
1731
- for(i = 0; i < NN; i++)
1732
- p[i] *= factor;
1733
- }
1734
- }
1735
-
1736
- // Compute lower bound on moduli of zeros
1737
- for(var i = 0; i < NN; i++)
1738
- pt[i] = Math.abs(p[i]);
1739
- pt[N] = -(pt[N]);
1740
- NM1 = N - 1;
1741
-
1742
- // Compute upper estimate of bound
1743
- x = Math.exp((Math.log(-pt[N]) - Math.log(pt[0])) / N);
1744
-
1745
- if(pt[NM1] != 0) {
1746
- // If Newton step at the origin is better, use it
1747
- xm = -pt[N] / pt[NM1];
1748
- x = ((xm < x) ? xm : x);
1749
- }
1750
-
1751
- // Chop the interval (0, x) until ff <= 0
1752
- xm = x;
1753
- do {
1754
- x = xm;
1755
- xm = 0.1 * x;
1756
- ff = pt[0];
1757
- for(var i = 1; i < NN; i++) {
1758
- ff = ff * xm + pt[i];
1759
- }
1760
- }
1761
- while(ff > 0); // End do-while loop
1762
-
1763
- dx = x;
1764
- // Do Newton iteration until x converges to two decimal places
1765
-
1766
- do {
1767
- df = ff = pt[0];
1768
- for(var i = 1; i < N; i++) {
1769
- ff = x * ff + pt[i];
1770
- df = x * df + ff;
1771
- } // End for i
1772
- ff = x * ff + pt[N];
1773
- dx = ff / df;
1774
- x -= dx;
1775
- }
1776
- while(Math.abs(dx / x) > 0.005); // End do-while loop
1777
-
1778
- bnd = x;
1779
-
1780
- // Compute the derivative as the initial K polynomial and do 5 steps with no shift
1781
- for(var i = 1; i < N; i++)
1782
- K[i] = (N - i) * p[i] / N;
1783
- K[0] = p[0];
1784
- aa = p[N];
1785
- bb = p[NM1];
1786
- zerok = ((K[NM1] == 0) ? 1 : 0);
1787
-
1788
- for(jj = 0; jj < 5; jj++) {
1789
- cc = K[NM1];
1790
- if(zerok) {
1791
- // Use unscaled form of recurrence
1792
- for(var i = 0; i < NM1; i++) {
1793
- j = NM1 - i;
1794
- K[j] = K[j - 1];
1795
- } // End for i
1796
- K[0] = 0;
1797
- zerok = ((K[NM1] == 0) ? 1 : 0);
1798
- }
1799
- else {
1800
- // Used scaled form of recurrence if value of K at 0 is nonzero
1801
- t = -aa / cc;
1802
- for(var i = 0; i < NM1; i++) {
1803
- j = NM1 - i;
1804
- K[j] = t * K[j - 1] + p[j];
1805
- } // End for i
1806
- K[0] = p[0];
1807
- zerok = ((Math.abs(K[NM1]) <= Math.abs(bb) * DBL_EPSILON * 10.0) ? 1 : 0);
1808
- }
1809
- }
1810
-
1811
- // Save K for restarts with new shifts
1812
- for(var i = 0; i < N; i++)
1813
- temp[i] = K[i];
1814
-
1815
- // Loop to select the quadratic corresponding to each new shift
1816
- for(jj = 1; jj <= 20; jj++) {
1817
-
1818
- // Quadratic corresponds to a double shift to a non-real point and its
1819
- // complex conjugate. The point has modulus BND and amplitude rotated
1820
- // by 94 degrees from the previous shift.
1821
-
1822
- xxx = -(sinr * yy) + cosr * xx;
1823
- yy = sinr * xx + cosr * yy;
1824
- xx = xxx;
1825
- sr = bnd * xx;
1826
- u = -(2.0 * sr);
1827
-
1828
- // Second stage calculation, fixed quadratic
1829
- Fxshfr_ak1(DBL_EPSILON, MDP1, 20 * jj, sr, bnd, K, N, p, NN, qp, u, Fxshfr_Par);
1830
-
1831
- if(Fxshfr_Par.NZ != 0) {
1832
- // The second stage jumps directly to one of the third stage iterations and
1833
- // returns here if successful. Deflate the polynomial, store the zero or
1834
- // zeros, and return to the main algorithm.
1835
- j = degPar.Degree - N;
1836
- zeror[j] = Fxshfr_Par.szr;
1837
- zeroi[j] = Fxshfr_Par.szi;
1838
- NN = NN - Fxshfr_Par.NZ;
1839
- N = NN - 1;
1840
- for(var i = 0; i < NN; i++)
1841
- p[i] = qp[i];
1842
- if(Fxshfr_Par.NZ != 1) {
1843
- zeror[j + 1] = Fxshfr_Par.lzr;
1844
- zeroi[j + 1] = Fxshfr_Par.lzi;
1845
- }
1846
- break;
1847
- }
1848
- else {
1849
- // If the iteration is unsuccessful, another quadratic is chosen after restoring K
1850
- for(var i = 0; i < N; i++) {
1851
- K[i] = temp[i];
1852
- }
1853
- }
1854
- }
1855
- // Return with failure if no convergence with 20 shifts
1856
- if(jj > 20) {
1857
- degPar.Degree -= N;
1858
- break;
1859
- }
1860
- }
1861
- // >>>>> End Main Loop <<<<<
1862
- return;
1863
- }
1864
- //--> End Jenkins-Traub
1865
- rpSolve(degreePar, p, zeror, zeroi);
1866
-
1867
- var l = zeroi.length;
1868
- //format the output
1869
- for(i = 0; i < l; i++) {
1870
- // We round the imaginary part to avoid having something crazy like 5.67e-16.
1871
- var img = round(zeroi[i], decp + 8),
1872
- real = round(zeror[i], decp + 8);
1873
- // Did the rounding pay off? If the rounding did nothing more than chop off a few digits then no.
1874
- // If the rounding results in a a number at least 3 digits shorter we'll keep it else we'll keep
1875
- // the original otherwise the rounding was worth it.
1876
- real = decp - String(real).length > 2 ? real : zeror[i];
1877
- var sign = img < 0 ? '-' : '';
1878
-
1879
- // Remove the zeroes
1880
- if(real === 0) {
1881
- real = '';
1882
- }
1883
- if(img === 0) {
1884
- img = '';
1885
- }
1886
-
1887
- // Remove 1 as the multiplier and discard imaginary part if there isn't one.
1888
- img = Math.abs(img) === 1 ? sign + 'i' : (img ? img + '*i' : '');
1889
-
1890
- var num = (real && img) ? real + '+' + img : real + img;
1891
- zeror[i] = num.replace(/\+\-/g, '-');
1892
- }
1893
- return zeror;
1894
- }
1895
- },
1896
- roots: function (symbol) {
1897
-
1898
- if(symbol.isConstant(true, true)) {
1899
- return core.Utils.nroots(symbol);
1900
- }
1901
- var roots = __.proots(symbol).map(function (x) {
1902
- return _.parse(x);
1903
- });
1904
- return core.Vector.fromArray(roots);
1905
- },
1906
- froot: function (f, guess, dx) {
1907
- var newtonraph = function (xn) {
1908
- var mesh = 1e-12,
1909
- // If the derivative was already provided then don't recalculate.
1910
- df = dx ? dx : core.Utils.build(core.Calculus.diff(f.clone())),
1911
- // If the function was passed in as a function then don't recalculate.
1912
- fn = f instanceof Function ? f : core.Utils.build(f),
1913
- max = 10000,
1914
- done = false,
1915
- safety = 0;
1916
- while(!done) {
1917
- var x = xn - (fn(xn) / df(xn));
1918
- //absolute values for both x & xn ensures that we indeed have the radius
1919
- var r = Math.abs(x) - Math.abs(xn),
1920
- delta = Math.abs(r);
1921
- xn = x;
1922
-
1923
- if(delta < mesh)
1924
- done = true;
1925
- else if(safety > max) {
1926
- xn = null;
1927
- done = true;
1928
- }
1929
-
1930
- safety++;
1931
- }
1932
- return xn;
1933
- };
1934
- return newtonraph(Number(guess));
1935
- },
1936
- quad: function (a, b, c) {
1937
- var q = function (a, b, c, sign) {
1938
- return _.parse('-(' + b + '+' + sign + '*sqrt((' + b + ')^2-4*(' + a + ')*(' + c + ')))/(2*' + a + ')');
1939
- };
1940
- return [q(a, b, c, 1), q(a, b, c, -1)];
1941
- },
1942
- sumProd: function (a, b) {
1943
- return __.quad(-b, a, -1).map(function (x) {
1944
- return x.invert();
1945
- });
1946
- },
1947
- coeffs: function (symbol, wrt, coeffs) {
1948
- wrt = String(wrt);
1949
- symbol = _.expand(symbol);
1950
- coeffs = coeffs || [new Symbol(0)];
1951
- //we cannot get coeffs for group EX
1952
- if(symbol.group === EX && symbol.contains(wrt, true))
1953
- _.error('Unable to get coefficients using expression ' + symbol.toString());
1954
- var vars = variables(symbol);
1955
- if(vars.length === 1 && vars[0] === wrt && !symbol.isImaginary()) {
1956
- var a = new Polynomial(symbol).coeffs.map(function (x) {
1957
- return new Symbol(x);
1958
- });
1959
-
1960
- for(var i = 0, l = a.length; i < l; i++) {
1961
- var coeff = a[i],
1962
- e = coeffs[i];
1963
- if(e)
1964
- coeff = _.add(e, coeff);
1965
- coeffs[i] = coeff; //transfer it all over
1966
- }
1967
- }
1968
- else {
1969
- if(!wrt)
1970
- _.error('Polynomial contains more than one variable. Please specify which variable is to be used!');
1971
- //if the variable isn't part of this polynomial then we're looking at x^0
1972
-
1973
- if(vars.indexOf(wrt) === -1) {
1974
- coeffs[0] = _.add(symbol, coeffs[0]);
1975
- }
1976
- else {
1977
- coeffs = coeffs || [new Symbol(0)];
1978
- if(symbol.group === CB) {
1979
- var s = symbol.symbols[wrt];
1980
- if(!s)
1981
- _.error('Expression is not a polynomial!');
1982
- var p = Number(s.power);
1983
- coeff = _.divide(symbol.clone(), s.clone());
1984
- if(coeff.contains(wrt, true) || p < 0 || !isInt(p))
1985
- _.error('Expression is not a polynomial!');
1986
- var e = coeffs[p];
1987
- if(e)
1988
- coeff = _.add(e, coeff);
1989
- coeffs[p] = coeff;
1990
- }
1991
- else if(symbol.group === CP) {
1992
- symbol.each(function (x) {
1993
- __.coeffs(x.clone(), wrt, coeffs);
1994
- }, true);
1995
- }
1996
- }
1997
- }
1998
- //fill holes
1999
- for(var i = 0, l = coeffs.length; i < l; i++)
2000
- if(typeof coeffs[i] === 'undefined')
2001
- coeffs[i] = new Symbol(0);
2002
-
2003
- return coeffs;
2004
- },
2005
- /**
2006
- * Get's all the powers of a particular polynomial including the denominators. The denominators powers
2007
- * are returned as negative. All remaining polynomials are returned as zero order polynomials.
2008
- * for example polyPowers(x^2+1/x+y+t) will return [ '-1', 0, '2' ]
2009
- * @param {Symbol} e
2010
- * @param {String} for_variable
2011
- * @param {Array} powers
2012
- * @returns {Array} An array of the powers
2013
- */
2014
- //assumes you've already verified that it's a polynomial
2015
- polyPowers: function (e, for_variable, powers) {
2016
- powers = powers || [];
2017
- var g = g = e.group;
2018
- if(g === PL && for_variable === e.value) {
2019
- powers = powers.concat(keys(e.symbols));
2020
- }
2021
- else if(g === CP) {
2022
- for(var s in e.symbols) {
2023
- var symbol = e.symbols[s];
2024
- var g = symbol.group, v = symbol.value;
2025
- if(g === S && for_variable === v)
2026
- powers.push(symbol.power);
2027
- else if(g === PL || g === CP)
2028
- powers = __.polyPowers(symbol, for_variable, powers);
2029
- else if(g === CB && symbol.contains(for_variable)) {
2030
- var t = symbol.symbols[for_variable];
2031
- if(t)
2032
- powers.push((t.power));
2033
- }
2034
- else if(g === N || for_variable !== v)
2035
- powers.push(0);
2036
- }
2037
- }
2038
- else if(g === CB && e.contains(for_variable)) {
2039
- powers.push(core.Utils.decompose_fn(e, for_variable, true).x.power);
2040
- }
2041
- return core.Utils.arrayUnique(powers).sort();
2042
- },
2043
- //The factor object
2044
- Factor: {
2045
- //splits the symbol in symbol and constant
2046
- split: function (symbol) {
2047
- var c = new Symbol(1); //the constants part
2048
- var s = new Symbol(1); //the symbolic part
2049
- __.Factor.factor(symbol, new Factors()).each(function (x) {
2050
- var t = _.parse(x);
2051
- if(x.isConstant(true)) {
2052
- c = _.multiply(c, t);
2053
- }
2054
- else {
2055
- s = _.multiply(s, t);
2056
- }
2057
- });
2058
- return [c, s];
2059
- },
2060
- mix: function (o, include_negatives) {
2061
- var factors = keys(o);
2062
- var l = factors.length;
2063
- var m = [];//create a row which we'r going to be mixing
2064
- for(var i = 0; i < l; i++) {
2065
- var factor = factors[i],
2066
- p = o[factor];
2067
- var ll = m.length;
2068
- for(var j = 0; j < ll; j++) {
2069
- var t = m[j] * factor;
2070
- m.push(t);
2071
- if(include_negatives)
2072
- m.push(-t);
2073
- }
2074
-
2075
- for(var j = 1; j <= p; j++)
2076
- m.push(Math.pow(factor, j));
2077
- }
2078
- return m;
2079
- },
2080
- //TODO: this method is to replace common factoring
2081
- common: function (symbol, factors) {
2082
- try {
2083
- if(symbol.group === CP) {
2084
- //this may have the unfortunate side effect of expanding and factoring again
2085
- //to only end up with the same result.
2086
- //TODO: try to avoid this
2087
- //collect the symbols and sort to have the longest first. Thinking is that the longest terms
2088
- //has to contain the variable in order for it to be factorable
2089
- var symbols = _.expand(symbol.clone(), true).collectSymbols(null, null, function (a, b) {
2090
- return (b.length || 1) - (a.length || 1);
2091
- });
2092
-
2093
- var map = {}; //create a map of common factors
2094
- var coeffs = [];
2095
- for(var i = 0; i < symbols.length; i++) {
2096
- var sym = symbols[i];
2097
- coeffs.push(sym.multiplier.clone());
2098
- sym.each(function (x) {
2099
- var p = Number(x.power);
2100
- //This check exits since we have a symbolic power.
2101
- //For the future... think about removing this check and modify for symbolic powers
2102
- if(isNaN(p))
2103
- throw new Error('exiting');
2104
- //loop through the symbols and lump together common terms
2105
- if(x.value in map) {
2106
- if(p < map[x.value][0])
2107
- map[x.value][0] = p;
2108
- map[x.value][1].push(x);
2109
- }
2110
- else
2111
- map[x.value] = [p, [x]];
2112
- });
2113
- }
2114
- //the factor
2115
- var factor = new Symbol(1);
2116
- for(var x in map) {
2117
- //if this factor is found in all terms since the length of
2118
- //matching variable terms matches the number of original terms
2119
- if(map[x][1].length === symbols.length) {
2120
- //generate a symbol and multiply into the factor
2121
- factor = _.multiply(factor, _.pow(new Symbol(x), new Symbol(map[x][0])));
2122
- }
2123
- }
2124
- //get coefficient factor
2125
- var c = core.Math2.QGCD.apply(null, coeffs);
2126
-
2127
- if(!c.equals(1)) {
2128
- factors.add(new Symbol(c));
2129
- for(var i = 0; i < symbols.length; i++) {
2130
- symbols[i].multiplier = symbols[i].multiplier.divide(c);
2131
- }
2132
- }
2133
-
2134
- //if we actuall found any factors
2135
- if(!factor.equals(1)) {
2136
- factors.add(factor);
2137
- symbol = new Symbol(0);
2138
- for(var i = 0; i < symbols.length; i++) {
2139
- symbol = _.add(symbol, _.divide(symbols[i], factor.clone()));
2140
- }
2141
- }
2142
- }
2143
- }
2144
- catch(e) {
2145
- ;
2146
- }
2147
-
2148
- return symbol;
2149
- },
2150
- zeroes: function (symbol, factors) {
2151
- var exit = function () {
2152
- throw new core.exceptions.ValueLimitExceededError('Exiting');
2153
- };
2154
- try {
2155
- var vars, term, sum, p, e;
2156
- symbol = _.expand(symbol.clone());
2157
- e = symbol.toString();
2158
- vars = variables(symbol);
2159
-
2160
- sum = new Symbol(0);
2161
-
2162
- var terms = [];
2163
- var powers = [];
2164
-
2165
- //start setting each variable to zero
2166
- for(var i = 0, l = vars.length; i < vars.length; i++) {
2167
- var subs = {};
2168
- //we want to create a subs object with all but the current variable set to zero
2169
- for(var j = 0; j < l; j++)
2170
- if(i !== j) //make sure we're not looking at the same variable
2171
- subs[vars[j]] = 0;
2172
- term = _.parse(e, subs);
2173
- var tp = term.power;
2174
- //the temporary power has to be an integer as well
2175
- if(!isInt(tp))
2176
- exit();
2177
- terms.push(term);
2178
- powers.push(term.power);
2179
- }
2180
-
2181
- //get the gcd. This will be the p in (a^n+b^m)^p
2182
- //if the gcd equals 1 meaning n = m then we need a tie breakder
2183
- if(core.Utils.allSame(powers)) {
2184
- //get p given x number of terms
2185
- var n_terms = symbol.length;
2186
- //the number of zeroes determines
2187
- var n_zeroes = terms.length;
2188
- if(n_zeroes === 2) {
2189
- p = new Frac(powers[0] / (n_terms - 1));
2190
- }
2191
- if(n_zeroes === 3) {
2192
- p = new Frac(powers[0] / Math.round((Math.sqrt(8 * n_terms - 1) - 3) / 2));
2193
- }
2194
- /*
2195
- //get the lowest possible power
2196
- //e.g. given b^4+2*a^2*b^2+a^4, the power we're looking for would be 2
2197
- symbol.each(function(x) {
2198
- if(x.group === CB)
2199
- x.each(function(y) {
2200
- if(!p || y.power.lessThan(p))
2201
- //p = Number(y.power);
2202
- p = y.power;
2203
- });
2204
- else if(!p || x.power.lessThan(p))
2205
- //p = Number(x.power);
2206
- p = x.power;
2207
- });
2208
- */
2209
- }
2210
- else
2211
- //p is just the gcd of the powers
2212
- p = core.Math2.QGCD.apply(null, powers);
2213
-
2214
- //if we don't have an integer then exit
2215
- if(!isInt(p))
2216
- exit();
2217
-
2218
- //build the factor
2219
- for(var i = 0; i < terms.length; i++) {
2220
- var t = terms[i];
2221
- var n = t.power.clone().divide(p);
2222
- t.multiplier = new Frac(Math.pow(t.multiplier, 1 / n));
2223
- t.power = p.clone();
2224
- sum = _.add(sum, t);
2225
- }
2226
-
2227
- //by now we have the factor of zeroes. We'll know if we got it right because
2228
- //we'll get a remainder of zero each time we divide by it
2229
- if(sum.group !== CP)
2230
- return symbol; //nothing to do
2231
-
2232
- while(true) {
2233
- var d = __.div(symbol.clone(), sum.clone());
2234
- if(d[1].equals(0)) {
2235
- symbol = d[0];
2236
- factors.add(sum.clone());
2237
- if(symbol.equals(1)) //we've reached 1 so done.
2238
- break;
2239
- }
2240
- else
2241
- break;
2242
- }
2243
- }
2244
- catch(e) {
2245
- }
2246
- ;
2247
-
2248
- return symbol;
2249
- },
2250
- factor: function (symbol, factors) {
2251
- // Don't try to factor constants
2252
- if(symbol.isConstant()) {
2253
- return core.Math2.factor(symbol);
2254
- }
2255
-
2256
- var _symbol = _.parse(symbol);
2257
- var retval = __.Factor._factor(_symbol, factors);
2258
- if(retval.equals(symbol)) {
2259
- return retval;
2260
- }
2261
-
2262
- if(retval.group === CB) {
2263
- var t = new Symbol(1);
2264
- var p = _.parse(retval.power);
2265
- //store the multiplier and strip it
2266
- var m = _.parse(retval.multiplier);
2267
-
2268
- retval.toUnitMultiplier();
2269
-
2270
- /*
2271
- * NOTE: for sign issues with factor START DEBUGGING HERE
2272
- */
2273
- //move the sign to t
2274
- if(retval.multiplier.lessThan(0)) {
2275
- t.negate();
2276
- retval.negate();
2277
- }
2278
-
2279
- retval.each(function (x) {
2280
- // Related to #566. Since the symbol's group may not have been properly
2281
- // updated, it's easier to just parse the symbol and have the parser
2282
- // do the update for us.
2283
- var factored = _.parse(__.Factor._factor(x));
2284
-
2285
- if(factored.group === CB) {
2286
- // Include the multiplier
2287
- m = _.multiply(m, Symbol.create(factored.multiplier));
2288
- factored.each(function (y) {
2289
- var _factored = _.parse(__.Factor._factor(y));
2290
- t = _.multiply(t, _factored);
2291
- if(_factored.group === CB) {
2292
- m = _.multiply(m, Symbol.create(_factored.multiplier));
2293
- }
2294
- });
2295
- }
2296
- else {
2297
- t = _.multiply(t, factored);
2298
- }
2299
- });
2300
-
2301
- //put back the multiplier and power
2302
- retval = _.pow(_.multiply(m, t), p);
2303
- }
2304
-
2305
- return retval;
2306
- },
2307
- quadFactor: function (symbol, factors) {
2308
- if(symbol.isPoly() && __.degree(symbol.equals(2))) {
2309
- //We've already checked that we're dealing with a polynomial
2310
- var v = core.Utils.variables(symbol)[0]; //get the variable
2311
- var coeffs = __.coeffs(symbol, v);
2312
- //factor the lead coefficient
2313
- var cf = __.Factor._factor(coeffs[2].clone());
2314
- //check if we have factors
2315
- if(cf.group === CB) {
2316
- var symbols = cf.collectSymbols();
2317
- //if the factors are greater than 2 we're done so exit
2318
- if(symbols.length > 2)
2319
- return symbol;
2320
- //if we have two factors then attempt to factor the polynomial
2321
- //let the factors be f1 and f1
2322
- //let the factors be (ax+b)(cx+d)
2323
- //let the coefficients be c1x^2+c2x+c3
2324
- //then a(x1)+c(x2)=c2 and x1*x2=c3
2325
- //we can solve for x1 and x2
2326
- var c = _.multiply(_.parse(coeffs[0]), _.parse(symbols[0]));
2327
- var b = _.parse(coeffs[1]).negate();
2328
- var a = _.parse(symbols[1]);
2329
- //solve the system
2330
- var root = __.quad(a, b, c).filter(function (x) {
2331
- if(core.Utils.isInt(x))
2332
- return x;
2333
- });
2334
- //if we have one root then find the other one by dividing the constant
2335
- if(root.length === 1) {
2336
- var root1 = root[0];
2337
- var root2 = _.divide(coeffs[0], _.parse(root1));
2338
- if(core.Utils.isInt(root2)) {
2339
- //we found them both
2340
- factors.add(_.parse(format('({0})*({1})+({2})', symbols[1], v, root2)));
2341
- factors.add(_.parse(format('({0})*({1})+({2})', symbols[0], v, root1)));
2342
- symbol = new Symbol(1);
2343
- }
2344
- }
2345
- }
2346
- }
2347
- return symbol;
2348
- },
2349
- cubeFactor: function (symbol, factors) {
2350
- if(symbol.isComposite()) {
2351
- var symbols = symbol.collectSymbols();
2352
- // The symbol should be in the form of a^3+-b^3. The length
2353
- // should therefore only be two. If it's any different from this
2354
- // then we're done
2355
- if(symbols.length === 2) {
2356
- // Store the signs and then strip them from the symbols
2357
- var sign_a = symbols[0].sign();
2358
- var a = symbols[0].clone().abs();
2359
- var sign_b = symbols[1].sign();
2360
- var b = symbols[1].clone().abs();
2361
- // Check if they're cube
2362
- if(a.isCube() && b.isCube()) {
2363
- // Keep the negative sign on the right, meaning b is always negative.
2364
- if(sign_a < sign_b) {
2365
- // Swap the signs and then the values
2366
- [sign_a, sign_b] = [sign_b, sign_a];
2367
- [a, b] = [b, a];
2368
- }
2369
-
2370
- // Get teh roots
2371
- var m_root_a = _.parse(a.getNth(3));
2372
- var m_root_b = _.parse(b.getNth(3));
2373
-
2374
- // Remove the cube for both
2375
- var x = _.multiply(_.expand(_.pow(a.clone().toUnitMultiplier(), _.parse('1/3'))), m_root_a);
2376
- var y = _.multiply(_.expand(_.pow(b.clone().toUnitMultiplier(), _.parse('1/3'))), m_root_b);
2377
-
2378
- if(sign_a === 1 && sign_b === -1) {
2379
- // Apply difference of cubes rule
2380
- factors.add(_.parse(format('(({0})-({1}))', x, y)));
2381
- factors.add(_.parse(format('(({0})^2+({0})*({1})+({1})^2)', x, y)));
2382
- symbol = Symbol(1);
2383
- }
2384
- else if(sign_a === 1 && sign_b === 1) {
2385
- // Apply sum of cubes rule
2386
- factors.add(_.parse(format('(({0})+({1}))', x, y)));
2387
- factors.add(_.parse(format('(({0})^2-({0})*({1})+({1})^2)', x, y)));
2388
- symbol = Symbol(1);
2389
- }
2390
- }
2391
- }
2392
- }
2393
-
2394
- return symbol;
2395
- },
2396
- _factor: function (symbol, factors) {
2397
- var g = symbol.group;
2398
- //some items cannot be factored any further so return those right away
2399
- if(symbol.group === FN) {
2400
- var arg = symbol.args[0];
2401
- if(arg.group === S && arg.isSimple()) {
2402
- return symbol;
2403
- }
2404
- }
2405
- else if(symbol.group === S && symbol.isSimple()) {
2406
- return symbol;
2407
- }
2408
-
2409
- // Expand the symbol to get it in a predictable form. If this step
2410
- // is skipped some factors are missed.
2411
- //if(symbol.group === CP && !(even(symbol.power) && symbol.multiplier.lessThan(0))) {
2412
- if(symbol.group === CP) {
2413
- symbol.distributeMultiplier(true);
2414
- var t = new Symbol(0);
2415
- symbol.each(function (x) {
2416
- if((x.group === CP && x.power.greaterThan(1) || x.group === CB))
2417
- x = _.expand(x);
2418
- t = _.add(t, x);
2419
- });
2420
- t.power = symbol.power;
2421
-
2422
- symbol = t;
2423
- }
2424
-
2425
- if(symbol.group === FN && symbol.fname !== 'sqrt') {
2426
- symbol = core.Utils.evaluate(symbol);
2427
- }
2428
-
2429
- //make a copy of the symbol to return if something goes wrong
2430
- var untouched = symbol.clone();
2431
- try {
2432
- if(symbol.group === CB) {
2433
- var p = _.parse(symbol.power);
2434
-
2435
- var den_array, num_array, den, num, dfact, nfact;
2436
- //grab the denominator and strip the multiplier and power. Store them in an array
2437
- den_array = __.Simplify.strip(symbol.getDenom());
2438
- num_array = __.Simplify.strip(symbol.getNum());
2439
-
2440
- den = den_array.pop();
2441
- num = num_array.pop();
2442
-
2443
- //if the numerator equals the symbol then we've hit the simplest form and then we're done
2444
- if(num.equals(symbol)) {
2445
- return symbol;
2446
- }
2447
- nfact = __.Factor.factor(num);
2448
- dfact = __.Factor.factor(den);
2449
-
2450
- var n = __.Simplify.unstrip(num_array, nfact);
2451
- var d = __.Simplify.unstrip(den_array, dfact);
2452
-
2453
- var retval = _.divide(n, d);
2454
-
2455
- return retval;
2456
- }
2457
- if(symbol.group === S) {
2458
- return symbol; //absolutely nothing to do
2459
- }
2460
-
2461
- if(symbol.isConstant()) {
2462
- if(symbol.equals(1))
2463
- return symbol.clone();
2464
- var ret = core.Math2.factor(symbol);
2465
- return ret;
2466
- }
2467
-
2468
- var p = symbol.power.clone();
2469
-
2470
- if(isInt(p) && !(p.lessThan(0) && symbol.group === FN)) {
2471
- var sign = p.sign();
2472
- symbol.toLinear();
2473
- factors = factors || new Factors();
2474
- var map = {};
2475
- symbol = _.parse(core.Utils.subFunctions(symbol, map));
2476
- if(keys(map).length > 0) { //it might have functions
2477
- factors.preAdd = function (factor) {
2478
- var ret = _.parse(factor, core.Utils.getFunctionsSubs(map));
2479
- return ret;
2480
- };
2481
- }
2482
-
2483
- //strip the power
2484
- if(!symbol.isLinear()) {
2485
- factors.pFactor = symbol.power.toString();
2486
- symbol.toLinear();
2487
- }
2488
-
2489
- var vars = variables(symbol);
2490
- //bypass for imaginary. TODO: find a better solution
2491
- if(symbol.isImaginary()) {
2492
- vars.push(core.Settings.IMAGINARY);
2493
- }
2494
- var multiVar = vars.length > 1;
2495
-
2496
- //minor optimization. Seems to cut factor time by half in some cases.
2497
- if(multiVar) {
2498
- var all_S = true, all_unit = true;
2499
- symbol.each(function (x) {
2500
- if(x.group !== S)
2501
- all_S = false;
2502
- if(!x.multiplier.equals(1))
2503
- all_unit = false;
2504
- });
2505
-
2506
- if(all_S && all_unit) {
2507
- return _.pow(_.parse(symbol, core.Utils.getFunctionsSubs(map)), _.parse(p));
2508
- }
2509
- }
2510
-
2511
- //factor the coefficients
2512
- var coeff_factors = new Factors();
2513
-
2514
- symbol = __.Factor.coeffFactor(symbol, coeff_factors);
2515
-
2516
- coeff_factors.each(function (x) {
2517
- // If the factor was negative but was within a square then it becomes positive
2518
- if(even(p) && x.lessThan(0)) {
2519
- x.negate();
2520
- }
2521
-
2522
- if(sign < 0)
2523
- x.invert();
2524
- factors.add(x);
2525
- });
2526
-
2527
- //factor the power
2528
- var power_factors = new Factors();
2529
- symbol = __.Factor.powerFactor(symbol, power_factors);
2530
- power_factors.each(function (x) {
2531
- if(sign < 0)
2532
- x.invert();
2533
- factors.add(x);
2534
- });
2535
-
2536
- if(!multiVar) {
2537
- //pass in vars[0] for safety
2538
- var v = vars[0];
2539
-
2540
- symbol = __.Factor.squareFree(symbol, factors, v);
2541
-
2542
- var t_factors = new Factors();
2543
-
2544
- symbol = __.Factor.trialAndError(symbol, t_factors, v);
2545
-
2546
- //generate a symbol based off the last factors
2547
- var tf_symbol = t_factors.toSymbol();
2548
- //if nothing was factored then return the factors
2549
- if(tf_symbol.equals(untouched)) {
2550
- return tf_symbol;
2551
- }
2552
-
2553
- for(var x in t_factors.factors) {
2554
- //store the current factor in t_factor
2555
- var t_factor = t_factors.factors[x];
2556
- factors.add(_.pow(t_factor, _.parse(p)));
2557
- }
2558
- //if we still don't have a factor and it's quadratic then let's just do a quad factor
2559
- if(symbol.equals(untouched)) {
2560
- symbol = __.Factor.quadFactor(symbol, factors);
2561
- }
2562
-
2563
- }
2564
- else {
2565
- // Try sum and difference of cubes
2566
- symbol = __.Factor.cubeFactor(symbol, factors);
2567
-
2568
- symbol = __.Factor.mfactor(symbol, factors);
2569
-
2570
- //put back the sign of power
2571
- factors.each(function (x) {
2572
- if(sign < 0)
2573
- x.power.negate();
2574
- });
2575
- }
2576
-
2577
- //last minute clean up
2578
- symbol = _.parse(symbol, core.Utils.getFunctionsSubs(map));
2579
-
2580
- var addPower = factors.length === 1;
2581
-
2582
- factors.add(_.pow(symbol, _.parse(p)));
2583
-
2584
- var retval = factors.toSymbol();
2585
-
2586
- // We may have only factored out the symbol itself so we end up with a factor of one
2587
- // where the power needs to be placed back
2588
- // e.g. factor((2*y+p)^2). Here we end up having a factor of 1 remaining and a p of 2.
2589
- if(addPower && symbol.equals(1) && retval.isLinear()) {
2590
- retval = _.pow(retval, _.parse(p));
2591
- }
2592
-
2593
- return retval;
2594
- }
2595
-
2596
- return symbol;
2597
- }
2598
- catch(e) {
2599
- //no need to stop the show because something went wrong :). Just return the unfactored.
2600
- return untouched;
2601
- }
2602
- },
2603
- reduce: function (symbol, factors) {
2604
- if(symbol.group === CP && symbol.length === 2) {
2605
- var symbols = symbol.collectSymbols().sort(function (a, b) {
2606
- return b.multiplier - a.multiplier;
2607
- });
2608
- if(symbols[0].power.equals(symbols[1].power)) {
2609
- //x^n-a^n
2610
- var n = _.parse(symbols[0].power),
2611
- a = symbols[0].clone().toLinear(),
2612
- b = symbols[1].clone().toLinear();
2613
-
2614
- //apply rule: (a-b)*sum(a^(n-i)*b^(i-1),1,n)
2615
- factors.add(_.add(a.clone(), b.clone()));
2616
- //flip the sign
2617
- b.negate();
2618
- //turn n into a number
2619
- var nn = Number(n);
2620
- //the remainder
2621
- var result = new Symbol(0);
2622
- for(var i = 1; i <= nn; i++) {
2623
- var aa = _.pow(a.clone(), _.subtract(n.clone(), new Symbol(i))),
2624
- bb = _.pow(b.clone(), _.subtract(new Symbol(i), new Symbol(1)));
2625
- result = _.add(result, _.multiply(aa, bb));
2626
- }
2627
- return result;
2628
- }
2629
- }
2630
- return symbol;
2631
- },
2632
- /**
2633
- * Makes Symbol square free
2634
- * @param {Symbol} symbol
2635
- * @param {Factors} factors
2636
- * @@param {String} variable The variable which is being factored
2637
- * @returns {[Symbol, Factor]}
2638
- */
2639
- squareFree: function (symbol, factors, variable) {
2640
- if(symbol.isConstant() || symbol.group === S)
2641
- return symbol;
2642
-
2643
- var poly = new Polynomial(symbol, variable);
2644
- var sqfr = poly.squareFree();
2645
- var p = sqfr[2];
2646
- //if we found a square then the p entry in the array will be non-unit
2647
- if(p !== 1) {
2648
- //make sure the remainder doesn't have factors
2649
- var t = sqfr[1].toSymbol();
2650
- t.power = t.power.multiply(new Frac(p));
2651
- //send the factor to be fatored to be sure it's completely factored
2652
- factors.add(__.Factor.factor(t));
2653
-
2654
- var retval = __.Factor.squareFree(sqfr[0].toSymbol(), factors);
2655
-
2656
- return retval;
2657
- }
2658
-
2659
- return symbol;
2660
- },
2661
- /**
2662
- * Factors the powers such that the lowest power is a constant
2663
- * @param {Symbol} symbol
2664
- * @param {Factors} factors
2665
- * @returns {[Symbol, Factor]}
2666
- */
2667
- powerFactor: function (symbol, factors) {
2668
- //only PL need apply
2669
- if(symbol.group !== PL || symbol.previousGroup === EX)
2670
- return symbol;
2671
- var k = keys(symbol.symbols);
2672
- //we expect only numeric powers so return all else
2673
- if(!core.Utils.allNumeric(k))
2674
- return symbol;
2675
-
2676
- var d = core.Utils.arrayMin(k);
2677
- var retval = new Symbol(0);
2678
- var q = _.parse(symbol.value + '^' + d);
2679
- symbol.each(function (x) {
2680
- x = _.divide(x, q.clone());
2681
- retval = _.add(retval, x);
2682
- });
2683
-
2684
- factors.add(q);
2685
- return retval;
2686
- },
2687
- /**
2688
- * Removes GCD from coefficients
2689
- * @param {Symbol} symbol
2690
- * @param {Factor} factors
2691
- * @returns {Symbol}
2692
- */
2693
- coeffFactor: function (symbol, factors) {
2694
- if(symbol.isComposite()) {
2695
- var gcd = core.Math2.QGCD.apply(null, symbol.coeffs());
2696
-
2697
- if(!gcd.equals(1)) {
2698
- symbol.each(function (x) {
2699
- if(x.isComposite()) {
2700
- x.each(function (y) {
2701
- y.multiplier = y.multiplier.divide(gcd);
2702
- });
2703
- }
2704
- else
2705
- x.multiplier = x.multiplier.divide(gcd);
2706
- });
2707
- symbol.updateHash();
2708
- }
2709
- else {
2710
- // TODO: This should probably go to the prototype
2711
- var power = function (symbol) {
2712
- var p;
2713
- if(symbol.group === CB) {
2714
- p = 0;
2715
- symbol.each(function (x) {
2716
- p += x.power;
2717
- });
2718
- }
2719
- else {
2720
- p = Number(symbol.power);
2721
- }
2722
- return p;
2723
- };
2724
- // Factor out negatives from the lead term
2725
- var terms = symbol.collectSymbols(null, null, null, true).sort(function (a, b) {
2726
- // Push constants to the back
2727
- if(a.isConstant(true))
2728
- return 1;
2729
- return b.power - a.power;
2730
- });
2731
-
2732
- var LT = terms[0];
2733
-
2734
- // Check if the LT is indeed the greatest
2735
- if(power(LT) > power(terms[1]) || terms[1].isConstant(true)) {
2736
- if(LT.multiplier.lessThan(0)) {
2737
- // Although the symbol should always be linear at this point, remove the negative for squares
2738
- // to be safe.
2739
- factors.add(new Symbol(-1));
2740
-
2741
- symbol.each(function (x) {
2742
- x.negate();
2743
- }, true);
2744
- }
2745
- }
2746
-
2747
- }
2748
-
2749
- if(factors) {
2750
- factors.add(new Symbol(gcd));
2751
- }
2752
- }
2753
-
2754
- return symbol;
2755
- },
2756
- /**
2757
- * The name says it all :)
2758
- * @param {Symbol} symbol
2759
- * @param {Factor} factors
2760
- * @@param {String} variable
2761
- * @returns {Symbol}
2762
- */
2763
- trialAndError: function (symbol, factors, variable) {
2764
- var untouched = symbol.clone();
2765
- try {
2766
- // At temp holder for the factors. If all goes well then
2767
- // they'll be moved to the actual factors.
2768
- var factor_array = [];
2769
-
2770
- if(symbol.isConstant() || symbol.group === S)
2771
- return symbol;
2772
- var poly = new Polynomial(symbol, variable),
2773
- cnst = poly.coeffs[0],
2774
- cfactors = core.Math2.ifactor(cnst),
2775
- roots = __.proots(symbol);
2776
- for(var i = 0; i < roots.length; i++) {
2777
- var r = roots[i],
2778
- p = 1;
2779
- if(!isNaN(r)) { //if it's a number
2780
- for(var x in cfactors) {
2781
- //check it's raised to a power
2782
- var n = core.Utils.round(Math.log(x) / Math.log(Math.abs(r)), 8);
2783
- if(isInt(n)) {
2784
- r = x; //x must be the root since n gave us a whole
2785
- p = n;
2786
- break;
2787
- }
2788
- }
2789
- var root = new Frac(r),
2790
- terms = [new Frac(root.num).negate()];
2791
- terms[p] = new Frac(root.den);
2792
- //convert to Frac. The den is coeff of LT and the num is coeff of constant
2793
- var div = Polynomial.fromArray(terms, poly.variable).fill(),
2794
- t = poly.divide(div);
2795
- if(t[1].equalsNumber(0)) { //if it's zero we have a root and divide it out
2796
- poly = t[0];
2797
- // factors.add(div.toSymbol());
2798
- factor_array.push(div.toSymbol());
2799
- }
2800
- }
2801
- }
2802
-
2803
- if(!poly.equalsNumber(1)) {
2804
- poly = __.Factor.search(poly, factors);
2805
- }
2806
-
2807
- // Move the factors over since all went well.
2808
- factor_array.forEach(function (x) {
2809
- factors.add(x);
2810
- });
2811
-
2812
- return poly.toSymbol();
2813
- }
2814
- catch(e) {
2815
- return untouched;
2816
- }
2817
- },
2818
- search: function (poly, factors, base) {
2819
- base = base || 10; //I like 10 because numbers exhibit similar behaviours at 10
2820
- var v = poly.variable; //the polynmial variable name
2821
- /**
2822
- * Attempt to remove a root by division given a number by first creating
2823
- * a polynomial fromt he given information
2824
- * @param {int} c1 - coeffient for the constant
2825
- * @param {int} c2 - coefficient for the LT
2826
- * @param {int} n - the number to be used to construct the polynomial
2827
- * @param {int} p - the power at which to create the polynomial
2828
- * @returns {null|Polynomial} - returns polynomial if successful otherwise null
2829
- */
2830
- var check = function (c1, c2, n, p) {
2831
- var candidate = Polynomial.fit(c1, c2, n, base, p, v);
2832
- if(candidate && candidate.coeffs.length > 1) {
2833
- var t = poly.divide(candidate);
2834
- if(t[1].equalsNumber(0)) {
2835
- factors.add(candidate.toSymbol());
2836
- return [t[0], candidate];
2837
- }
2838
- }
2839
- return null;
2840
- };
2841
- var cnst = poly.coeffs[0];
2842
- var cfactors = core.Math2.ifactor(cnst);
2843
- var lc = poly.lc();
2844
- var ltfactors = core.Math2.ifactor(lc);
2845
- var subbed = poly.sub(base);
2846
- var isubbed = core.Math2.ifactor(subbed);
2847
- var nfactors = __.Factor.mix(isubbed, subbed < 0);
2848
- var cp = Math.ceil(poly.coeffs.length / 2);
2849
- var lc_is_neg = lc.lessThan(0);
2850
- var cnst_is_neg = cnst.lessThan(0);
2851
- ltfactors['1'] = 1;
2852
- cfactors['1'] = 1;
2853
- while(cp--) {
2854
- for(var x in ltfactors) {
2855
- for(var y in cfactors) {
2856
- for(var i = 0; i < nfactors.length; i++) {
2857
- var factor_found = check(x, y, nfactors[i], cp);
2858
- if(factor_found) {
2859
- poly = factor_found[0];
2860
- if(!core.Utils.isPrime(poly.sub(base)))
2861
- poly = __.Factor.search(poly, factors);
2862
- return poly;
2863
- }
2864
- else if(!factor_found) {
2865
- if(lc_is_neg && cnst_is_neg)
2866
- factor_found = check(-x, -y, nfactors[i], cp);
2867
- else if(lc_is_neg)
2868
- factor_found = check(-x, y, nfactors[i], cp); //check a negative lc
2869
- else if(cnst_is_neg)
2870
- factor_found = check(x, -y, nfactors[i], cp); //check a negative constant
2871
- }
2872
- }
2873
- }
2874
- }
2875
- }
2876
- return poly;
2877
- },
2878
- /**
2879
- * Equivalent of square free factor for multivariate polynomials
2880
- * @param {type} symbol
2881
- * @param {type} factors
2882
- * @returns {AlgebraL#18.Factor.mSqfrFactor.symbol|Array|AlgebraL#18.__.Factor.mSqfrFactor.d}
2883
- */
2884
- mSqfrFactor: function (symbol, factors) {
2885
- if(symbol.group !== FN) {
2886
- var vars = variables(symbol).reverse();
2887
-
2888
- // Loop through all the variable and remove the partial derivatives
2889
- for(var i = 0; i < vars.length; i++) {
2890
- do {
2891
- if(vars[i] === symbol.value) {
2892
- //the derivative tells us nothing since this symbol is already the factor
2893
- factors.add(symbol);
2894
- symbol = new Symbol(1);
2895
- continue;
2896
- }
2897
-
2898
- var diff = core.Calculus.diff(symbol, vars[i]);
2899
-
2900
- var d = __.Factor.coeffFactor(diff);
2901
-
2902
- if(d.equals(0))
2903
- break;
2904
-
2905
- //trial division to see if factors have whole numbers.
2906
- //This can be optimized by stopping as soon as can_divide is false
2907
- //this will also need utilize big number at some point
2908
- var can_divide = true;
2909
- if(d.isConstant() && symbol.isComposite()) {
2910
- //check the coefficients
2911
-
2912
- symbol.each(function (x) {
2913
- if(x.multiplier % d !== 0)
2914
- can_divide = false;
2915
- }, true);
2916
- }
2917
-
2918
- //if we can divide then do so
2919
- if(can_divide) {
2920
-
2921
- var div = __.div(symbol, d.clone()),
2922
- is_factor = div[1].equals(0);
2923
-
2924
- // Break infinite loop for factoring e^t*x-1
2925
- if((symbol.equals(div[0]) && div[1].equals(0))) {
2926
- break;
2927
- }
2928
-
2929
- if(div[0].isConstant()) {
2930
- factors.add(div[0]);
2931
- break;
2932
- }
2933
-
2934
- }
2935
- else
2936
- is_factor = false;
2937
-
2938
- if(is_factor) {
2939
- factors.add(div[0]);
2940
- symbol = d;
2941
- }
2942
- }
2943
- while(is_factor)
2944
- }
2945
- }
2946
-
2947
- return symbol;
2948
- },
2949
- //difference of squares factorization
2950
- sqdiff: function (symbol, factors) {
2951
- if(symbol.isConstant('all')) {
2952
- // Nothing to do
2953
- return symbol;
2954
- }
2955
-
2956
- try {
2957
- var remove_square = function (x) {
2958
- return core.Utils.block('POSITIVE_MULTIPLIERS', function () {
2959
- return Symbol.unwrapPARENS(math.sqrt(math.abs(x)));
2960
- }, true);
2961
- };
2962
- var separated = core.Utils.separate(symbol.clone());
2963
-
2964
- var obj_array = [];
2965
-
2966
- //get the unique variables
2967
- for(var x in separated) {
2968
- if(x !== 'constants') {
2969
- obj_array.push(separated[x]);
2970
- }
2971
- }
2972
- obj_array.sort(function (a, b) {
2973
- return b.power - a.power;
2974
- });
2975
-
2976
- //if we have the same number of variables as unique variables then we can apply the difference of squares
2977
- if(obj_array.length === 2) {
2978
- var a, b;
2979
- a = obj_array.pop();
2980
- b = obj_array.pop();
2981
-
2982
- if(even(a.power) && even(b.power)
2983
- && a.sign() === b.sign()
2984
- && a.group === S && b.group === S) {
2985
- throw new Error('Unable to factor');
2986
- }
2987
- ;
2988
-
2989
- if(a.isComposite() && b.power.equals(2)) {
2990
- //remove the square from b
2991
- b = remove_square(b);
2992
- var f = __.Factor.factor(_.add(a, separated.constants));
2993
- if(f.power.equals(2)) {
2994
- f.toLinear();
2995
- factors.add(_.subtract(f.clone(), b.clone()));
2996
- factors.add(_.add(f, b));
2997
- symbol = new Symbol(1);
2998
- }
2999
- }
3000
- else {
3001
- a = a.powSimp();
3002
- b = b.powSimp();
3003
-
3004
- if((a.group === S || a.fname === '') && a.power.equals(2) && (b.group === S || b.fname === '') && b.power.equals(2) && !separated.constants) {
3005
- if(a.multiplier.lessThan(0)) {
3006
- var t = b;
3007
- b = a;
3008
- a = t;
3009
- }
3010
- if(a.multiplier.greaterThan(0)) {
3011
- a = remove_square(a);
3012
- b = remove_square(b);
3013
- }
3014
-
3015
- factors.add(_.subtract(a.clone(), b.clone()));
3016
- factors.add(_.add(a, b));
3017
- symbol = new Symbol(1);
3018
- }
3019
- }
3020
- }
3021
- }
3022
- catch(e) {
3023
- ;
3024
- }
3025
-
3026
- return symbol;
3027
- },
3028
- //factoring for multivariate
3029
- mfactor: function (symbol, factors) {
3030
-
3031
- if(symbol.group === FN) {
3032
- if(symbol.fname === 'sqrt') {
3033
- var factors2 = new Factors(),
3034
- arg = __.Factor.common(symbol.args[0].clone(), factors2);
3035
- arg = __.Factor.coeffFactor(arg, factors2);
3036
- symbol = _.multiply(_.symfunction('sqrt', [arg]), _.parse(symbol.multiplier));
3037
- factors2.each(function (x) {
3038
- symbol = _.multiply(symbol, _.parse(core.Utils.format('sqrt({0})', x)));
3039
- });
3040
- }
3041
- else
3042
- factors.add(symbol);
3043
- }
3044
- else {
3045
-
3046
- //square free factorization
3047
- symbol = __.Factor.mSqfrFactor(symbol, factors);
3048
-
3049
- //try factor out common factors
3050
- //symbol = __.Factor.common(symbol, factors);
3051
-
3052
- var vars = variables(symbol),
3053
- symbols = symbol.collectSymbols().map(function (x) {
3054
- return Symbol.unwrapSQRT(x);
3055
- }),
3056
- sorted = {},
3057
- maxes = {},
3058
- l = vars.length, n = symbols.length;
3059
- //take all the variables in the symbol and organize by variable name
3060
- //e.g. a^2+a^2+b*a -> {a: {a^3, a^2, b*a}, b: {b*a}}
3061
-
3062
- for(var i = 0; i < l; i++) {
3063
- var v = vars[i];
3064
- sorted[v] = new Symbol(0);
3065
- for(var j = 0; j < n; j++) {
3066
- var s = symbols[j];
3067
- if(s.contains(v)) {
3068
- var p = s.value === v ? s.power.toDecimal() : s.symbols[v].power.toDecimal();
3069
- if(!maxes[v] || p < maxes[v])
3070
- maxes[v] = p;
3071
- sorted[v] = _.add(sorted[v], s.clone());
3072
- }
3073
- }
3074
- }
3075
-
3076
- for(var x in sorted) {
3077
- var r = _.parse(x + '^' + maxes[x]);
3078
- var div = _.divide(sorted[x], r);
3079
- var new_factor = _.expand(div);
3080
-
3081
- if(new_factor.equals(1))
3082
- break; //why divide by one. Just move
3083
- var divided = __.div(symbol.clone(), new_factor);
3084
-
3085
- if(divided[0].equals(0)) {
3086
- //cant factor anymore
3087
- break;
3088
- }
3089
-
3090
- // We potentially ended up with fractional coefficients when the
3091
- // trial division was performed. We need to remove
3092
- // This check will more then likely become superfluous with improvements
3093
- // to polynomial division
3094
- if(divided[1].equals(0)) {
3095
- var has_fractions = false;
3096
-
3097
- divided[0].each(function (x) {
3098
- if(!isInt(x.multiplier)) {
3099
- has_fractions = true;
3100
- }
3101
- });
3102
-
3103
- // The factor isn't really a factor and needs to be put back
3104
- if(has_fractions) {
3105
- divided[1] = _.expand(_.multiply(divided[1], new_factor));
3106
- // Since the new factor is not just one, we exit.
3107
- break;
3108
- }
3109
- }
3110
-
3111
- var neg_numeric_factor = isInt(new_factor) && new_factor.lessThan(0);
3112
-
3113
- if(divided[1].equals(0) && !neg_numeric_factor) { //we found at least one factor
3114
-
3115
- //factors.add(new_factor);
3116
- var d = __.div(symbol.clone(), divided[0].clone());
3117
- var r = d[0];
3118
-
3119
- // Nothing left to do since we didn't get a reduction
3120
- if(r.equals(0)) {
3121
- return symbol;
3122
- }
3123
-
3124
- symbol = d[1];
3125
- //we don't want to just flip the sign. If the remainder is -1 then we accomplished nothing
3126
- //and we just return the symbol;
3127
- //If r equals zero then there's nothing left to do so we're done
3128
-
3129
- if(r.equals(-1) && !symbol.equals(0))
3130
- return symbol;
3131
-
3132
- var factor = divided[0];
3133
-
3134
- if(symbol.equals(factor)) {
3135
- var rem = __.Factor.reduce(factor, factors);
3136
-
3137
- if(!symbol.equals(rem))
3138
- return __.Factor.mfactor(rem, factors);
3139
-
3140
- return rem;
3141
- }
3142
- else {
3143
- factors.add(factor);
3144
- //if the remainder of the symbol is zero then we're done. TODO: Rethink this logic a bit.
3145
- if(symbol.equals(0))
3146
- return r;
3147
- }
3148
-
3149
- if(r.isConstant('all')) {
3150
- factors.add(r);
3151
- return r;
3152
- }
3153
-
3154
- return __.Factor.mfactor(r, factors);
3155
- }
3156
- }
3157
-
3158
- }
3159
-
3160
- //difference of squares factorization
3161
- symbol = __.Factor.sqdiff(symbol, factors);
3162
-
3163
- //factors by fishing for zeroes
3164
- symbol = __.Factor.zeroes(symbol, factors);
3165
-
3166
- return symbol;
3167
- }
3168
- },
3169
- /**
3170
- * Checks to see if a set of "equations" is linear.
3171
- * @param {type} set
3172
- * @returns {Boolean}
3173
- */
3174
- allLinear: function (set) {
3175
- var l = set.length;
3176
- for(var i = 0; i < l; i++) {
3177
- if(!__.isLinear(set[i]))
3178
- return false;
3179
- }
3180
- return true;
3181
- },
3182
- /*
3183
- * Checks to see if the "equation" is linear
3184
- * @param {Symbol} e
3185
- * @returns {boolean}
3186
- */
3187
- isLinear: function (e) {
3188
- var status = false, g = e.group;
3189
- if(g === PL || g === CP) {
3190
- status = true;
3191
- for(var s in e.symbols) {
3192
- var symbol = e.symbols[s], sg = symbol.group;
3193
- if(sg === FN || sg === EX) {
3194
- status = false;
3195
- }
3196
- if(sg === CB) {
3197
- //needs further checking since it might be imaginary
3198
- status = variables(symbol).length === 1;
3199
- }
3200
- else {
3201
- if(sg === PL || sg === CP)
3202
- status = __.isLinear(symbol);
3203
- else {
3204
- if(symbol.group !== N && symbol.power.toString() !== '1') {
3205
- status = false;
3206
- break;
3207
- }
3208
- }
3209
- }
3210
- }
3211
- }
3212
- else if(g === S && e.power === 1)
3213
- status = true;
3214
- return status;
3215
- },
3216
- gcd: function () {
3217
- var args;
3218
- if(arguments.length === 1 && arguments[0] instanceof core.Vector)
3219
- args = arguments[0].elements;
3220
- else
3221
- args = core.Utils.arguments2Array(arguments);
3222
-
3223
- //short-circuit early
3224
- if(args.length === 0)
3225
- return new Symbol(1);
3226
- else if(args.length === 1)
3227
- return args[0];
3228
-
3229
- var appeared = [], evaluate = false;
3230
- for(var i = 0; i < args.length; i++) {
3231
- if(args[i].group === FN && args[i].fname === 'gcd')
3232
- {
3233
- //compress gcd(a,gcd(b,c)) into gcd(a,b,c)
3234
- args = args.concat(arguments[i].args);
3235
- //do not keep gcd in args
3236
- args.splice(i, 1);
3237
- }
3238
- else
3239
- {
3240
- //Look if there are any common variables such that
3241
- //gcd(a,b) => gcd(a,b); gcd(a,a) => a
3242
- var vars = variables(args[i]);
3243
- if(core.Utils.haveIntersection(vars, appeared))
3244
- {
3245
- //Ok, there are common variables
3246
- evaluate = true;
3247
- break;
3248
- }
3249
- else
3250
- appeared = appeared.concat(vars);
3251
- }
3252
- }
3253
-
3254
- //appeared.length is 0 when all arguments are group N
3255
- if(evaluate || appeared.length === 0) {
3256
- //TODO: distribute exponent so that (a^-1*b^-1)^-1 => a*b
3257
- if(args.every(function (symbol) {
3258
- return symbol.getDenom().equals(1)
3259
- })) {
3260
- var aggregate = args[0];
3261
-
3262
- for(var i = 1; i < args.length; i++) {
3263
- aggregate = __.gcd_(args[i], aggregate);
3264
- }
3265
- return aggregate;
3266
- }
3267
- else {
3268
- //gcd_ cannot handle denominators correctly
3269
- return _.divide(__.gcd.apply(null, args.map(function (symbol) {
3270
- return symbol.getNum();
3271
- })),
3272
- __.lcm.apply(null, args.map(function (symbol) {
3273
- return symbol.getDenom();
3274
- })));
3275
- }
3276
- }
3277
- else
3278
- return _.symfunction('gcd', args);
3279
- },
3280
- gcd_: function (a, b) {
3281
- if(a.group === FN || a.group === P)
3282
- a = core.Utils.block('PARSE2NUMBER', function () {
3283
- return _.parse(a);
3284
- });
3285
-
3286
- if(b.group === FN)
3287
- b = core.Utils.block('PARSE2NUMBER', function () {
3288
- return _.parse(b);
3289
- });
3290
-
3291
- if(a.isConstant() && b.isConstant()) {
3292
- // return core.Math2.QGCD(new Frac(+a), new Frac(+b));
3293
- return new Symbol(core.Math2.QGCD(new Frac(+a), new Frac(+b)));
3294
- }
3295
-
3296
- var den = _.multiply(a.getDenom() || new Symbol(1), b.getDenom() || new Symbol(1)).invert();
3297
- a = _.multiply(a.clone(), den.clone());
3298
- b = _.multiply(b.clone(), den.clone());
3299
-
3300
- //feels counter intuitive but it works. Issue #123 (nerdamer("gcd(x+y,(x+y)^2)"))
3301
- a = _.expand(a);
3302
- b = _.expand(b);
3303
-
3304
- if(a.group === CB || b.group === CB) {
3305
- var q = _.divide(a.clone(), b.clone()); //get the quotient
3306
- var t = _.multiply(b.clone(), q.getDenom().invert());//multiply by the denominator
3307
- //if they have a common factor then the result will not equal one
3308
- if(!t.equals(1))
3309
- return t;
3310
- }
3311
-
3312
- //just take the gcd of each component when either of them is in group EX
3313
- if(a.group === EX || b.group === EX)
3314
- {
3315
- var gcd_m = new Symbol(core.Math2.GCD(a.multiplier, b.multiplier));
3316
- var gcd_v = __.gcd_(a.value === CONST_HASH ? new Symbol(1) : _.parse(a.value), b.value === CONST_HASH ? new Symbol(1) : _.parse(b.value));
3317
- var gcd_p = __.gcd_(_.parse(a.power), _.parse(b.power));
3318
- return _.multiply(gcd_m, _.pow(gcd_v, gcd_p));
3319
- }
3320
-
3321
- if(a.length < b.length) { //swap'm
3322
- var t = a;
3323
- a = b;
3324
- b = t;
3325
- }
3326
- var vars_a = variables(a), vars_b = variables(b);
3327
- if((vars_a.length === vars_b.length && vars_a.length === 1 && vars_a[0] === vars_b[0])
3328
- || vars_a.length === 1 && vars_b.length === 0
3329
- || vars_a.length === 0 && vars_b.length === 1) {
3330
- a = new Polynomial(a);
3331
- b = new Polynomial(b);
3332
- return _.divide(a.gcd(b).toSymbol(), den);
3333
- }
3334
- else {
3335
- //get the gcd of the multipiers
3336
- //get rid of gcd in coeffs
3337
- var multipliers = [];
3338
- a.each(function (x) {
3339
- multipliers.push(x.multiplier);
3340
- });
3341
- b.each(function (x) {
3342
- multipliers.push(x.multiplier);
3343
- });
3344
-
3345
- var T;
3346
- while(!b.equals(0)) {
3347
- var t = b.clone();
3348
- a = a.clone();
3349
- T = __.div(a, t);
3350
-
3351
- b = T[1];
3352
- if(T[0].equals(0)) {
3353
- //return _.multiply(new Symbol(core.Math2.QGCD(a.multiplier, b.multiplier)), b);
3354
- return _.divide(new Symbol(core.Math2.QGCD(a.multiplier, b.multiplier)), den);
3355
- }
3356
- a = t;
3357
- }
3358
-
3359
- var gcd = core.Math2.QGCD.apply(undefined, multipliers);
3360
-
3361
- if(!gcd.equals(1)) {
3362
- a.each(function (x) {
3363
- x.multiplier = x.multiplier.divide(gcd);
3364
- });
3365
- }
3366
-
3367
- //return symbolic function for gcd in indeterminate form
3368
- if(a.equals(1) && !a.isConstant() && !b.isConstant())
3369
- return _.divide(_.symfunction('gcd', arguments), den);
3370
-
3371
- return _.divide(a, den);
3372
- }
3373
- },
3374
- lcm: function () {
3375
- //https://math.stackexchange.com/a/319310
3376
- //generalization of the 2-variable formula of lcm
3377
-
3378
- var args;
3379
- if(arguments.length === 1)
3380
- if(arguments[0] instanceof core.Vector)
3381
- args = arguments[0].elements;
3382
- else
3383
- _.error('lcm expects either 1 vector or 2 or more arguments');
3384
- else
3385
- args = core.Utils.arguments2Array(arguments);
3386
-
3387
- //product of all arguments
3388
- //start with new Symbol(1) so that prev.clone() which makes unnessesary clones can be avoided
3389
- var numer = args.reduce(function (prev, curr) {
3390
- return _.multiply(prev, curr.clone())
3391
- }, new Symbol(1));
3392
-
3393
- //gcd of complementary terms
3394
- var denom_args =
3395
- //https://stackoverflow.com/a/18223072
3396
- //take all complementary terms, e.g.
3397
- //[a,b,c] => [a*b, b*c, a*c]
3398
- //[a,b,c,d] => [a*b*c, a*b*d, a*c*d, b*c*d]
3399
- (function (input, size) {
3400
- size = Number(size);
3401
- var results = [], result, mask, i, total = Math.pow(2, input.length);
3402
- for(mask = size; mask < total; mask++) {
3403
- result = [];
3404
- i = input.length - 1;
3405
-
3406
- do {
3407
- if((mask & (1 << i)) !== 0) {
3408
- result.push(input[i]);
3409
- }
3410
- }
3411
- while(i--);
3412
-
3413
- if(result.length === size) {
3414
- results.push(result);
3415
- }
3416
- }
3417
- return results;
3418
- //start with new Symbol(1) so that prev.clone() which makes unnessesary clones can be avoided
3419
- })(arguments, arguments.length - 1).map(function (x) {
3420
- return x.reduce(function (prev, curr) {
3421
- return _.multiply(prev, curr.clone())
3422
- }, new Symbol(1))
3423
- });
3424
-
3425
- var denom;
3426
- //don't eat the gcd term if all arguments are symbols
3427
- if(args.every(function (x) {
3428
- return core.Utils.isVariableSymbol(x)
3429
- }))
3430
- denom = _.symfunction('gcd', core.Utils.arrayUnique(denom_args));
3431
- else
3432
- denom = __.gcd.apply(null, denom_args);
3433
- //divide product of all arguments by gcd of complementary terms
3434
- var div = _.divide(numer, denom);
3435
- return div;
3436
- },
3437
- /**
3438
- * Divides one expression by another
3439
- * @param {Symbol} symbol1
3440
- * @param {Symbol} symbol2
3441
- * @returns {Array}
3442
- */
3443
- divide: function (symbol1, symbol2) {
3444
- var result, remainder, factored, den;
3445
- factored = core.Algebra.Factor.factor(symbol1.clone());
3446
- den = factored.getDenom();
3447
- if(!den.isConstant('all')) {
3448
- symbol1 = _.expand(Symbol.unwrapPARENS(_.multiply(factored, den.clone())));
3449
- }
3450
- else
3451
- //reset the denominator since we're not dividing by it anymore
3452
- den = new Symbol(1);
3453
- result = __.div(symbol1, symbol2);
3454
- remainder = _.divide(result[1], symbol2);
3455
- return _.divide(_.add(result[0], remainder), den);
3456
- },
3457
- div: function (symbol1, symbol2) {
3458
- // If all else fails then assume that division failed with
3459
- // a remainder of zero and the original quotient
3460
- var fail = [new Symbol(0), symbol1.clone()];
3461
-
3462
- try {
3463
-
3464
- // Division by constants
3465
- if(symbol2.isConstant('all')) {
3466
- symbol1.each(function (x) {
3467
- x.multiplier = x.multiplier.divide(symbol2.multiplier);
3468
- });
3469
- return [symbol1, new Symbol(0)];
3470
- }
3471
- // So that factorized symbols don't affect the result
3472
- symbol1 = _.expand(symbol1);
3473
- symbol2 = _.expand(symbol2);
3474
- // Special case. May need revisiting
3475
- if(symbol1.group === S && symbol2.group === CP) {
3476
- var x = symbol1.value;
3477
- var f = core.Utils.decompose_fn(symbol2.clone(), x, true);
3478
- if(symbol1.isLinear() && f.x && f.x.isLinear() && symbol2.isLinear()) {
3479
- var k = Symbol.create(symbol1.multiplier);
3480
- return [_.divide(k.clone(), f.a.clone()), _.divide(_.multiply(k, f.b), f.a).negate()];
3481
- }
3482
- }
3483
- if(symbol1.group === S && symbol2.group === S) {
3484
- var r = _.divide(symbol1.clone(), symbol2.clone());
3485
- if(r.isConstant()) //we have a whole
3486
- return [r, new Symbol(0)];
3487
- return [new Symbol(0), symbol1.clone()];
3488
- }
3489
- var symbol1_has_func = symbol1.hasFunc(),
3490
- symbol2_has_func = symbol2.hasFunc(),
3491
- parse_funcs = false;
3492
-
3493
- //substitute out functions so we can treat them as regular variables
3494
- if(symbol1_has_func || symbol2_has_func) {
3495
- parse_funcs = true;
3496
- var map = {},
3497
- symbol1 = _.parse(core.Utils.subFunctions(symbol1, map)),
3498
- symbol2 = _.parse(core.Utils.subFunctions(symbol2, map)),
3499
- subs = core.Utils.getFunctionsSubs(map);
3500
- }
3501
- //get a list of the variables
3502
- var vars = core.Utils.arrayUnique(variables(symbol1).concat(variables(symbol2))),
3503
- quot, rem;
3504
-
3505
- //treat imaginary numbers as variables
3506
- if(symbol1.isImaginary() || symbol2.isImaginary()) {
3507
- vars.push(core.Settings.IMAGINARY);
3508
- }
3509
-
3510
- if(vars.length === 1) {
3511
- var q = new Polynomial(symbol1).divide(new Polynomial(symbol2));
3512
- quot = q[0].toSymbol();
3513
- rem = q[1].toSymbol();
3514
- }
3515
- else {
3516
- vars.push(CONST_HASH); //this is for the numbers
3517
- var reconvert = function (arr) {
3518
- var symbol = new Symbol(0);
3519
- for(var i = 0; i < arr.length; i++) {
3520
- var x = arr[i].toSymbol();
3521
- symbol = _.add(symbol, x);
3522
- }
3523
- return symbol;
3524
- };
3525
-
3526
- // Silly Martin. This is why you document. I don't remember now
3527
- var get_unique_max = function (term, any) {
3528
- var max = Math.max.apply(null, term.terms),
3529
- count = 0, idx;
3530
-
3531
- if(!any) {
3532
- for(var i = 0; i < term.terms.length; i++) {
3533
- if(term.terms[i].equals(max)) {
3534
- idx = i;
3535
- count++;
3536
- }
3537
- if(count > 1)
3538
- return;
3539
- }
3540
- }
3541
- if(any) {
3542
- for(i = 0; i < term.terms.length; i++)
3543
- if(term.terms[i].equals(max)) {
3544
- idx = i;
3545
- break;
3546
- }
3547
- }
3548
- return [max, idx, term];
3549
- };
3550
-
3551
- // Tries to find an LT in the dividend that will satisfy division
3552
- var get_det = function (s, lookat) {
3553
- lookat = lookat || 0;
3554
- var det = s[lookat], l = s.length;
3555
- if(!det)
3556
- return;
3557
- //eliminate the first term if it doesn't apply
3558
- var umax = get_unique_max(det);
3559
- for(var i = lookat + 1; i < l; i++) {
3560
- var term = s[i],
3561
- is_equal = det.sum.equals(term.sum);
3562
- if(!is_equal && umax) {
3563
- break;
3564
- }
3565
- if(is_equal) {
3566
- // Check the differences of their maxes. The one with the biggest difference governs
3567
- // e.g. x^2*y^3 vs x^2*y^3 is unclear but this isn't the case in x*y and x^2
3568
- var max1, max2, idx1, idx2, l2 = det.terms.length;
3569
- for(var j = 0; j < l2; j++) {
3570
- var item1 = det.terms[j], item2 = term.terms[j];
3571
- if(typeof max1 === 'undefined' || item1.greaterThan(max1)) {
3572
- max1 = item1;
3573
- idx1 = j;
3574
- }
3575
- if(typeof max2 === 'undefined' || item2.greaterThan(max2)) {
3576
- max2 = item2;
3577
- idx2 = j;
3578
- }
3579
- }
3580
- //check their differences
3581
- var d1 = max1.subtract(term.terms[idx1]),
3582
- d2 = max2.subtract(det.terms[idx2]);
3583
- if(d2 > d1) {
3584
- umax = [max2, idx2, term];
3585
- break;
3586
- }
3587
- if(d1 > d2) {
3588
- umax = [max1, idx1, det];
3589
- break;
3590
- }
3591
- }
3592
- else {
3593
- //check if it's a suitable pick to determine the order
3594
- umax = get_unique_max(term);
3595
- //if(umax) return umax;
3596
- if(umax)
3597
- break;
3598
- }
3599
- umax = get_unique_max(term); //calculate a new unique max
3600
- }
3601
-
3602
- //if still no umax then any will do since we have a tie
3603
- if(!umax)
3604
- return get_unique_max(s[0], true);
3605
- var e, idx;
3606
- for(var i = 0; i < s2.length; i++) {
3607
- var cterm = s2[i].terms;
3608
- //confirm that this is a good match for the denominator
3609
- idx = umax[1];
3610
- if(idx === cterm.length - 1)
3611
- return;
3612
- e = cterm[idx];
3613
- if(!e.equals(0))
3614
- break;
3615
- }
3616
- if(e.equals(0))
3617
- return get_det(s, ++lookat); //look at the next term
3618
-
3619
- return umax;
3620
- };
3621
-
3622
- var t_map = core.Utils.toMapObj(vars);
3623
- var init_sort = function (a, b) {
3624
- return b.sum.subtract(a.sum);
3625
- };
3626
- var is_larger = function (a, b) {
3627
- if(!a || !b)
3628
- return false; //it's empty so...
3629
- for(var i = 0; i < a.terms.length; i++) {
3630
- if(a.terms[i].lessThan(b.terms[i]))
3631
- return false;
3632
- }
3633
- return true;
3634
- };
3635
-
3636
- var s1 = symbol1.tBase(t_map).sort(init_sort),
3637
- s2 = symbol2.tBase(t_map).sort(init_sort);
3638
- var target = is_larger(s1[0], s2[0]) && s1[0].count > s2[0].count ? s2 : s1; //since the num is already larger than we can get the det from denom
3639
- var det = get_det(target);//we'll begin by assuming that this will let us know which term
3640
- var quotient = [];
3641
- if(det) {
3642
- var lead_var = det[1];
3643
- var can_divide = function (a, b) {
3644
- if(a[0].sum.equals(b[0].sum))
3645
- return a.length >= b.length;
3646
- return true;
3647
- };
3648
-
3649
- var try_better_lead_var = function (s1, s2, lead_var) {
3650
- var checked = [];
3651
- for(var i = 0; i < s1.length; i++) {
3652
- var t = s1[i];
3653
- for(var j = 0; j < t.terms.length; j++) {
3654
- var cf = checked[j], tt = t.terms[j];
3655
- if(i === 0)
3656
- checked[j] = tt; //add the terms for the first one
3657
- else if(cf && !cf.equals(tt))
3658
- checked[j] = undefined;
3659
- }
3660
- }
3661
- for(var i = 0; i < checked.length; i++) {
3662
- var t = checked[i];
3663
- if(t && !t.equals(0))
3664
- return i;
3665
- }
3666
- return lead_var;
3667
- };
3668
- var sf = function (a, b) {
3669
- var l1 = a.len(), l2 = b.len();
3670
- var blv = b.terms[lead_var], alv = a.terms[lead_var];
3671
- if(l2 > l1 && blv.greaterThan(alv))
3672
- return l2 - l1;
3673
- return blv.subtract(alv);
3674
- };
3675
-
3676
- //check to see if there's a better lead_var
3677
- lead_var = try_better_lead_var(s1, s2, lead_var);
3678
- //reorder both according to the max power
3679
- s1.sort(sf); //sort them both according to the leading variable power
3680
- s2.sort(sf);
3681
-
3682
- //try to adjust if den is larger
3683
- var fdt = s2[0], fnt = s1[0];
3684
-
3685
- var den = new MVTerm(new Frac(1), [], fnt.map);
3686
- if(fdt.sum.greaterThan(fnt.sum) && fnt.len() > 1) {
3687
- for(var i = 0; i < fnt.terms.length; i++) {
3688
- var d = fdt.terms[i].subtract(fnt.terms[i]);
3689
- if(!d.equals(0)) {
3690
- var nd = d.add(new Frac(1));
3691
- den.terms[i] = d;
3692
- for(var j = 0; j < s1.length; j++) {
3693
- s1[j].terms[i] = s1[j].terms[i].add(nd);
3694
- }
3695
- }
3696
- else
3697
- den.terms[i] = new Frac(0);
3698
- }
3699
- }
3700
-
3701
- var dividend_larger = is_larger(s1[0], s2[0]);
3702
-
3703
- var safety = 0;
3704
- var max = 200;
3705
-
3706
- while(dividend_larger && can_divide(s1, s2)) {
3707
- if(safety++ > max) {
3708
- throw new core.exceptions.InfiniteLoopError('Unable to compute!');
3709
- }
3710
-
3711
- var q = s1[0].divide(s2[0]);
3712
-
3713
- quotient.push(q); //add what's divided to the quotient
3714
- s1.shift();//the first one is guaranteed to be gone so remove from dividend
3715
- for(var i = 1; i < s2.length; i++) { //loop through the denominator
3716
- var t = s2[i].multiply(q).generateImage(),
3717
- l2 = s1.length;
3718
- //if we're subtracting from 0
3719
- if(l2 === 0) {
3720
- t.coeff = t.coeff.neg();
3721
- s1.push(t);
3722
- s1.sort(sf);
3723
- }
3724
-
3725
- for(var j = 0; j < l2; j++) {
3726
- var cur = s1[j];
3727
- if(cur.getImg() === t.getImg()) {
3728
- cur.coeff = cur.coeff.subtract(t.coeff);
3729
- if(cur.coeff.equals(0)) {
3730
- core.Utils.remove(s1, j);
3731
- j--; //adjust the iterator
3732
- }
3733
- break;
3734
- }
3735
- if(j === l2 - 1) {
3736
- t.coeff = t.coeff.neg();
3737
- s1.push(t);
3738
- s1.sort(sf);
3739
- }
3740
- }
3741
- }
3742
- dividend_larger = is_larger(s1[0], s2[0]);
3743
-
3744
- if(!dividend_larger && s1.length >= s2.length) {
3745
- //One more try since there might be a terms that is larger than the LT of the divisor
3746
- for(var i = 1; i < s1.length; i++) {
3747
- dividend_larger = is_larger(s1[i], s2[0]);
3748
- if(dividend_larger) {
3749
- //take it from its current position and move it to the front
3750
- s1.unshift(core.Utils.remove(s1, i));
3751
- break;
3752
- }
3753
- }
3754
- }
3755
- }
3756
- }
3757
-
3758
- quot = reconvert(quotient);
3759
- rem = reconvert(s1);
3760
-
3761
- if(typeof den !== 'undefined') {
3762
- den = den.toSymbol();
3763
- quot = _.divide(quot, den.clone());
3764
- rem = _.divide(rem, den);
3765
- }
3766
- }
3767
-
3768
- //put back the functions
3769
- if(parse_funcs) {
3770
- quot = _.parse(quot.text(), subs);
3771
- rem = _.parse(rem.text(), subs);
3772
- }
3773
-
3774
- return [quot, rem];
3775
- }
3776
- catch(e) {
3777
- return fail;
3778
- }
3779
-
3780
- },
3781
- line: function (v1, v2, x) {
3782
- if(core.Utils.isArray(v1))
3783
- v1 = core.Utils.convertToVector(v1);
3784
- if(core.Utils.isArray(v2))
3785
- v2 = core.Utils.convertToVector(v2);
3786
- x = _.parse(x || 'x');
3787
- if(!core.Utils.isVector(v1) || !core.Utils.isVector(v2))
3788
- _.error('Line expects a vector! Received "' + v1 + '" & "' + v2 + '"');
3789
- var dx = _.subtract(v2.e(1).clone(), v1.e(1).clone()),
3790
- dy = _.subtract(v2.e(2).clone(), v1.e(2).clone()),
3791
- m = _.divide(dy, dx),
3792
- a = _.multiply(x, m.clone()),
3793
- b = _.multiply(v1.e(1).clone(), m);
3794
- return _.add(_.subtract(a, b), v1.e(2).clone());
3795
- },
3796
- PartFrac: {
3797
- createTemplate: function (den, denom_factors, f_array, v) {
3798
- //clean up the denominator function by factors so it reduces nicely
3799
- den = __.Factor.factor(den);
3800
-
3801
- //clean up factors. This is so inefficient but factors are wrapped in parens for safety
3802
- den.each(function (x, key) {
3803
- if(x.group === FN && x.fname === '' && x.args[0].group === S) {
3804
- var y = x.args[0];
3805
- if(this.symbols) {
3806
- delete this.symbols[key];
3807
- this.symbols[y.value] = y;
3808
- }
3809
- else {
3810
- den = x.args[0];
3811
- }
3812
- }
3813
- });
3814
-
3815
- var factors, factors_vec, f, p, deg, degrees, m;
3816
- factors = denom_factors.collectFactors();
3817
- factors_vec = []; //a vector for the template
3818
- degrees = [];
3819
- m = new Symbol(1);
3820
-
3821
- for(var i = 0; i < factors.length; i++) { //loop through the factors
3822
- var factor = Symbol.unwrapPARENS(factors[i]);
3823
- //if in he for P^n where P is polynomial and n = integer
3824
- if(factor.power.greaterThan(1)) {
3825
- p = Number(factor.power);
3826
- f = factor.clone().toLinear(); //remove the power so we have only the function
3827
- deg = Number(__.degree(f, v)); //get the degree of f
3828
- //expand the factor
3829
- for(var j = 0; j < p; j++) {
3830
- var efactor = _.pow(f.clone(), new Symbol(j + 1));
3831
- f_array.push(efactor.clone());
3832
- var d = _.divide(den.clone(), efactor.clone());
3833
- degrees.push(deg);
3834
- factors_vec.push(d);
3835
- }
3836
- }
3837
- /*
3838
- Possible bug.
3839
- Removed: causes 1/(20+24*x+4*x^2) to result in (-1/64)*(5+x)^(-1)+(1/64)*(1+x)^(-1)
3840
- else if(factor.isConstant('all')) {
3841
- m = _.multiply(m, factor);
3842
- }
3843
- */
3844
- else {
3845
- //get the degree of the factor so we tack it on tot he factor. This should probably be an array
3846
- //but for now we note it on the symbol
3847
- deg = Number(__.degree(factor, v));
3848
- f_array.push(factor);
3849
- var d = _.divide(den.clone(), factor.clone());
3850
- d = _.expand(Symbol.unwrapPARENS(d));
3851
- degrees.push(deg);
3852
- factors_vec.push(d);
3853
- }
3854
- }
3855
- //put back the constant
3856
- f_array = f_array.map(function (x) {
3857
- return _.multiply(x, m.clone());
3858
- });
3859
- return [f_array, factors_vec, degrees];
3860
- },
3861
- partfrac: function (symbol, v, as_array) {
3862
-
3863
- var vars = variables(symbol);
3864
-
3865
- v = v || _.parse(vars[0]); //make wrt optional and assume first variable
3866
- try {
3867
- var num, den, factors, tfactors, ofactors, nterms, degrees,
3868
- dterms, max, M, c, powers, div, r, factors_vec, ks,
3869
- template, tfactors;
3870
- num = _.expand(symbol.getNum());
3871
- den = _.expand(symbol.getDenom().toUnitMultiplier());
3872
- //move the entire multipier to the numerator
3873
- num.multiplier = symbol.multiplier;
3874
- //we only have a meaningful change if n factors > 1. This means that
3875
- //the returned group will be a CB
3876
- //collect the terms wrt the x
3877
- nterms = num.groupTerms(v);
3878
- //divide out wholes if top is larger
3879
- if(Number(__.degree(num, v)) >= Number(__.degree(den, v))) {
3880
- div = __.div(num.clone(), _.expand(den.clone()));
3881
- r = div[0]; //remove the wholes
3882
- num = div[1]; //work with the remainder
3883
- nterms = num.groupTerms(v); //recalculate the nterms
3884
- }
3885
- else
3886
- r = new Symbol(0);
3887
-
3888
- if(Number(__.degree(den, v)) === 1) {
3889
- var q = _.divide(num, den);
3890
- if(as_array)
3891
- return [r, q];
3892
- return _.add(r, q);
3893
- }
3894
- //first factor the denominator. This means that the strength of this
3895
- //algorithm depends on how well we can factor the denominator.
3896
- ofactors = __.Factor.factor(den);
3897
- //create the template. This method will create the template for solving
3898
- //the partial fractions. So given x/(x-1)^2 the template creates A/(x-1)+B/(x-1)^2
3899
- template = __.PartFrac.createTemplate(den.clone(), ofactors, [], v);
3900
- tfactors = template[0]; //grab the factors
3901
- factors_vec = template[1]; //grab the factor vectors
3902
- degrees = template[2]; //grab the degrees
3903
- //make note of the powers of each term
3904
- powers = [nterms.length];
3905
- //create the dterms vector
3906
- dterms = [];
3907
- factors = [];
3908
- ks = [];
3909
- var factor, deg;
3910
- factors_vec.map(function (x, idx) {
3911
- factor = tfactors[idx];
3912
- deg = degrees[idx];
3913
- for(var i = 0; i < deg; i++) {
3914
- factors.push(factor.clone());
3915
- var k = Symbol.create(v, i);
3916
- var t = _.expand(_.multiply(x, k.clone())).groupTerms(v);
3917
- //make a note of the power which corresponds to the length of the array
3918
- var p = t.length;
3919
- powers.push(p);
3920
- dterms.push(t);
3921
- ks.push(k.clone());
3922
- }
3923
- });
3924
- //get the max power
3925
- max = core.Utils.arrayMax(powers);
3926
-
3927
- //fill the holes and create a matrix
3928
- c = new core.Matrix(core.Utils.fillHoles(nterms, max)).transpose();
3929
- //for each of the factors we do the same
3930
- M = new core.Matrix();
3931
- for(var i = 0; i < dterms.length; i++) {
3932
- M.elements.push(core.Utils.fillHoles(dterms[i], max));
3933
- }
3934
-
3935
- //solve the system of equations
3936
- var partials = _.multiply(M.transpose().invert(), c);
3937
- //the results are backwards to reverse it
3938
- //partials.elements.reverse();
3939
- //convert it all back
3940
- var retval = as_array ? [r] : r;
3941
- partials.each(function (e, i) {
3942
- var term = _.multiply(ks[i], _.divide(e, factors[i]));
3943
- if(as_array)
3944
- retval.push(term);
3945
- else
3946
- retval = _.add(retval, term);
3947
- });
3948
-
3949
- //done
3950
- return retval;
3951
- }
3952
- catch(e) {
3953
- //try to group symbols
3954
- try {
3955
- if(symbol.isComposite()) {
3956
- //group denominators
3957
- var denominators = {};
3958
-
3959
- symbol.each(function (x) {
3960
- var d = x.getDenom();
3961
- var n = x.getNum();
3962
- var e = denominators[d];
3963
- denominators[d] = e ? _.add(e, n) : n;
3964
- });
3965
-
3966
- var t = new Symbol(0);
3967
-
3968
- for(var x in denominators) {
3969
- t = _.add(t, _.divide(denominators[x], _.parse(x)));
3970
- }
3971
-
3972
- symbol = t;
3973
- }
3974
- }
3975
- catch(e2) {
3976
- }
3977
- ;
3978
- }
3979
- ;
3980
-
3981
- return symbol;
3982
- }
3983
- },
3984
- degree: function (symbol, v, o) {
3985
- o = o || {
3986
- nd: [], //numeric
3987
- sd: [], //symbolic
3988
- depth: 0 //call depth
3989
- };
3990
-
3991
- if(!v) {
3992
- var vars = variables(symbol);
3993
- //The user must specify the variable for multivariate
3994
- if(vars.length > 1)
3995
- throw new Error('You must specify the variable for multivariate polynomials!');
3996
- //if it's empty then we're dealing with a constant
3997
- if(vars.length === 0)
3998
- return new Symbol(0);
3999
- //assume the variable for univariate
4000
- v = _.parse(vars[0]);
4001
- }
4002
-
4003
- //store the group
4004
- var g = symbol.group;
4005
- //we're going to trust the user and assume no EX. Calling isPoly
4006
- //would eliminate this but no sense in checking twice.
4007
- if(symbol.isComposite()) {
4008
- symbol = symbol.clone();
4009
- symbol.distributeExponent();
4010
- symbol.each(function (x) {
4011
- o.depth++; //mark a depth increase
4012
- __.degree(x, v, o);
4013
- o.depth--; //we're back
4014
- });
4015
- }
4016
- else if(symbol.group === CB) {
4017
- symbol.each(function (x) {
4018
- o.depth++;
4019
- __.degree(x, v, o);
4020
- o.depth++;
4021
- });
4022
- }
4023
- else if(g === EX && symbol.value === v.value) {
4024
- o.sd.push(symbol.power.clone());
4025
- }
4026
- else if(g === S && symbol.value === v.value) {
4027
- o.nd.push(_.parse(symbol.power));
4028
- }
4029
- else
4030
- o.nd.push(new Symbol(0));
4031
-
4032
- //get the max out of the array
4033
- var deg = o.nd.length > 0 ? core.Utils.arrayMax(o.nd) : undefined;
4034
-
4035
- if(o.depth === 0 && o.sd.length > 0) {
4036
- if(deg !== undefined)
4037
- o.sd.unshift(deg);
4038
- return _.symfunction('max', o.sd);
4039
- }
4040
- if(!core.Utils.isSymbol(deg))
4041
- deg = _.parse(deg);
4042
- //return the degree
4043
- return deg;
4044
- },
4045
- /**
4046
- * Attempts to complete the square of a polynomial
4047
- * @param {type} symbol
4048
- * @param {type} v
4049
- * @param {type} raw
4050
- * @throws {Error}
4051
- * @returns {Object|Symbol[]}
4052
- */
4053
- sqComplete: function (symbol, v, raw) {
4054
- if(!core.Utils.isSymbol(v))
4055
- v = _.parse(v);
4056
- var stop = function (msg) {
4057
- msg = msg || 'Stopping';
4058
- throw new core.exceptions.ValueLimitExceededError(msg);
4059
- };
4060
- //if not CP then nothing to do
4061
- if(!symbol.isPoly(true))
4062
- stop('Must be a polynomial!');
4063
-
4064
- //declare vars
4065
- var deg, a, b, c, d, e, coeffs, sign, br, sym, sqrt_a;
4066
-
4067
- br = core.Utils.inBrackets;
4068
- //make a copy
4069
- symbol = symbol.clone();
4070
- deg = core.Algebra.degree(symbol, v); //get the degree of polynomial
4071
- //must be in form ax^2 +/- bx +/- c
4072
- if(!deg.equals(2))
4073
- stop('Cannot complete square for degree ' + deg);
4074
- //get the coeffs
4075
- coeffs = core.Algebra.coeffs(symbol, v);
4076
- a = coeffs[2];
4077
- //store the sign
4078
- sign = coeffs[1].sign();
4079
- //divide the linear term by two and square it
4080
- b = _.divide(coeffs[1], new Symbol(2));
4081
- //add the difference to the constant
4082
- c = _.pow(b.clone(), new Symbol(2));
4083
- if(raw)
4084
- return [a, b, d];
4085
- sqrt_a = math.sqrt(a);
4086
- e = _.divide(math.sqrt(c), sqrt_a.clone());
4087
- //calculate d which is the constant
4088
- d = _.subtract(coeffs[0], _.pow(e.clone(), new Symbol(2)));
4089
- //compute the square part
4090
- sym = _.parse(br(sqrt_a.clone() + '*' + v + (sign < 0 ? '-' : '+') + e));
4091
- return {
4092
- a: sym,
4093
- c: d,
4094
- f: _.add(_.pow(sym.clone(), new Symbol(2)), d.clone())
4095
- };
4096
- },
4097
- Simplify: {
4098
- strip: function (symbol) {
4099
- var c = _.parse(symbol.multiplier);
4100
- symbol.toUnitMultiplier();
4101
- var p = _.parse(symbol.power);
4102
- symbol.toLinear();
4103
- return [c, p, symbol];
4104
- },
4105
- unstrip: function (cp, symbol) {
4106
- var c = cp[0];
4107
- var p = cp[1];
4108
- return _.multiply(c, _.pow(symbol, p));
4109
- },
4110
- complexSimp: function (num, den) {
4111
- var ac, bd, bc, ad, cd, r1, r2, i1, i2;
4112
- r1 = num.realpart();
4113
- i1 = num.imagpart();
4114
- r2 = den.realpart();
4115
- i2 = den.imagpart();
4116
- //apply complex arithmatic rule
4117
- ac = _.multiply(r1.clone(), r2.clone());
4118
- bd = _.multiply(i1.clone(), i2.clone());
4119
- bc = _.multiply(r2.clone(), i1);
4120
- ad = _.multiply(r1, i2.clone());
4121
- cd = _.add(_.pow(r2, new Symbol(2)), _.pow(i2, new Symbol(2)));
4122
-
4123
- return _.divide(_.add(_.add(ac, bd), _.multiply(_.subtract(bc, ad), Symbol.imaginary())), cd);
4124
- },
4125
- trigSimp: function (symbol) {
4126
- if(symbol.containsFunction(['cos', 'sin', 'tan'])) {
4127
- symbol = symbol.clone();
4128
- //remove power and multiplier
4129
- var sym_array = __.Simplify.strip(symbol);
4130
- symbol = sym_array.pop();
4131
- //the default return value is the symbol
4132
- var retval = symbol.clone();
4133
-
4134
- //rewrite the symbol
4135
- if(symbol.group === CP) {
4136
- var sym = new Symbol(0);
4137
- symbol.each(function (x) {
4138
- //rewrite the function
4139
- var tr = __.Simplify.trigSimp(x.fnTransform());
4140
- sym = _.add(sym, tr);
4141
- }, true);
4142
-
4143
- //put back the power and multiplier and return
4144
- retval = _.pow(_.multiply(new Symbol(symbol.multiplier), sym), new Symbol(symbol.power));
4145
- }
4146
- else if(symbol.group === CB) {
4147
-
4148
- var n = symbol.getNum();
4149
- var d = symbol.getDenom();
4150
-
4151
- //try for tangent
4152
- if(n.fname === 'sin' && d.fname === 'cos' && n.args[0].equals(d.args[0]) && n.power.equals(d.power)) {
4153
- retval = _.parse(core.Utils.format('({0})*({1})*tan({2})^({3})', d.multiplier, n.multiplier, n.args[0], n.power));
4154
- }
4155
- if(retval.group === CB) {
4156
- var t = new Symbol(1);
4157
- retval.each(function (x) {
4158
- if(x.fname === 'tan') {
4159
- x = _.parse(core.Utils.format('({0})*sin({1})^({2})/cos({1})^({2})', x.multiplier, __.Simplify.simplify(x.args[0]), x.power));
4160
- }
4161
- t = _.multiply(t, x);
4162
- });
4163
- retval = t;
4164
- }
4165
- }
4166
-
4167
-
4168
- retval = __.Simplify.unstrip(sym_array, retval).distributeMultiplier();
4169
-
4170
- symbol = retval;
4171
- }
4172
-
4173
- return symbol;
4174
- },
4175
- fracSimp: function (symbol) {
4176
- //try a quick simplify of imaginary numbers
4177
- var den = symbol.getDenom();
4178
- var num = symbol.getNum();
4179
-
4180
- if(num.isImaginary() && den.isImaginary())
4181
- symbol = __.Simplify.complexSimp(num, den);
4182
-
4183
- if(symbol.isComposite()) {
4184
- if(symbol.power > 1) {
4185
- symbol = _.expand(symbol);
4186
- }
4187
-
4188
- var symbols = symbol.collectSymbols();
4189
- //assumption 1.
4190
- //since it's a composite, it has a length of at least 1
4191
- var retval, a, b, d1, d2, n1, n2, s, x, y, c, den, num;
4192
- a = symbols.pop(); //grab the first symbol
4193
- //loop through each term and make denominator common
4194
- while(symbols.length) {
4195
- b = symbols.pop(); //grab the second symbol
4196
- d1 = _.parse(a.getDenom());
4197
- d2 = _.parse(b.getDenom());
4198
- n1 = a.getNum();
4199
- n2 = b.getNum();
4200
- c = _.multiply(d1.clone(), d2.clone());
4201
- x = _.multiply(n1, d2);
4202
- y = _.multiply(n2, d1);
4203
- s = _.add(x, y);
4204
- a = _.divide(s, c);
4205
- }
4206
- den = _.expand(a.getDenom());
4207
- num = _.expand(a.getNum());
4208
- //simplify imaginary
4209
- if(num.isImaginary() && den.isImaginary()) {
4210
- retval = __.Simplify.complexSimp(num, den);
4211
- }
4212
- else {
4213
- retval = _.divide(num, den);
4214
- }
4215
-
4216
- //we've already hit the simplest form so return that
4217
- if(retval.equals(symbol)) {
4218
- return symbol;
4219
- }
4220
-
4221
- //otherwise simplify it some more
4222
- return __.Simplify.simplify(retval);
4223
- }
4224
- return symbol;
4225
- },
4226
- ratSimp: function (symbol) {
4227
- if(symbol.group === CB) {
4228
- var den = symbol.getDenom();
4229
- var num = symbol.getNum().distributeMultiplier();
4230
- var d = __.Simplify.fracSimp(den);
4231
- var n = __.Simplify.fracSimp(num);
4232
- symbol = _.divide(n, d);
4233
- }
4234
- return symbol;
4235
- },
4236
- sqrtSimp: function (symbol, sym_array) {
4237
- var retval;
4238
- if(symbol.isSQRT()) {
4239
- var factored = __.Factor.factor(symbol.args[0].clone());
4240
- var m = _.parse(factored.multiplier);
4241
- var sign = m.sign();
4242
-
4243
- var retval = _.sqrt(m.abs());
4244
- var arg;
4245
-
4246
- if(isInt(retval)) {
4247
-
4248
- if(factored.group === CB) {
4249
- var rem = new Symbol(1);
4250
-
4251
- factored.each(function (x) {
4252
- if(x.group === N) {
4253
- var trial = _.sqrt(x.clone());
4254
-
4255
- // Multiply back sqrt if it's an integer otherwise just put back the number
4256
- if(isInt(trial)) {
4257
- retval = _.multiply(retval, trial);
4258
- }
4259
- else {
4260
- rem = _.multiply(rem, x);
4261
- }
4262
- }
4263
- else {
4264
- rem = _.multiply(rem, x);
4265
- }
4266
-
4267
- });
4268
- var t = _.multiply(rem, _.parse(sign));
4269
- arg = _.sqrt(t.clone());
4270
-
4271
- // Expand if it's imaginary
4272
- if(arg.isImaginary) {
4273
- arg = _.sqrt(_.expand(t.clone()));
4274
- }
4275
- }
4276
- else {
4277
- // Strip the multiplier
4278
- arg = _.sqrt(factored.clone().toUnitMultiplier());
4279
- }
4280
- return _.multiply(retval, arg);
4281
-
4282
- }
4283
-
4284
- }
4285
- else if(symbol.isComposite() && symbol.isLinear()) {
4286
- retval = new Symbol(0);
4287
- symbol.each(function (x) {
4288
- retval = _.add(retval, __.Simplify.sqrtSimp(x));
4289
- }, true);
4290
- // Put back the multiplier
4291
- retval = _.multiply(retval, _.parse(symbol.multiplier));
4292
- }
4293
- else if(symbol.group === CB) {
4294
- retval = _.parse(symbol.multiplier);
4295
- symbol.each(function (x) {
4296
- var simp = __.Simplify.sqrtSimp(x);
4297
- retval = _.multiply(retval, simp);
4298
-
4299
- }, true);
4300
- // Put back the power
4301
- retval = _.pow(retval, _.parse(symbol.power));
4302
- }
4303
-
4304
- return retval ? retval : _.parse(symbol);
4305
- },
4306
- /**
4307
- * Unused. The goal is to substitute out patterns but it currently doesn't work.
4308
- * @param {Symbol} symbol
4309
- * @return {Array} The symbol and the matched patterns
4310
- */
4311
- patternSub: function (symbol) {
4312
- var patterns = {};
4313
-
4314
- var has_CP = function (symbol) {
4315
- var found = false;
4316
- symbol.each(function (x) {
4317
- if(x.group === CP) {
4318
- found = true;
4319
- }
4320
- else if(x.symbols) {
4321
- found = has_CP(x);
4322
- }
4323
- });
4324
-
4325
- return found;
4326
- };
4327
-
4328
- var collect = function (sym) {
4329
- // We loop through each symbol looking for anything in the simplest
4330
- // form of ax+byz+...
4331
- sym.each(function (x) {
4332
- // Items of group N,P,S, need to apply
4333
- if(!x.symbols && x.group !== FN) {
4334
- return;
4335
- }
4336
-
4337
- // Check to see if it has any symbols of group CP
4338
- // Get the patterns in that symbol instead if it has anything of group CP
4339
- if(has_CP(x)) {
4340
- collect(x);
4341
- }
4342
- else {
4343
- if(!patterns[x.value]) {
4344
- var u = core.Utils.getU(symbol);
4345
- // Get a u value and mark it for subsitution
4346
- patterns[x.value] = u;
4347
- symbol = symbol.sub(x.value, u);
4348
- }
4349
- }
4350
- }, true);
4351
- };
4352
-
4353
- // Collect a list of patterns
4354
- collect(symbol);
4355
-
4356
- return [symbol, patterns];
4357
- },
4358
- simplify: function (symbol) {
4359
- //remove the multiplier to make calculation easier;
4360
- var sym_array = __.Simplify.strip(symbol);
4361
- symbol = sym_array.pop();
4362
- //remove gcd from denominator
4363
- symbol = __.Simplify.fracSimp(symbol);
4364
- //nothing more to do
4365
- if(symbol.isConstant() || symbol.group === core.groups.S) {
4366
- sym_array.push(symbol);
4367
- var ret = __.Simplify.unstrip(sym_array, symbol);
4368
- return ret;
4369
- }
4370
-
4371
- //var patterns;
4372
-
4373
- var simplified = symbol.clone(); //make a copy
4374
-
4375
- //[simplified, patterns] = __.Simplify.patternSub(symbol);
4376
-
4377
- // Simplify sqrt within the symbol
4378
- // simplified = __.Simplify.sqrtSimp(simplified, sym_array);
4379
-
4380
- // Try trig simplificatons e.g. cos(x)^2+sin(x)^2
4381
- simplified = __.Simplify.trigSimp(simplified);
4382
-
4383
- // Simplify common denominators
4384
- simplified = __.Simplify.ratSimp(simplified);
4385
-
4386
- // First go for the "cheapest" simplification which may eliminate
4387
- // your problems right away. factor -> evaluate. Remember
4388
- // that there's no need to expand since factor already does that
4389
-
4390
- simplified = __.Factor.factor(simplified);
4391
-
4392
- //If the simplfied is a sum then we can make a few more simplifications
4393
- //e.g. simplify(1/(x-1)+1/(1-x)) as per issue #431
4394
- if(simplified.group === core.groups.CP && simplified.isLinear()) {
4395
- var m = simplified.multiplier.clone();
4396
- simplified.toUnitMultiplier(); //strip the multiplier
4397
- var r = new Symbol(0);
4398
- //return the sum of simplifications
4399
- simplified.each(function (x) {
4400
- var s = __.Simplify.simplify(x);
4401
- r = _.add(r, s);
4402
- });
4403
- simplified = r;
4404
- //put back the multiplier
4405
- r.multiplier = r.multiplier.multiply(m);
4406
- }
4407
-
4408
- //place back multiplier and return
4409
- var retval = __.Simplify.unstrip(sym_array, simplified);
4410
-
4411
- // Back substitute
4412
- /*
4413
- for(var x in patterns) {
4414
- retval = retval.sub(patterns[x], x);
4415
- }
4416
- */
4417
-
4418
- return retval;
4419
- }
4420
- },
4421
-
4422
- Classes: {
4423
- Polynomial: Polynomial,
4424
- Factors: Factors,
4425
- MVTerm: MVTerm
4426
- }
4427
- };
4428
-
4429
- // Add a link to simplify
4430
- core.Expression.prototype.simplify = function () {
4431
- return __.Simplify.simplify(this.symbol);
4432
- };
4433
-
4434
- nerdamer.useAlgebraDiv = function () {
4435
- var divide = __.divideFn = _.divide;
4436
- var calls = 0; //keep track of how many calls were made
4437
- _.divide = function (a, b) {
4438
- calls++;
4439
- var ans;
4440
- if(calls === 1) //check if this is the first call. If it is use algebra divide
4441
- ans = core.Algebra.divide(a, b);
4442
- else //otherwise use parser divide
4443
- ans = divide(a, b);
4444
- calls = 0; //reset the number of calls back to none
4445
- return ans;
4446
- };
4447
- };
4448
-
4449
- nerdamer.useParserDiv = function () {
4450
- if(__.divideFn)
4451
- _.divide = __.divideFn;
4452
- delete __.divideFn;
4453
- };
4454
-
4455
- nerdamer.register([
4456
- {
4457
- name: 'factor',
4458
- visible: true,
4459
- numargs: 1,
4460
- build: function () {
4461
- return __.Factor.factor;
4462
- }
4463
- },
4464
- {
4465
- name: 'simplify',
4466
- visible: true,
4467
- numargs: 1,
4468
- build: function () {
4469
- return __.Simplify.simplify;
4470
- }
4471
- },
4472
- {
4473
- name: 'gcd',
4474
- visible: true,
4475
- numargs: [1, ],
4476
- build: function () {
4477
- return __.gcd;
4478
- }
4479
- },
4480
- {
4481
- name: 'lcm',
4482
- visible: true,
4483
- numargs: [1, ],
4484
- build: function () {
4485
- return __.lcm;
4486
- }
4487
- },
4488
- {
4489
- name: 'roots',
4490
- visible: true,
4491
- numargs: -1,
4492
- build: function () {
4493
- return __.roots;
4494
- }
4495
- },
4496
- {
4497
- name: 'divide',
4498
- visible: true,
4499
- numargs: 2,
4500
- build: function () {
4501
- return __.divide;
4502
- }
4503
- },
4504
- {
4505
- name: 'div',
4506
- visible: true,
4507
- numargs: 2,
4508
- build: function () {
4509
- return __.div;
4510
- }
4511
- },
4512
- {
4513
- name: 'partfrac',
4514
- visible: true,
4515
- numargs: [1, 2],
4516
- build: function () {
4517
- return __.PartFrac.partfrac;
4518
- }
4519
- },
4520
- {
4521
- name: 'deg',
4522
- visible: true,
4523
- numargs: [1, 2],
4524
- build: function () {
4525
- return __.degree;
4526
- }
4527
- },
4528
- {
4529
- name: 'coeffs',
4530
- visible: true,
4531
- numargs: [1, 2],
4532
- build: function () {
4533
- var f = function () {
4534
- var coeffs = __.coeffs.apply(__, arguments);
4535
- return new core.Vector(coeffs);
4536
- };
4537
- return f;
4538
- }
4539
- },
4540
- {
4541
- name: 'line',
4542
- visible: true,
4543
- numargs: [2, 3],
4544
- build: function () {
4545
- return __.line;
4546
- }
4547
- },
4548
- {
4549
- name: 'sqcomp',
4550
- visible: true,
4551
- numargs: [1, 2],
4552
- build: function () {
4553
- var f = function (x, v) {
4554
- try {
4555
- v = v || variables(x)[0];
4556
- var sq = __.sqComplete(x.clone(), v);
4557
- return sq.f;
4558
- }
4559
- catch(e) {
4560
- return x;
4561
- }
4562
- };
4563
- return f;
4564
- }
4565
- }
4566
- ]);
4567
- nerdamer.updateAPI();
4568
- })();