mathjs 10.0.2 → 10.2.0

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 (337) hide show
  1. package/HISTORY.md +37 -0
  2. package/NOTICE +1 -1
  3. package/README.md +10 -2
  4. package/bin/cli.js +1 -1
  5. package/docs/expressions/algebra.md +27 -0
  6. package/docs/expressions/syntax.md +1 -1
  7. package/docs/reference/functions/abs.md +6 -0
  8. package/docs/reference/functions/acos.md +6 -0
  9. package/docs/reference/functions/acosh.md +6 -0
  10. package/docs/reference/functions/acot.md +6 -0
  11. package/docs/reference/functions/acoth.md +6 -0
  12. package/docs/reference/functions/acsc.md +6 -0
  13. package/docs/reference/functions/acsch.md +6 -0
  14. package/docs/reference/functions/add.md +6 -0
  15. package/docs/reference/functions/and.md +6 -0
  16. package/docs/reference/functions/apply.md +6 -0
  17. package/docs/reference/functions/arg.md +6 -0
  18. package/docs/reference/functions/asec.md +6 -0
  19. package/docs/reference/functions/asech.md +6 -0
  20. package/docs/reference/functions/asin.md +6 -0
  21. package/docs/reference/functions/asinh.md +6 -0
  22. package/docs/reference/functions/atan.md +6 -0
  23. package/docs/reference/functions/atan2.md +6 -0
  24. package/docs/reference/functions/atanh.md +6 -0
  25. package/docs/reference/functions/bellNumbers.md +6 -0
  26. package/docs/reference/functions/bin.md +6 -0
  27. package/docs/reference/functions/bitAnd.md +6 -0
  28. package/docs/reference/functions/bitNot.md +6 -0
  29. package/docs/reference/functions/bitOr.md +6 -0
  30. package/docs/reference/functions/bitXor.md +6 -0
  31. package/docs/reference/functions/catalan.md +6 -0
  32. package/docs/reference/functions/cbrt.md +6 -0
  33. package/docs/reference/functions/ceil.md +6 -0
  34. package/docs/reference/functions/clone.md +6 -0
  35. package/docs/reference/functions/column.md +6 -0
  36. package/docs/reference/functions/combinations.md +6 -0
  37. package/docs/reference/functions/combinationsWithRep.md +6 -0
  38. package/docs/reference/functions/compare.md +6 -0
  39. package/docs/reference/functions/compareNatural.md +6 -0
  40. package/docs/reference/functions/compareText.md +6 -0
  41. package/docs/reference/functions/compile.md +6 -0
  42. package/docs/reference/functions/composition.md +6 -0
  43. package/docs/reference/functions/concat.md +6 -0
  44. package/docs/reference/functions/conj.md +6 -0
  45. package/docs/reference/functions/cos.md +6 -0
  46. package/docs/reference/functions/cosh.md +6 -0
  47. package/docs/reference/functions/cot.md +6 -0
  48. package/docs/reference/functions/coth.md +6 -0
  49. package/docs/reference/functions/count.md +6 -0
  50. package/docs/reference/functions/cross.md +6 -0
  51. package/docs/reference/functions/csc.md +6 -0
  52. package/docs/reference/functions/csch.md +6 -0
  53. package/docs/reference/functions/ctranspose.md +6 -0
  54. package/docs/reference/functions/cube.md +6 -0
  55. package/docs/reference/functions/deepEqual.md +6 -0
  56. package/docs/reference/functions/derivative.md +6 -0
  57. package/docs/reference/functions/det.md +6 -0
  58. package/docs/reference/functions/diag.md +6 -0
  59. package/docs/reference/functions/diff.md +6 -0
  60. package/docs/reference/functions/distance.md +6 -0
  61. package/docs/reference/functions/divide.md +6 -0
  62. package/docs/reference/functions/dot.md +6 -0
  63. package/docs/reference/functions/dotDivide.md +6 -0
  64. package/docs/reference/functions/dotMultiply.md +6 -0
  65. package/docs/reference/functions/dotPow.md +6 -0
  66. package/docs/reference/functions/eigs.md +6 -0
  67. package/docs/reference/functions/equal.md +6 -0
  68. package/docs/reference/functions/equalText.md +6 -0
  69. package/docs/reference/functions/erf.md +6 -0
  70. package/docs/reference/functions/evaluate.md +6 -0
  71. package/docs/reference/functions/exp.md +6 -0
  72. package/docs/reference/functions/expm.md +6 -0
  73. package/docs/reference/functions/expm1.md +6 -0
  74. package/docs/reference/functions/factorial.md +6 -0
  75. package/docs/reference/functions/filter.md +6 -0
  76. package/docs/reference/functions/fix.md +6 -0
  77. package/docs/reference/functions/flatten.md +6 -0
  78. package/docs/reference/functions/floor.md +6 -0
  79. package/docs/reference/functions/forEach.md +6 -0
  80. package/docs/reference/functions/format.md +6 -0
  81. package/docs/reference/functions/gamma.md +6 -0
  82. package/docs/reference/functions/gcd.md +6 -0
  83. package/docs/reference/functions/getMatrixDataType.md +6 -0
  84. package/docs/reference/functions/hasNumericValue.md +6 -0
  85. package/docs/reference/functions/help.md +6 -0
  86. package/docs/reference/functions/hex.md +6 -0
  87. package/docs/reference/functions/hypot.md +6 -0
  88. package/docs/reference/functions/identity.md +6 -0
  89. package/docs/reference/functions/im.md +6 -0
  90. package/docs/reference/functions/intersect.md +6 -0
  91. package/docs/reference/functions/inv.md +6 -0
  92. package/docs/reference/functions/invmod.md +47 -0
  93. package/docs/reference/functions/isInteger.md +6 -0
  94. package/docs/reference/functions/isNaN.md +6 -0
  95. package/docs/reference/functions/isNegative.md +6 -0
  96. package/docs/reference/functions/isNumeric.md +6 -0
  97. package/docs/reference/functions/isPositive.md +6 -0
  98. package/docs/reference/functions/isPrime.md +6 -0
  99. package/docs/reference/functions/isZero.md +6 -0
  100. package/docs/reference/functions/kldivergence.md +6 -0
  101. package/docs/reference/functions/kron.md +6 -0
  102. package/docs/reference/functions/larger.md +6 -0
  103. package/docs/reference/functions/largerEq.md +6 -0
  104. package/docs/reference/functions/lcm.md +6 -0
  105. package/docs/reference/functions/leafCount.md +52 -0
  106. package/docs/reference/functions/leftShift.md +6 -0
  107. package/docs/reference/functions/log.md +6 -0
  108. package/docs/reference/functions/log10.md +6 -0
  109. package/docs/reference/functions/log1p.md +6 -0
  110. package/docs/reference/functions/log2.md +6 -0
  111. package/docs/reference/functions/lsolve.md +6 -0
  112. package/docs/reference/functions/lsolveAll.md +6 -0
  113. package/docs/reference/functions/lup.md +6 -0
  114. package/docs/reference/functions/lusolve.md +6 -0
  115. package/docs/reference/functions/mad.md +6 -0
  116. package/docs/reference/functions/map.md +6 -0
  117. package/docs/reference/functions/matrixFromColumns.md +6 -0
  118. package/docs/reference/functions/matrixFromFunction.md +6 -0
  119. package/docs/reference/functions/matrixFromRows.md +6 -0
  120. package/docs/reference/functions/max.md +6 -0
  121. package/docs/reference/functions/mean.md +6 -0
  122. package/docs/reference/functions/median.md +6 -0
  123. package/docs/reference/functions/min.md +6 -0
  124. package/docs/reference/functions/mod.md +6 -0
  125. package/docs/reference/functions/mode.md +6 -0
  126. package/docs/reference/functions/multinomial.md +6 -0
  127. package/docs/reference/functions/multiply.md +6 -0
  128. package/docs/reference/functions/norm.md +6 -0
  129. package/docs/reference/functions/not.md +6 -0
  130. package/docs/reference/functions/nthRoot.md +6 -0
  131. package/docs/reference/functions/nthRoots.md +6 -0
  132. package/docs/reference/functions/numeric.md +6 -0
  133. package/docs/reference/functions/oct.md +6 -0
  134. package/docs/reference/functions/ones.md +6 -0
  135. package/docs/reference/functions/or.md +6 -0
  136. package/docs/reference/functions/parser.md +6 -0
  137. package/docs/reference/functions/partitionSelect.md +6 -0
  138. package/docs/reference/functions/permutations.md +6 -0
  139. package/docs/reference/functions/pickRandom.md +6 -0
  140. package/docs/reference/functions/pow.md +6 -0
  141. package/docs/reference/functions/print.md +6 -0
  142. package/docs/reference/functions/prod.md +6 -0
  143. package/docs/reference/functions/qr.md +6 -0
  144. package/docs/reference/functions/quantileSeq.md +6 -0
  145. package/docs/reference/functions/random.md +6 -0
  146. package/docs/reference/functions/randomInt.md +6 -0
  147. package/docs/reference/functions/range.md +6 -0
  148. package/docs/reference/functions/rationalize.md +7 -1
  149. package/docs/reference/functions/re.md +6 -0
  150. package/docs/reference/functions/reshape.md +7 -0
  151. package/docs/reference/functions/resize.md +6 -0
  152. package/docs/reference/functions/resolve.md +46 -0
  153. package/docs/reference/functions/rightArithShift.md +6 -0
  154. package/docs/reference/functions/rightLogShift.md +6 -0
  155. package/docs/reference/functions/rotate.md +6 -0
  156. package/docs/reference/functions/rotationMatrix.md +6 -0
  157. package/docs/reference/functions/round.md +6 -0
  158. package/docs/reference/functions/row.md +6 -0
  159. package/docs/reference/functions/sec.md +6 -0
  160. package/docs/reference/functions/sech.md +6 -0
  161. package/docs/reference/functions/setCartesian.md +6 -0
  162. package/docs/reference/functions/setDifference.md +6 -0
  163. package/docs/reference/functions/setDistinct.md +6 -0
  164. package/docs/reference/functions/setIntersect.md +6 -0
  165. package/docs/reference/functions/setIsSubset.md +6 -0
  166. package/docs/reference/functions/setMultiplicity.md +6 -0
  167. package/docs/reference/functions/setPowerset.md +6 -0
  168. package/docs/reference/functions/setSize.md +6 -0
  169. package/docs/reference/functions/setSymDifference.md +6 -0
  170. package/docs/reference/functions/setUnion.md +6 -0
  171. package/docs/reference/functions/sign.md +6 -0
  172. package/docs/reference/functions/simplify.md +47 -7
  173. package/docs/reference/functions/simplifyCore.md +50 -0
  174. package/docs/reference/functions/sin.md +6 -0
  175. package/docs/reference/functions/sinh.md +6 -0
  176. package/docs/reference/functions/size.md +6 -0
  177. package/docs/reference/functions/slu.md +6 -0
  178. package/docs/reference/functions/smaller.md +6 -0
  179. package/docs/reference/functions/smallerEq.md +6 -0
  180. package/docs/reference/functions/sort.md +6 -0
  181. package/docs/reference/functions/sqrt.md +6 -0
  182. package/docs/reference/functions/sqrtm.md +6 -0
  183. package/docs/reference/functions/square.md +6 -0
  184. package/docs/reference/functions/squeeze.md +6 -0
  185. package/docs/reference/functions/std.md +6 -0
  186. package/docs/reference/functions/stirlingS2.md +6 -0
  187. package/docs/reference/functions/subset.md +6 -0
  188. package/docs/reference/functions/subtract.md +6 -0
  189. package/docs/reference/functions/sum.md +6 -0
  190. package/docs/reference/functions/tan.md +6 -0
  191. package/docs/reference/functions/tanh.md +6 -0
  192. package/docs/reference/functions/to.md +6 -0
  193. package/docs/reference/functions/trace.md +6 -0
  194. package/docs/reference/functions/transpose.md +6 -0
  195. package/docs/reference/functions/typeOf.md +6 -0
  196. package/docs/reference/functions/unaryMinus.md +6 -0
  197. package/docs/reference/functions/unaryPlus.md +6 -0
  198. package/docs/reference/functions/unequal.md +6 -0
  199. package/docs/reference/functions/usolve.md +6 -0
  200. package/docs/reference/functions/usolveAll.md +6 -0
  201. package/docs/reference/functions/variance.md +6 -0
  202. package/docs/reference/functions/xgcd.md +6 -0
  203. package/docs/reference/functions/xor.md +6 -0
  204. package/docs/reference/functions/zeros.md +6 -0
  205. package/docs/reference/functions.md +4 -0
  206. package/lib/browser/math.js +7 -7
  207. package/lib/browser/math.js.map +1 -1
  208. package/lib/cjs/core/create.js +4 -4
  209. package/lib/cjs/core/function/import.js +3 -3
  210. package/lib/cjs/core/function/typed.js +2 -2
  211. package/lib/cjs/defaultInstance.js +3 -3
  212. package/lib/cjs/entry/allFactoriesAny.js +1 -1
  213. package/lib/cjs/entry/allFactoriesNumber.js +1 -1
  214. package/lib/cjs/entry/configReadonly.js +1 -1
  215. package/lib/cjs/entry/dependenciesAny/dependenciesInvmod.generated.js +41 -0
  216. package/lib/cjs/entry/dependenciesAny/dependenciesLeafCount.generated.js +23 -0
  217. package/lib/cjs/entry/dependenciesAny/dependenciesRationalize.generated.js +18 -0
  218. package/lib/cjs/entry/dependenciesAny/dependenciesResolve.generated.js +32 -0
  219. package/lib/cjs/entry/dependenciesAny/dependenciesSimplify.generated.js +21 -0
  220. package/lib/cjs/entry/dependenciesAny/dependenciesSimplifyCore.generated.js +65 -0
  221. package/lib/cjs/entry/dependenciesAny.generated.js +32 -0
  222. package/lib/cjs/entry/dependenciesNumber/dependenciesRationalize.generated.js +18 -0
  223. package/lib/cjs/entry/dependenciesNumber/dependenciesResolve.generated.js +32 -0
  224. package/lib/cjs/entry/dependenciesNumber/dependenciesSimplify.generated.js +21 -0
  225. package/lib/cjs/entry/dependenciesNumber/dependenciesSimplifyCore.generated.js +65 -0
  226. package/lib/cjs/entry/dependenciesNumber.generated.js +16 -0
  227. package/lib/cjs/entry/impureFunctionsAny.generated.js +78 -29
  228. package/lib/cjs/entry/impureFunctionsNumber.generated.js +102 -60
  229. package/lib/cjs/entry/pureFunctionsAny.generated.js +65 -55
  230. package/lib/cjs/entry/pureFunctionsNumber.generated.js +46 -48
  231. package/lib/cjs/expression/Help.js +4 -0
  232. package/lib/cjs/expression/Parser.js +1 -1
  233. package/lib/cjs/expression/embeddedDocs/core/typed.js +1 -1
  234. package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +20 -6
  235. package/lib/cjs/expression/embeddedDocs/function/algebra/leafCount.js +15 -0
  236. package/lib/cjs/expression/embeddedDocs/function/algebra/resolve.js +16 -0
  237. package/lib/cjs/expression/embeddedDocs/function/algebra/simplify.js +1 -1
  238. package/lib/cjs/expression/embeddedDocs/function/algebra/simplifyCore.js +15 -0
  239. package/lib/cjs/expression/embeddedDocs/function/arithmetic/invmod.js +15 -0
  240. package/lib/cjs/expression/embeddedDocs/function/matrix/forEach.js +1 -1
  241. package/lib/cjs/expression/node/FunctionNode.js +7 -7
  242. package/lib/cjs/expression/node/IndexNode.js +1 -1
  243. package/lib/cjs/expression/node/Node.js +3 -3
  244. package/lib/cjs/expression/node/ObjectNode.js +1 -1
  245. package/lib/cjs/expression/node/utils/access.js +1 -1
  246. package/lib/cjs/expression/node/utils/assign.js +1 -1
  247. package/lib/cjs/expression/parse.js +13 -13
  248. package/lib/cjs/factoriesAny.js +32 -0
  249. package/lib/cjs/factoriesNumber.js +16 -0
  250. package/lib/cjs/function/algebra/decomposition/qr.js +1 -1
  251. package/lib/cjs/function/algebra/leafCount.js +66 -0
  252. package/lib/cjs/function/algebra/rationalize.js +36 -39
  253. package/lib/cjs/function/algebra/resolve.js +106 -0
  254. package/lib/cjs/function/algebra/simplify/simplifyConstant.js +226 -32
  255. package/lib/cjs/function/algebra/simplify/util.js +171 -33
  256. package/lib/cjs/function/algebra/simplify.js +608 -191
  257. package/lib/cjs/function/algebra/{simplify/simplifyCore.js → simplifyCore.js} +83 -31
  258. package/lib/cjs/function/algebra/solver/lsolveAll.js +2 -2
  259. package/lib/cjs/function/algebra/solver/usolveAll.js +2 -2
  260. package/lib/cjs/function/arithmetic/ceil.js +3 -3
  261. package/lib/cjs/function/arithmetic/floor.js +3 -3
  262. package/lib/cjs/function/arithmetic/invmod.js +73 -0
  263. package/lib/cjs/function/arithmetic/norm.js +1 -1
  264. package/lib/cjs/function/arithmetic/round.js +1 -1
  265. package/lib/cjs/function/matrix/eigs/complexEigs.js +5 -5
  266. package/lib/cjs/function/matrix/matrixFromColumns.js +1 -1
  267. package/lib/cjs/function/matrix/matrixFromRows.js +1 -1
  268. package/lib/cjs/function/probability/util/seededRNG.js +2 -2
  269. package/lib/cjs/function/relational/compareNatural.js +6 -6
  270. package/lib/cjs/header.js +3 -3
  271. package/lib/cjs/plain/bignumber/index.js +1 -1
  272. package/lib/cjs/plain/number/combinations.js +18 -6
  273. package/lib/cjs/type/bignumber/BigNumber.js +2 -2
  274. package/lib/cjs/type/bignumber/function/bignumber.js +1 -1
  275. package/lib/cjs/type/boolean.js +2 -2
  276. package/lib/cjs/type/complex/Complex.js +14 -14
  277. package/lib/cjs/type/complex/function/complex.js +1 -1
  278. package/lib/cjs/type/fraction/Fraction.js +6 -6
  279. package/lib/cjs/type/fraction/function/fraction.js +1 -1
  280. package/lib/cjs/type/matrix/DenseMatrix.js +5 -5
  281. package/lib/cjs/type/matrix/SparseMatrix.js +2 -2
  282. package/lib/cjs/type/number.js +1 -1
  283. package/lib/cjs/type/string.js +2 -2
  284. package/lib/cjs/type/unit/Unit.js +8 -8
  285. package/lib/cjs/utils/customs.js +2 -2
  286. package/lib/cjs/utils/emitter.js +1 -1
  287. package/lib/cjs/utils/function.js +2 -2
  288. package/lib/cjs/utils/is.js +6 -6
  289. package/lib/cjs/utils/latex.js +3 -3
  290. package/lib/cjs/utils/lruQueue.js +1 -1
  291. package/lib/cjs/utils/map.js +3 -3
  292. package/lib/cjs/utils/object.js +2 -2
  293. package/lib/cjs/utils/snapshot.js +7 -7
  294. package/lib/cjs/utils/string.js +2 -2
  295. package/lib/cjs/version.js +1 -1
  296. package/lib/esm/entry/dependenciesAny/dependenciesInvmod.generated.js +24 -0
  297. package/lib/esm/entry/dependenciesAny/dependenciesLeafCount.generated.js +12 -0
  298. package/lib/esm/entry/dependenciesAny/dependenciesRationalize.generated.js +12 -0
  299. package/lib/esm/entry/dependenciesAny/dependenciesResolve.generated.js +18 -0
  300. package/lib/esm/entry/dependenciesAny/dependenciesSimplify.generated.js +14 -0
  301. package/lib/esm/entry/dependenciesAny/dependenciesSimplifyCore.generated.js +40 -0
  302. package/lib/esm/entry/dependenciesAny.generated.js +4 -0
  303. package/lib/esm/entry/dependenciesNumber/dependenciesRationalize.generated.js +12 -0
  304. package/lib/esm/entry/dependenciesNumber/dependenciesResolve.generated.js +18 -0
  305. package/lib/esm/entry/dependenciesNumber/dependenciesSimplify.generated.js +14 -0
  306. package/lib/esm/entry/dependenciesNumber/dependenciesSimplifyCore.generated.js +40 -0
  307. package/lib/esm/entry/dependenciesNumber.generated.js +2 -0
  308. package/lib/esm/entry/impureFunctionsAny.generated.js +68 -22
  309. package/lib/esm/entry/impureFunctionsNumber.generated.js +92 -52
  310. package/lib/esm/entry/pureFunctionsAny.generated.js +53 -42
  311. package/lib/esm/entry/pureFunctionsNumber.generated.js +32 -32
  312. package/lib/esm/expression/Help.js +4 -0
  313. package/lib/esm/expression/embeddedDocs/core/typed.js +1 -1
  314. package/lib/esm/expression/embeddedDocs/embeddedDocs.js +10 -1
  315. package/lib/esm/expression/embeddedDocs/function/algebra/leafCount.js +8 -0
  316. package/lib/esm/expression/embeddedDocs/function/algebra/resolve.js +9 -0
  317. package/lib/esm/expression/embeddedDocs/function/algebra/simplify.js +1 -1
  318. package/lib/esm/expression/embeddedDocs/function/algebra/simplifyCore.js +8 -0
  319. package/lib/esm/expression/embeddedDocs/function/arithmetic/invmod.js +8 -0
  320. package/lib/esm/expression/embeddedDocs/function/matrix/forEach.js +1 -1
  321. package/lib/esm/factoriesAny.js +4 -0
  322. package/lib/esm/factoriesNumber.js +2 -0
  323. package/lib/esm/function/algebra/leafCount.js +59 -0
  324. package/lib/esm/function/algebra/rationalize.js +36 -38
  325. package/lib/esm/function/algebra/resolve.js +95 -0
  326. package/lib/esm/function/algebra/simplify/simplifyConstant.js +200 -32
  327. package/lib/esm/function/algebra/simplify/util.js +170 -34
  328. package/lib/esm/function/algebra/simplify.js +603 -186
  329. package/lib/esm/function/algebra/{simplify/simplifyCore.js → simplifyCore.js} +75 -31
  330. package/lib/esm/function/arithmetic/invmod.js +57 -0
  331. package/lib/esm/header.js +1 -1
  332. package/lib/esm/plain/number/combinations.js +18 -6
  333. package/lib/esm/version.js +1 -1
  334. package/package.json +21 -15
  335. package/types/index.d.ts +48 -6
  336. package/lib/cjs/function/algebra/simplify/resolve.js +0 -76
  337. package/lib/esm/function/algebra/simplify/resolve.js +0 -67
@@ -15,18 +15,14 @@ var _factory = require("../../utils/factory.js");
15
15
 
16
16
  var _util = require("./simplify/util.js");
17
17
 
18
- var _simplifyCore = require("./simplify/simplifyCore.js");
19
-
20
18
  var _simplifyConstant = require("./simplify/simplifyConstant.js");
21
19
 
22
- var _resolve = require("./simplify/resolve.js");
23
-
24
20
  var _object = require("../../utils/object.js");
25
21
 
26
22
  var _map = require("../../utils/map.js");
27
23
 
28
24
  var name = 'simplify';
29
- var dependencies = ['config', 'typed', 'parse', 'add', 'subtract', 'multiply', 'divide', 'pow', 'isZero', 'equal', '?fraction', '?bignumber', 'mathWithTransform', 'ConstantNode', 'FunctionNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
25
+ var dependencies = ['config', 'typed', 'parse', 'add', 'subtract', 'multiply', 'divide', 'pow', 'isZero', 'equal', 'resolve', 'simplifyCore', '?fraction', '?bignumber', 'mathWithTransform', 'matrix', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
30
26
  var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
31
27
  var config = _ref.config,
32
28
  typed = _ref.typed,
@@ -38,11 +34,18 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
38
34
  pow = _ref.pow,
39
35
  isZero = _ref.isZero,
40
36
  equal = _ref.equal,
37
+ resolve = _ref.resolve,
38
+ simplifyCore = _ref.simplifyCore,
41
39
  fraction = _ref.fraction,
42
40
  bignumber = _ref.bignumber,
43
41
  mathWithTransform = _ref.mathWithTransform,
42
+ matrix = _ref.matrix,
43
+ AccessorNode = _ref.AccessorNode,
44
+ ArrayNode = _ref.ArrayNode,
44
45
  ConstantNode = _ref.ConstantNode,
45
46
  FunctionNode = _ref.FunctionNode,
47
+ IndexNode = _ref.IndexNode,
48
+ ObjectNode = _ref.ObjectNode,
46
49
  OperatorNode = _ref.OperatorNode,
47
50
  ParenthesisNode = _ref.ParenthesisNode,
48
51
  SymbolNode = _ref.SymbolNode;
@@ -50,31 +53,17 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
50
53
  typed: typed,
51
54
  config: config,
52
55
  mathWithTransform: mathWithTransform,
56
+ matrix: matrix,
53
57
  fraction: fraction,
54
58
  bignumber: bignumber,
59
+ AccessorNode: AccessorNode,
60
+ ArrayNode: ArrayNode,
55
61
  ConstantNode: ConstantNode,
56
- OperatorNode: OperatorNode,
57
- FunctionNode: FunctionNode,
58
- SymbolNode: SymbolNode
59
- });
60
- var simplifyCore = (0, _simplifyCore.createSimplifyCore)({
61
- equal: equal,
62
- isZero: isZero,
63
- add: add,
64
- subtract: subtract,
65
- multiply: multiply,
66
- divide: divide,
67
- pow: pow,
68
- ConstantNode: ConstantNode,
69
- OperatorNode: OperatorNode,
70
- FunctionNode: FunctionNode,
71
- ParenthesisNode: ParenthesisNode
72
- });
73
- var resolve = (0, _resolve.createResolve)({
74
- parse: parse,
75
62
  FunctionNode: FunctionNode,
63
+ IndexNode: IndexNode,
64
+ ObjectNode: ObjectNode,
76
65
  OperatorNode: OperatorNode,
77
- ParenthesisNode: ParenthesisNode
66
+ SymbolNode: SymbolNode
78
67
  });
79
68
 
80
69
  var _createUtil = (0, _util.createUtil)({
@@ -82,12 +71,17 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
82
71
  OperatorNode: OperatorNode,
83
72
  SymbolNode: SymbolNode
84
73
  }),
74
+ hasProperty = _createUtil.hasProperty,
85
75
  isCommutative = _createUtil.isCommutative,
86
76
  isAssociative = _createUtil.isAssociative,
77
+ mergeContext = _createUtil.mergeContext,
87
78
  flatten = _createUtil.flatten,
88
79
  unflattenr = _createUtil.unflattenr,
89
80
  unflattenl = _createUtil.unflattenl,
90
- createMakeNodeFunction = _createUtil.createMakeNodeFunction;
81
+ createMakeNodeFunction = _createUtil.createMakeNodeFunction,
82
+ defaultContext = _createUtil.defaultContext,
83
+ realContext = _createUtil.realContext,
84
+ positiveContext = _createUtil.positiveContext;
91
85
  /**
92
86
  * Simplify an expression tree.
93
87
  *
@@ -118,17 +112,49 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
118
112
  * The default list of rules is exposed on the function as `simplify.rules`
119
113
  * and can be used as a basis to built a set of custom rules.
120
114
  *
115
+ * To specify a rule as a string, separate the left and right pattern by '->'
116
+ * When specifying a rule as an object, the following keys are meaningful:
117
+ * - l - the left pattern
118
+ * - r - the right pattern
119
+ * - s - in lieu of l and r, the string form that is broken at -> to give them
120
+ * - repeat - whether to repeat this rule until the expression stabilizes
121
+ * - assuming - gives a context object, as in the 'context' option to
122
+ * simplify. Every property in the context object must match the current
123
+ * context in order, or else the rule will not be applied.
124
+ * - imposeContext - gives a context object, as in the 'context' option to
125
+ * simplify. Any settings specified will override the incoming context
126
+ * for all matches of this rule.
127
+ *
121
128
  * For more details on the theory, see:
122
129
  *
123
130
  * - [Strategies for simplifying math expressions (Stackoverflow)](https://stackoverflow.com/questions/7540227/strategies-for-simplifying-math-expressions)
124
131
  * - [Symbolic computation - Simplification (Wikipedia)](https://en.wikipedia.org/wiki/Symbolic_computation#Simplification)
125
132
  *
126
133
  * An optional `options` argument can be passed as last argument of `simplify`.
127
- * There is currently one option available:
128
- * - `exactFractions`: a boolean which is `true` by default.
129
- * - `fractionsLimit`: when `exactFractions` is true, a fraction will be returned
130
- * only when both numerator and denominator are smaller than `fractionsLimit`.
131
- * Default value is 10000.
134
+ * Currently available options (defaults in parentheses):
135
+ * - `consoleDebug` (false): whether to write the expression being simplified
136
+ * and any changes to it, along with the rule responsible, to console
137
+ * - `context` (simplify.defaultContext): an object giving properties of
138
+ * each operator, which determine what simplifications are allowed. The
139
+ * currently meaningful properties are commutative, associative,
140
+ * total (whether the operation is defined for all arguments), and
141
+ * trivial (whether the operation applied to a single argument leaves
142
+ * that argument unchanged). The default context is very permissive and
143
+ * allows almost all simplifications. Only properties differing from
144
+ * the default need to be specified; the default context is used as a
145
+ * fallback. Additional contexts `simplify.realContext` and
146
+ * `simplify.positiveContext` are supplied to cause simplify to perform
147
+ * just simplifications guaranteed to preserve all values of the expression
148
+ * assuming all variables and subexpressions are real numbers or
149
+ * positive real numbers, respectively. (Note that these are in some cases
150
+ * more restrictive than the default context; for example, the default
151
+ * context will allow `x/x` to simplify to 1, whereas
152
+ * `simplify.realContext` will not, as `0/0` is not equal to 1.)
153
+ * - `exactFractions` (true): whether to try to convert all constants to
154
+ * exact rational numbers.
155
+ * - `fractionsLimit` (10000): when `exactFractions` is true, constants will
156
+ * be expressed as fractions only when both numerator and denominator
157
+ * are smaller than `fractionsLimit`.
132
158
  *
133
159
  * Syntax:
134
160
  *
@@ -151,7 +177,7 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
151
177
  *
152
178
  * See also:
153
179
  *
154
- * derivative, parse, evaluate, rationalize
180
+ * simplifyCore, derivative, evaluate, parse, rationalize, resolve
155
181
  *
156
182
  * @param {Node | string} expr
157
183
  * The expression to be simplified
@@ -199,7 +225,8 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
199
225
  return this(expr, rules, (0, _map.createMap)(scope), options);
200
226
  },
201
227
  'Node, Array, Map, Object': function NodeArrayMapObject(expr, rules, scope, options) {
202
- rules = _buildRules(rules);
228
+ var debug = options.consoleDebug;
229
+ rules = _buildRules(rules, options.context);
203
230
  var res = resolve(expr, scope);
204
231
  res = removeParens(res);
205
232
  var visited = {};
@@ -211,15 +238,40 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
211
238
  visited[str] = true;
212
239
  _lastsym = 0; // counter for placeholder symbols
213
240
 
241
+ var laststr = str;
242
+ if (debug) console.log('Working on: ', str);
243
+
214
244
  for (var i = 0; i < rules.length; i++) {
245
+ var rulestr = '';
246
+
215
247
  if (typeof rules[i] === 'function') {
216
248
  res = rules[i](res, options);
249
+ if (debug) rulestr = rules[i].name;
217
250
  } else {
218
- flatten(res);
219
- res = applyRule(res, rules[i]);
251
+ flatten(res, options.context);
252
+ res = applyRule(res, rules[i], options.context);
253
+
254
+ if (debug) {
255
+ rulestr = "".concat(rules[i].l.toString(), " -> ").concat(rules[i].r.toString());
256
+ }
220
257
  }
221
258
 
222
- unflattenl(res); // using left-heavy binary tree here since custom rule functions may expect it
259
+ if (debug) {
260
+ var newstr = res.toString({
261
+ parenthesis: 'all'
262
+ });
263
+
264
+ if (newstr !== laststr) {
265
+ console.log('Applying', rulestr, 'produced', newstr);
266
+ laststr = newstr;
267
+ }
268
+ }
269
+ /* Use left-heavy binary tree internally,
270
+ * since custom rule functions may expect it
271
+ */
272
+
273
+
274
+ unflattenl(res, options.context);
223
275
  }
224
276
 
225
277
  str = res.toString({
@@ -230,8 +282,9 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
230
282
  return res;
231
283
  }
232
284
  });
233
- simplify.simplifyCore = simplifyCore;
234
- simplify.resolve = resolve;
285
+ simplify.defaultContext = defaultContext;
286
+ simplify.realContext = realContext;
287
+ simplify.positiveContext = positiveContext;
235
288
 
236
289
  function removeParens(node) {
237
290
  return node.transform(function (node, path, parent) {
@@ -241,8 +294,8 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
241
294
 
242
295
 
243
296
  var SUPPORTED_CONSTANTS = {
244
- "true": true,
245
- "false": true,
297
+ true: true,
298
+ false: true,
246
299
  e: true,
247
300
  i: true,
248
301
  Infinity: true,
@@ -280,72 +333,247 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
280
333
  l: 'log(e)',
281
334
  r: '1'
282
335
  }, // temporary rules
336
+ // Note initially we tend constants to the right because like-term
337
+ // collection prefers the left, and we would rather collect nonconstants
283
338
  {
284
- l: 'n-n1',
285
- r: 'n+-n1'
286
- }, // temporarily replace 'subtract' so we can further flatten the 'add' operator
339
+ s: 'n-n1 -> n+-n1',
340
+ // temporarily replace 'subtract' so we can further flatten the 'add' operator
341
+ assuming: {
342
+ subtract: {
343
+ total: true
344
+ }
345
+ }
346
+ }, {
347
+ s: '-(c*v) -> v * (-c)',
348
+ // make non-constant terms positive
349
+ assuming: {
350
+ multiply: {
351
+ commutative: true
352
+ },
353
+ subtract: {
354
+ total: true
355
+ }
356
+ }
357
+ }, {
358
+ s: '-(c*v) -> (-c) * v',
359
+ // non-commutative version, part 1
360
+ assuming: {
361
+ multiply: {
362
+ commutative: false
363
+ },
364
+ subtract: {
365
+ total: true
366
+ }
367
+ }
368
+ }, {
369
+ s: '-(v*c) -> v * (-c)',
370
+ // non-commutative version, part 2
371
+ assuming: {
372
+ multiply: {
373
+ commutative: false
374
+ },
375
+ subtract: {
376
+ total: true
377
+ }
378
+ }
379
+ }, {
380
+ l: '-(n1/n2)',
381
+ r: '-n1/n2'
382
+ }, {
383
+ l: '-v',
384
+ r: 'v * (-1)'
385
+ }, // finish making non-constant terms positive
287
386
  {
288
- l: '-(c*v)',
289
- r: '(-c) * v'
290
- }, // make non-constant terms positive
387
+ l: '(n1 + n2)*(-1)',
388
+ r: 'n1*(-1) + n2*(-1)',
389
+ repeat: true
390
+ }, // expand negations to achieve as much sign cancellation as possible
291
391
  {
292
- l: '-v',
293
- r: '(-1) * v'
294
- }, {
295
392
  l: 'n/n1^n2',
296
393
  r: 'n*n1^-n2'
297
394
  }, // temporarily replace 'divide' so we can further flatten the 'multiply' operator
298
395
  {
299
396
  l: 'n/n1',
300
397
  r: 'n*n1^-1'
398
+ }, {
399
+ s: '(n1*n2)^n3 -> n1^n3 * n2^n3',
400
+ assuming: {
401
+ multiply: {
402
+ commutative: true
403
+ }
404
+ }
405
+ }, {
406
+ s: '(n1*n2)^(-1) -> n2^(-1) * n1^(-1)',
407
+ assuming: {
408
+ multiply: {
409
+ commutative: false
410
+ }
411
+ }
301
412
  }, // expand nested exponentiation
302
413
  {
303
- l: '(n ^ n1) ^ n2',
304
- r: 'n ^ (n1 * n2)'
305
- }, // collect like factors
414
+ s: '(n ^ n1) ^ n2 -> n ^ (n1 * n2)',
415
+ assuming: {
416
+ divide: {
417
+ total: true
418
+ }
419
+ } // 1/(1/n) = n needs 1/n to exist
420
+
421
+ }, // collect like factors; into a sum, only do this for nonconstants
306
422
  {
423
+ l: ' v * ( v * n1 + n2)',
424
+ r: 'v^2 * n1 + v * n2'
425
+ }, {
426
+ s: ' v * (v^n4 * n1 + n2) -> v^(1+n4) * n1 + v * n2',
427
+ assuming: {
428
+ divide: {
429
+ total: true
430
+ }
431
+ } // v*1/v = v^(1+-1) needs 1/v
432
+
433
+ }, {
434
+ s: 'v^n3 * ( v * n1 + n2) -> v^(n3+1) * n1 + v^n3 * n2',
435
+ assuming: {
436
+ divide: {
437
+ total: true
438
+ }
439
+ }
440
+ }, {
441
+ s: 'v^n3 * (v^n4 * n1 + n2) -> v^(n3+n4) * n1 + v^n3 * n2',
442
+ assuming: {
443
+ divide: {
444
+ total: true
445
+ }
446
+ }
447
+ }, {
307
448
  l: 'n*n',
308
449
  r: 'n^2'
309
450
  }, {
310
- l: 'n * n^n1',
311
- r: 'n^(n1+1)'
451
+ s: 'n * n^n1 -> n^(n1+1)',
452
+ assuming: {
453
+ divide: {
454
+ total: true
455
+ }
456
+ } // n*1/n = n^(-1+1) needs 1/n
457
+
312
458
  }, {
313
- l: 'n^n1 * n^n2',
314
- r: 'n^(n1+n2)'
315
- }, // collect like terms
459
+ s: 'n^n1 * n^n2 -> n^(n1+n2)',
460
+ assuming: {
461
+ divide: {
462
+ total: true
463
+ }
464
+ } // ditto for n^2*1/n^2
465
+
466
+ }, // Unfortunately, to deal with more complicated cancellations, it
467
+ // becomes necessary to simplify constants twice per pass. It's not
468
+ // terribly expensive compared to matching rules, so this should not
469
+ // pose a performance problem.
470
+ simplifyConstant, // First: before collecting like terms
471
+ // collect like terms
316
472
  {
317
- l: 'n+n',
318
- r: '2*n'
473
+ s: 'n+n -> 2*n',
474
+ assuming: {
475
+ add: {
476
+ total: true
477
+ }
478
+ } // 2 = 1 + 1 needs to exist
479
+
319
480
  }, {
320
481
  l: 'n+-n',
321
482
  r: '0'
322
483
  }, {
323
- l: 'n1*n2 + n2',
324
- r: '(n1+1)*n2'
484
+ l: 'v*n + v',
485
+ r: 'v*(n+1)'
486
+ }, // NOTE: leftmost position is special:
487
+ {
488
+ l: 'n3*n1 + n3*n2',
489
+ r: 'n3*(n1+n2)'
490
+ }, // All sub-monomials tried there.
491
+ {
492
+ l: 'n3^(-n4)*n1 + n3 * n2',
493
+ r: 'n3^(-n4)*(n1 + n3^(n4+1) *n2)'
494
+ }, {
495
+ l: 'n3^(-n4)*n1 + n3^n5 * n2',
496
+ r: 'n3^(-n4)*(n1 + n3^(n4+n5)*n2)'
497
+ }, {
498
+ s: 'n*v + v -> (n+1)*v',
499
+ // noncommutative additional cases
500
+ assuming: {
501
+ multiply: {
502
+ commutative: false
503
+ }
504
+ }
505
+ }, {
506
+ s: 'n1*n3 + n2*n3 -> (n1+n2)*n3',
507
+ assuming: {
508
+ multiply: {
509
+ commutative: false
510
+ }
511
+ }
512
+ }, {
513
+ s: 'n1*n3^(-n4) + n2 * n3 -> (n1 + n2*n3^(n4 + 1))*n3^(-n4)',
514
+ assuming: {
515
+ multiply: {
516
+ commutative: false
517
+ }
518
+ }
519
+ }, {
520
+ s: 'n1*n3^(-n4) + n2 * n3^n5 -> (n1 + n2*n3^(n4 + n5))*n3^(-n4)',
521
+ assuming: {
522
+ multiply: {
523
+ commutative: false
524
+ }
525
+ }
526
+ }, {
527
+ l: 'n*c + c',
528
+ r: '(n+1)*c'
325
529
  }, {
326
- l: 'n1*n3 + n2*n3',
327
- r: '(n1+n2)*n3'
328
- }, // remove parenthesis in the case of negating a quantitiy
530
+ s: 'c*n + c -> c*(n+1)',
531
+ assuming: {
532
+ multiply: {
533
+ commutative: false
534
+ }
535
+ }
536
+ }, simplifyConstant, // Second: before returning expressions to "standard form"
537
+ // make factors positive (and undo 'make non-constant terms positive')
329
538
  {
330
- l: 'n1 + -1 * (n2 + n3)',
331
- r: 'n1 + -1 * n2 + -1 * n3'
332
- }, simplifyConstant, {
333
- l: '(-n)*n1',
334
- r: '-(n*n1)'
335
- }, // make factors positive (and undo 'make non-constant terms positive')
336
- // ordering of constants
539
+ s: '(-n)*n1 -> -(n*n1)',
540
+ assuming: {
541
+ subtract: {
542
+ total: true
543
+ }
544
+ }
545
+ }, {
546
+ s: 'n1*(-n) -> -(n1*n)',
547
+ // in case * non-commutative
548
+ assuming: {
549
+ subtract: {
550
+ total: true
551
+ },
552
+ multiply: {
553
+ commutative: false
554
+ }
555
+ }
556
+ }, // final ordering of constants
337
557
  {
338
- l: 'c+v',
339
- r: 'v+c',
340
- context: {
558
+ s: 'c+v -> v+c',
559
+ assuming: {
560
+ add: {
561
+ commutative: true
562
+ }
563
+ },
564
+ imposeContext: {
341
565
  add: {
342
566
  commutative: false
343
567
  }
344
568
  }
345
569
  }, {
346
- l: 'v*c',
347
- r: 'c*v',
348
- context: {
570
+ s: 'v*c -> c*v',
571
+ assuming: {
572
+ multiply: {
573
+ commutative: true
574
+ }
575
+ },
576
+ imposeContext: {
349
577
  multiply: {
350
578
  commutative: false
351
579
  }
@@ -357,36 +585,127 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
357
585
  r: 'n-n1'
358
586
  }, // undo replace 'subtract'
359
587
  {
360
- l: 'n*(n1^-1)',
361
- r: 'n/n1'
362
- }, // undo replace 'divide'
363
- {
364
- l: 'n*n1^-n2',
365
- r: 'n/n1^n2'
588
+ s: 'n*(n1^-1) -> n/n1',
589
+ // undo replace 'divide'; for * commutative
590
+ assuming: {
591
+ multiply: {
592
+ commutative: true
593
+ }
594
+ } // o.w. / not conventional
595
+
366
596
  }, {
367
- l: 'n1^-1',
368
- r: '1/n1'
597
+ s: 'n*n1^-n2 -> n/n1^n2',
598
+ assuming: {
599
+ multiply: {
600
+ commutative: true
601
+ }
602
+ } // o.w. / not conventional
603
+
369
604
  }, {
370
- l: 'n*(n1/n2)',
371
- r: '(n*n1)/n2'
372
- }, // '*' before '/'
605
+ s: 'n^-1 -> 1/n',
606
+ assuming: {
607
+ multiply: {
608
+ commutative: true
609
+ }
610
+ } // o.w. / not conventional
611
+
612
+ }, {
613
+ l: 'n^1',
614
+ r: 'n'
615
+ }, // can be produced by power cancellation
373
616
  {
374
- l: 'n-(n1+n2)',
375
- r: 'n-n1-n2'
376
- }, // '-' before '+'
377
- // { l: '(n1/n2)/n3', r: 'n1/(n2*n3)' },
617
+ s: 'n*(n1/n2) -> (n*n1)/n2',
618
+ // '*' before '/'
619
+ assuming: {
620
+ multiply: {
621
+ associative: true
622
+ }
623
+ }
624
+ }, {
625
+ s: 'n-(n1+n2) -> n-n1-n2',
626
+ // '-' before '+'
627
+ assuming: {
628
+ addition: {
629
+ associative: true,
630
+ commutative: true
631
+ }
632
+ }
633
+ }, // { l: '(n1/n2)/n3', r: 'n1/(n2*n3)' },
378
634
  // { l: '(n*n1)/(n*n2)', r: 'n1/n2' },
635
+ // simplifyConstant can leave an extra factor of 1, which can always
636
+ // be eliminated, since the identity always commutes
379
637
  {
380
638
  l: '1*n',
381
- r: 'n'
382
- }, // this pattern can be produced by simplifyConstant
383
- {
384
- l: 'n1/(n2/n3)',
385
- r: '(n1*n3)/n2'
639
+ r: 'n',
640
+ imposeContext: {
641
+ multiply: {
642
+ commutative: true
643
+ }
644
+ }
645
+ }, {
646
+ s: 'n1/(n2/n3) -> (n1*n3)/n2',
647
+ assuming: {
648
+ multiply: {
649
+ associative: true
650
+ }
651
+ }
386
652
  }, {
387
653
  l: 'n1/(-n2)',
388
654
  r: '-n1/n2'
389
655
  }];
656
+ /**
657
+ * Takes any rule object as allowed by the specification in simplify
658
+ * and puts it in a standard form used by applyRule
659
+ */
660
+
661
+ function _canonicalizeRule(ruleObject, context) {
662
+ var newRule = {};
663
+
664
+ if (ruleObject.s) {
665
+ var lr = ruleObject.s.split('->');
666
+
667
+ if (lr.length === 2) {
668
+ newRule.l = lr[0];
669
+ newRule.r = lr[1];
670
+ } else {
671
+ throw SyntaxError('Could not parse rule: ' + ruleObject.s);
672
+ }
673
+ } else {
674
+ newRule.l = ruleObject.l;
675
+ newRule.r = ruleObject.r;
676
+ }
677
+
678
+ newRule.l = removeParens(parse(newRule.l));
679
+ newRule.r = removeParens(parse(newRule.r));
680
+
681
+ for (var _i = 0, _arr = ['imposeContext', 'repeat', 'assuming']; _i < _arr.length; _i++) {
682
+ var prop = _arr[_i];
683
+
684
+ if (prop in ruleObject) {
685
+ newRule[prop] = ruleObject[prop];
686
+ }
687
+ }
688
+
689
+ if (ruleObject.evaluate) {
690
+ newRule.evaluate = parse(ruleObject.evaluate);
691
+ }
692
+
693
+ if (isAssociative(newRule.l, context)) {
694
+ var makeNode = createMakeNodeFunction(newRule.l);
695
+
696
+ var expandsym = _getExpandPlaceholderSymbol();
697
+
698
+ newRule.expanded = {};
699
+ newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
700
+ // This helps to match the newRule against nodes returned from getSplits() later on.
701
+
702
+ flatten(newRule.expanded.l, context);
703
+ unflattenr(newRule.expanded.l, context);
704
+ newRule.expanded.r = makeNode([newRule.r, expandsym]);
705
+ }
706
+
707
+ return newRule;
708
+ }
390
709
  /**
391
710
  * Parse the string array of rules into nodes
392
711
  *
@@ -404,60 +723,26 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
404
723
  * 'n1 * c1 -> c1 * n1'
405
724
  */
406
725
 
407
- function _buildRules(rules) {
726
+
727
+ function _buildRules(rules, context) {
408
728
  // Array of rules to be used to simplify expressions
409
729
  var ruleSet = [];
410
730
 
411
731
  for (var i = 0; i < rules.length; i++) {
412
732
  var rule = rules[i];
413
733
  var newRule = void 0;
414
- var ruleType = (0, _typeof2["default"])(rule);
734
+ var ruleType = (0, _typeof2.default)(rule);
415
735
 
416
736
  switch (ruleType) {
417
737
  case 'string':
418
- {
419
- var lr = rule.split('->');
420
-
421
- if (lr.length === 2) {
422
- rule = {
423
- l: lr[0],
424
- r: lr[1]
425
- };
426
- } else {
427
- throw SyntaxError('Could not parse rule: ' + rule);
428
- }
429
- }
738
+ rule = {
739
+ s: rule
740
+ };
430
741
 
431
742
  /* falls through */
432
743
 
433
744
  case 'object':
434
- newRule = {
435
- l: removeParens(parse(rule.l)),
436
- r: removeParens(parse(rule.r))
437
- };
438
-
439
- if (rule.context) {
440
- newRule.evaluate = rule.context;
441
- }
442
-
443
- if (rule.evaluate) {
444
- newRule.evaluate = parse(rule.evaluate);
445
- }
446
-
447
- if (isAssociative(newRule.l)) {
448
- var makeNode = createMakeNodeFunction(newRule.l);
449
-
450
- var expandsym = _getExpandPlaceholderSymbol();
451
-
452
- newRule.expanded = {};
453
- newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
454
- // This helps to match the newRule against nodes returned from getSplits() later on.
455
-
456
- flatten(newRule.expanded.l);
457
- unflattenr(newRule.expanded.l);
458
- newRule.expanded.r = makeNode([newRule.r, expandsym]);
459
- }
460
-
745
+ newRule = _canonicalizeRule(rule, context);
461
746
  break;
462
747
 
463
748
  case 'function':
@@ -481,71 +766,156 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
481
766
  function _getExpandPlaceholderSymbol() {
482
767
  return new SymbolNode('_p' + _lastsym++);
483
768
  }
769
+
770
+ function mapRule(nodes, rule, context) {
771
+ var resNodes = nodes;
772
+
773
+ if (nodes) {
774
+ for (var i = 0; i < nodes.length; ++i) {
775
+ var newNode = applyRule(nodes[i], rule, context);
776
+
777
+ if (newNode !== nodes[i]) {
778
+ if (resNodes === nodes) {
779
+ resNodes = nodes.slice();
780
+ }
781
+
782
+ resNodes[i] = newNode;
783
+ }
784
+ }
785
+ }
786
+
787
+ return resNodes;
788
+ }
484
789
  /**
485
790
  * Returns a simplfied form of node, or the original node if no simplification was possible.
486
791
  *
487
792
  * @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
793
+ * @param {Object | Function} rule
794
+ * @param {Object} context -- information about assumed properties of operators
488
795
  * @return {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} The simplified form of `expr`, or the original node if no simplification was possible.
489
796
  */
490
797
 
491
798
 
492
- var applyRule = typed('applyRule', {
493
- 'Node, Object': function NodeObject(node, rule) {
494
- // console.log('Entering applyRule(' + node.toString() + ')')
495
- // Do not clone node unless we find a match
496
- var res = node; // First replace our child nodes with their simplified versions
497
- // If a child could not be simplified, the assignments will have
498
- // no effect since the node is returned unchanged
499
-
500
- if (res instanceof OperatorNode || res instanceof FunctionNode) {
501
- if (res.args) {
502
- for (var i = 0; i < res.args.length; i++) {
503
- res.args[i] = applyRule(res.args[i], rule);
799
+ function applyRule(node, rule, context) {
800
+ // console.log('Entering applyRule("', rule.l.toString({parenthesis:'all'}), '->', rule.r.toString({parenthesis:'all'}), '",', node.toString({parenthesis:'all'}),')')
801
+ // check that the assumptions for this rule are satisfied by the current
802
+ // context:
803
+ if (rule.assuming) {
804
+ for (var symbol in rule.assuming) {
805
+ for (var property in rule.assuming[symbol]) {
806
+ if (hasProperty(symbol, property, context) !== rule.assuming[symbol][property]) {
807
+ return node;
504
808
  }
505
809
  }
506
- } else if (res instanceof ParenthesisNode) {
507
- if (res.content) {
508
- res.content = applyRule(res.content, rule);
810
+ }
811
+ }
812
+
813
+ var mergedContext = mergeContext(rule.imposeContext, context); // Do not clone node unless we find a match
814
+
815
+ var res = node; // First replace our child nodes with their simplified versions
816
+ // If a child could not be simplified, applying the rule to it
817
+ // will have no effect since the node is returned unchanged
818
+
819
+ if (res instanceof OperatorNode || res instanceof FunctionNode) {
820
+ var newArgs = mapRule(res.args, rule, context);
821
+
822
+ if (newArgs !== res.args) {
823
+ res = res.clone();
824
+ res.args = newArgs;
825
+ }
826
+ } else if (res instanceof ParenthesisNode) {
827
+ if (res.content) {
828
+ var newContent = applyRule(res.content, rule, context);
829
+
830
+ if (newContent !== res.content) {
831
+ res = new ParenthesisNode(newContent);
509
832
  }
510
- } // Try to match a rule against this node
833
+ }
834
+ } else if (res instanceof ArrayNode) {
835
+ var newItems = mapRule(res.items, rule, context);
511
836
 
837
+ if (newItems !== res.items) {
838
+ res = new ArrayNode(newItems);
839
+ }
840
+ } else if (res instanceof AccessorNode) {
841
+ var newObj = res.object;
512
842
 
513
- var repl = rule.r;
843
+ if (res.object) {
844
+ newObj = applyRule(res.object, rule, context);
845
+ }
514
846
 
515
- var matches = _ruleMatch(rule.l, res)[0]; // If the rule is associative operator, we can try matching it while allowing additional terms.
516
- // This allows us to match rules like 'n+n' to the expression '(1+x)+x' or even 'x+1+x' if the operator is commutative.
847
+ var newIndex = res.index;
517
848
 
849
+ if (res.index) {
850
+ newIndex = applyRule(res.index, rule, context);
851
+ }
518
852
 
519
- if (!matches && rule.expanded) {
520
- repl = rule.expanded.r;
521
- matches = _ruleMatch(rule.expanded.l, res)[0];
853
+ if (newObj !== res.object || newIndex !== res.index) {
854
+ res = new AccessorNode(newObj, newIndex);
522
855
  }
856
+ } else if (res instanceof IndexNode) {
857
+ var newDims = mapRule(res.dimensions, rule, context);
523
858
 
524
- if (matches) {
525
- // const before = res.toString({parenthesis: 'all'})
526
- // Create a new node by cloning the rhs of the matched rule
527
- // we keep any implicit multiplication state if relevant
528
- var implicit = res.implicit;
529
- res = repl.clone();
859
+ if (newDims !== res.dimensions) {
860
+ res = new IndexNode(newDims);
861
+ }
862
+ } else if (res instanceof ObjectNode) {
863
+ var changed = false;
864
+ var newProps = {};
530
865
 
531
- if (implicit && 'implicit' in repl) {
532
- res.implicit = true;
533
- } // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
866
+ for (var prop in res.properties) {
867
+ newProps[prop] = applyRule(res.properties[prop], rule, context);
534
868
 
869
+ if (newProps[prop] !== res.properties[prop]) {
870
+ changed = true;
871
+ }
872
+ }
535
873
 
536
- res = res.transform(function (node) {
537
- if (node.isSymbolNode && (0, _object.hasOwnProperty)(matches.placeholders, node.name)) {
538
- return matches.placeholders[node.name].clone();
539
- } else {
540
- return node;
541
- }
542
- }); // const after = res.toString({parenthesis: 'all'})
543
- // console.log('Simplified ' + before + ' to ' + after)
874
+ if (changed) {
875
+ res = new ObjectNode(newProps);
544
876
  }
877
+ } // Try to match a rule against this node
545
878
 
546
- return res;
879
+
880
+ var repl = rule.r;
881
+
882
+ var matches = _ruleMatch(rule.l, res, mergedContext)[0]; // If the rule is associative operator, we can try matching it while allowing additional terms.
883
+ // This allows us to match rules like 'n+n' to the expression '(1+x)+x' or even 'x+1+x' if the operator is commutative.
884
+
885
+
886
+ if (!matches && rule.expanded) {
887
+ repl = rule.expanded.r;
888
+ matches = _ruleMatch(rule.expanded.l, res, mergedContext)[0];
547
889
  }
548
- });
890
+
891
+ if (matches) {
892
+ // const before = res.toString({parenthesis: 'all'})
893
+ // Create a new node by cloning the rhs of the matched rule
894
+ // we keep any implicit multiplication state if relevant
895
+ var implicit = res.implicit;
896
+ res = repl.clone();
897
+
898
+ if (implicit && 'implicit' in repl) {
899
+ res.implicit = true;
900
+ } // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
901
+
902
+
903
+ res = res.transform(function (node) {
904
+ if (node.isSymbolNode && (0, _object.hasOwnProperty)(matches.placeholders, node.name)) {
905
+ return matches.placeholders[node.name].clone();
906
+ } else {
907
+ return node;
908
+ }
909
+ }); // const after = res.toString({parenthesis: 'all'})
910
+ // console.log('Simplified ' + before + ' to ' + after)
911
+ }
912
+
913
+ if (rule.repeat && res !== node) {
914
+ res = applyRule(res, rule, context);
915
+ }
916
+
917
+ return res;
918
+ }
549
919
  /**
550
920
  * Get (binary) combinations of a flattened binary node
551
921
  * e.g. +(node1, node2, node3) -> [
@@ -555,6 +925,7 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
555
925
  *
556
926
  */
557
927
 
928
+
558
929
  function getSplits(node, context) {
559
930
  var res = [];
560
931
  var right, rightArgs;
@@ -568,9 +939,18 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
568
939
  res.push(makeNode([node.args[i], right]));
569
940
  }
570
941
  } else {
571
- rightArgs = node.args.slice(1);
572
- right = rightArgs.length === 1 ? rightArgs[0] : makeNode(rightArgs);
573
- res.push(makeNode([node.args[0], right]));
942
+ // Keep order, but try all parenthesizations
943
+ for (var _i2 = 1; _i2 < node.args.length; _i2++) {
944
+ var left = node.args[0];
945
+
946
+ if (_i2 > 1) {
947
+ left = makeNode(node.args.slice(0, _i2));
948
+ }
949
+
950
+ rightArgs = node.args.slice(_i2);
951
+ right = rightArgs.length === 1 ? rightArgs[0] : makeNode(rightArgs);
952
+ res.push(makeNode([left, right]));
953
+ }
574
954
  }
575
955
 
576
956
  return res;
@@ -673,15 +1053,19 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
673
1053
  *
674
1054
  * @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} rule
675
1055
  * @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
1056
+ * @param {Object} context -- provides assumed properties of operators
1057
+ * @param {Boolean} isSplit -- whether we are in process of splitting an
1058
+ * n-ary operator node into possible binary combinations.
1059
+ * Defaults to false.
676
1060
  * @return {Object} Information about the match, if it exists.
677
1061
  */
678
1062
 
679
1063
 
680
- function _ruleMatch(rule, node, isSplit) {
1064
+ function _ruleMatch(rule, node, context, isSplit) {
681
1065
  // console.log('Entering _ruleMatch(' + JSON.stringify(rule) + ', ' + JSON.stringify(node) + ')')
682
1066
  // console.log('rule = ' + rule)
683
1067
  // console.log('node = ' + node)
684
- // console.log('Entering _ruleMatch(' + rule.toString() + ', ' + node.toString() + ')')
1068
+ // console.log('Entering _ruleMatch(', rule.toString({parenthesis:'all'}), ', ', node.toString({parenthesis:'all'}), ', ', context, ')')
685
1069
  var res = [{
686
1070
  placeholders: {}
687
1071
  }];
@@ -699,32 +1083,65 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
699
1083
  } // rule and node match. Search the children of rule and node.
700
1084
 
701
1085
 
702
- if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node) && node.args.length === rule.args.length || isSplit) {
703
- // Expect non-associative operators to match exactly
1086
+ if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node, context) && node.args.length === rule.args.length || isSplit) {
1087
+ // Expect non-associative operators to match exactly,
1088
+ // except in any order if operator is commutative
704
1089
  var childMatches = [];
705
1090
 
706
1091
  for (var i = 0; i < rule.args.length; i++) {
707
- var childMatch = _ruleMatch(rule.args[i], node.args[i]);
1092
+ var childMatch = _ruleMatch(rule.args[i], node.args[i], context);
708
1093
 
709
1094
  if (childMatch.length === 0) {
710
1095
  // Child did not match, so stop searching immediately
711
- return [];
1096
+ break;
712
1097
  } // The child matched, so add the information returned from the child to our result
713
1098
 
714
1099
 
715
1100
  childMatches.push(childMatch);
716
1101
  }
717
1102
 
1103
+ if (childMatches.length !== rule.args.length) {
1104
+ if (!isCommutative(node, context) || // exact match in order needed
1105
+ rule.args.length === 1) {
1106
+ // nothing to commute
1107
+ return [];
1108
+ }
1109
+
1110
+ if (rule.args.length > 2) {
1111
+ /* Need to generate all permutations and try them.
1112
+ * It's a bit complicated, and unlikely to come up since there
1113
+ * are very few ternary or higher operators. So punt for now.
1114
+ */
1115
+ throw new Error('permuting >2 commutative non-associative rule arguments not yet implemented');
1116
+ }
1117
+ /* Exactly two arguments, try them reversed */
1118
+
1119
+
1120
+ var leftMatch = _ruleMatch(rule.args[0], node.args[1], context);
1121
+
1122
+ if (leftMatch.length === 0) {
1123
+ return [];
1124
+ }
1125
+
1126
+ var rightMatch = _ruleMatch(rule.args[1], node.args[0], context);
1127
+
1128
+ if (rightMatch.length === 0) {
1129
+ return [];
1130
+ }
1131
+
1132
+ childMatches = [leftMatch, rightMatch];
1133
+ }
1134
+
718
1135
  res = mergeChildMatches(childMatches);
719
1136
  } else if (node.args.length >= 2 && rule.args.length === 2) {
720
1137
  // node is flattened, rule is not
721
1138
  // Associative operators/functions can be split in different ways so we check if the rule matches each
722
1139
  // them and return their union.
723
- var splits = getSplits(node, rule.context);
1140
+ var splits = getSplits(node, context);
724
1141
  var splitMatches = [];
725
1142
 
726
- for (var _i = 0; _i < splits.length; _i++) {
727
- var matchSet = _ruleMatch(rule, splits[_i], true); // recursing at the same tree depth here
1143
+ for (var _i3 = 0; _i3 < splits.length; _i3++) {
1144
+ var matchSet = _ruleMatch(rule, splits[_i3], context, true); // recursing at the same tree depth here
728
1145
 
729
1146
 
730
1147
  splitMatches = splitMatches.concat(matchSet);