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
@@ -1,13 +1,11 @@
1
1
  import { isConstantNode, isParenthesisNode } from '../../utils/is.js';
2
2
  import { factory } from '../../utils/factory.js';
3
3
  import { createUtil } from './simplify/util.js';
4
- import { createSimplifyCore } from './simplify/simplifyCore.js';
5
4
  import { createSimplifyConstant } from './simplify/simplifyConstant.js';
6
- import { createResolve } from './simplify/resolve.js';
7
5
  import { hasOwnProperty } from '../../utils/object.js';
8
6
  import { createEmptyMap, createMap } from '../../utils/map.js';
9
7
  var name = 'simplify';
10
- var dependencies = ['config', 'typed', 'parse', 'add', 'subtract', 'multiply', 'divide', 'pow', 'isZero', 'equal', '?fraction', '?bignumber', 'mathWithTransform', 'ConstantNode', 'FunctionNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
8
+ 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'];
11
9
  export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
12
10
  var {
13
11
  config,
@@ -20,11 +18,18 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
20
18
  pow,
21
19
  isZero,
22
20
  equal,
21
+ resolve,
22
+ simplifyCore,
23
23
  fraction,
24
24
  bignumber,
25
25
  mathWithTransform,
26
+ matrix,
27
+ AccessorNode,
28
+ ArrayNode,
26
29
  ConstantNode,
27
30
  FunctionNode,
31
+ IndexNode,
32
+ ObjectNode,
28
33
  OperatorNode,
29
34
  ParenthesisNode,
30
35
  SymbolNode
@@ -33,39 +38,30 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
33
38
  typed,
34
39
  config,
35
40
  mathWithTransform,
41
+ matrix,
36
42
  fraction,
37
43
  bignumber,
44
+ AccessorNode,
45
+ ArrayNode,
38
46
  ConstantNode,
39
- OperatorNode,
40
- FunctionNode,
41
- SymbolNode
42
- });
43
- var simplifyCore = createSimplifyCore({
44
- equal,
45
- isZero,
46
- add,
47
- subtract,
48
- multiply,
49
- divide,
50
- pow,
51
- ConstantNode,
52
- OperatorNode,
53
- FunctionNode,
54
- ParenthesisNode
55
- });
56
- var resolve = createResolve({
57
- parse,
58
47
  FunctionNode,
48
+ IndexNode,
49
+ ObjectNode,
59
50
  OperatorNode,
60
- ParenthesisNode
51
+ SymbolNode
61
52
  });
62
53
  var {
54
+ hasProperty,
63
55
  isCommutative,
64
56
  isAssociative,
57
+ mergeContext,
65
58
  flatten,
66
59
  unflattenr,
67
60
  unflattenl,
68
- createMakeNodeFunction
61
+ createMakeNodeFunction,
62
+ defaultContext,
63
+ realContext,
64
+ positiveContext
69
65
  } = createUtil({
70
66
  FunctionNode,
71
67
  OperatorNode,
@@ -101,17 +97,49 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
101
97
  * The default list of rules is exposed on the function as `simplify.rules`
102
98
  * and can be used as a basis to built a set of custom rules.
103
99
  *
100
+ * To specify a rule as a string, separate the left and right pattern by '->'
101
+ * When specifying a rule as an object, the following keys are meaningful:
102
+ * - l - the left pattern
103
+ * - r - the right pattern
104
+ * - s - in lieu of l and r, the string form that is broken at -> to give them
105
+ * - repeat - whether to repeat this rule until the expression stabilizes
106
+ * - assuming - gives a context object, as in the 'context' option to
107
+ * simplify. Every property in the context object must match the current
108
+ * context in order, or else the rule will not be applied.
109
+ * - imposeContext - gives a context object, as in the 'context' option to
110
+ * simplify. Any settings specified will override the incoming context
111
+ * for all matches of this rule.
112
+ *
104
113
  * For more details on the theory, see:
105
114
  *
106
115
  * - [Strategies for simplifying math expressions (Stackoverflow)](https://stackoverflow.com/questions/7540227/strategies-for-simplifying-math-expressions)
107
116
  * - [Symbolic computation - Simplification (Wikipedia)](https://en.wikipedia.org/wiki/Symbolic_computation#Simplification)
108
117
  *
109
118
  * An optional `options` argument can be passed as last argument of `simplify`.
110
- * There is currently one option available:
111
- * - `exactFractions`: a boolean which is `true` by default.
112
- * - `fractionsLimit`: when `exactFractions` is true, a fraction will be returned
113
- * only when both numerator and denominator are smaller than `fractionsLimit`.
114
- * Default value is 10000.
119
+ * Currently available options (defaults in parentheses):
120
+ * - `consoleDebug` (false): whether to write the expression being simplified
121
+ * and any changes to it, along with the rule responsible, to console
122
+ * - `context` (simplify.defaultContext): an object giving properties of
123
+ * each operator, which determine what simplifications are allowed. The
124
+ * currently meaningful properties are commutative, associative,
125
+ * total (whether the operation is defined for all arguments), and
126
+ * trivial (whether the operation applied to a single argument leaves
127
+ * that argument unchanged). The default context is very permissive and
128
+ * allows almost all simplifications. Only properties differing from
129
+ * the default need to be specified; the default context is used as a
130
+ * fallback. Additional contexts `simplify.realContext` and
131
+ * `simplify.positiveContext` are supplied to cause simplify to perform
132
+ * just simplifications guaranteed to preserve all values of the expression
133
+ * assuming all variables and subexpressions are real numbers or
134
+ * positive real numbers, respectively. (Note that these are in some cases
135
+ * more restrictive than the default context; for example, the default
136
+ * context will allow `x/x` to simplify to 1, whereas
137
+ * `simplify.realContext` will not, as `0/0` is not equal to 1.)
138
+ * - `exactFractions` (true): whether to try to convert all constants to
139
+ * exact rational numbers.
140
+ * - `fractionsLimit` (10000): when `exactFractions` is true, constants will
141
+ * be expressed as fractions only when both numerator and denominator
142
+ * are smaller than `fractionsLimit`.
115
143
  *
116
144
  * Syntax:
117
145
  *
@@ -134,7 +162,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
134
162
  *
135
163
  * See also:
136
164
  *
137
- * derivative, parse, evaluate, rationalize
165
+ * simplifyCore, derivative, evaluate, parse, rationalize, resolve
138
166
  *
139
167
  * @param {Node | string} expr
140
168
  * The expression to be simplified
@@ -181,7 +209,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
181
209
  return this(expr, rules, createMap(scope), options);
182
210
  },
183
211
  'Node, Array, Map, Object': function NodeArrayMapObject(expr, rules, scope, options) {
184
- rules = _buildRules(rules);
212
+ var debug = options.consoleDebug;
213
+ rules = _buildRules(rules, options.context);
185
214
  var res = resolve(expr, scope);
186
215
  res = removeParens(res);
187
216
  var visited = {};
@@ -193,15 +222,40 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
193
222
  visited[str] = true;
194
223
  _lastsym = 0; // counter for placeholder symbols
195
224
 
225
+ var laststr = str;
226
+ if (debug) console.log('Working on: ', str);
227
+
196
228
  for (var i = 0; i < rules.length; i++) {
229
+ var rulestr = '';
230
+
197
231
  if (typeof rules[i] === 'function') {
198
232
  res = rules[i](res, options);
233
+ if (debug) rulestr = rules[i].name;
199
234
  } else {
200
- flatten(res);
201
- res = applyRule(res, rules[i]);
235
+ flatten(res, options.context);
236
+ res = applyRule(res, rules[i], options.context);
237
+
238
+ if (debug) {
239
+ rulestr = "".concat(rules[i].l.toString(), " -> ").concat(rules[i].r.toString());
240
+ }
241
+ }
242
+
243
+ if (debug) {
244
+ var newstr = res.toString({
245
+ parenthesis: 'all'
246
+ });
247
+
248
+ if (newstr !== laststr) {
249
+ console.log('Applying', rulestr, 'produced', newstr);
250
+ laststr = newstr;
251
+ }
202
252
  }
253
+ /* Use left-heavy binary tree internally,
254
+ * since custom rule functions may expect it
255
+ */
203
256
 
204
- unflattenl(res); // using left-heavy binary tree here since custom rule functions may expect it
257
+
258
+ unflattenl(res, options.context);
205
259
  }
206
260
 
207
261
  str = res.toString({
@@ -212,8 +266,9 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
212
266
  return res;
213
267
  }
214
268
  });
215
- simplify.simplifyCore = simplifyCore;
216
- simplify.resolve = resolve;
269
+ simplify.defaultContext = defaultContext;
270
+ simplify.realContext = realContext;
271
+ simplify.positiveContext = positiveContext;
217
272
 
218
273
  function removeParens(node) {
219
274
  return node.transform(function (node, path, parent) {
@@ -262,72 +317,247 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
262
317
  l: 'log(e)',
263
318
  r: '1'
264
319
  }, // temporary rules
320
+ // Note initially we tend constants to the right because like-term
321
+ // collection prefers the left, and we would rather collect nonconstants
265
322
  {
266
- l: 'n-n1',
267
- r: 'n+-n1'
268
- }, // temporarily replace 'subtract' so we can further flatten the 'add' operator
323
+ s: 'n-n1 -> n+-n1',
324
+ // temporarily replace 'subtract' so we can further flatten the 'add' operator
325
+ assuming: {
326
+ subtract: {
327
+ total: true
328
+ }
329
+ }
330
+ }, {
331
+ s: '-(c*v) -> v * (-c)',
332
+ // make non-constant terms positive
333
+ assuming: {
334
+ multiply: {
335
+ commutative: true
336
+ },
337
+ subtract: {
338
+ total: true
339
+ }
340
+ }
341
+ }, {
342
+ s: '-(c*v) -> (-c) * v',
343
+ // non-commutative version, part 1
344
+ assuming: {
345
+ multiply: {
346
+ commutative: false
347
+ },
348
+ subtract: {
349
+ total: true
350
+ }
351
+ }
352
+ }, {
353
+ s: '-(v*c) -> v * (-c)',
354
+ // non-commutative version, part 2
355
+ assuming: {
356
+ multiply: {
357
+ commutative: false
358
+ },
359
+ subtract: {
360
+ total: true
361
+ }
362
+ }
363
+ }, {
364
+ l: '-(n1/n2)',
365
+ r: '-n1/n2'
366
+ }, {
367
+ l: '-v',
368
+ r: 'v * (-1)'
369
+ }, // finish making non-constant terms positive
269
370
  {
270
- l: '-(c*v)',
271
- r: '(-c) * v'
272
- }, // make non-constant terms positive
371
+ l: '(n1 + n2)*(-1)',
372
+ r: 'n1*(-1) + n2*(-1)',
373
+ repeat: true
374
+ }, // expand negations to achieve as much sign cancellation as possible
273
375
  {
274
- l: '-v',
275
- r: '(-1) * v'
276
- }, {
277
376
  l: 'n/n1^n2',
278
377
  r: 'n*n1^-n2'
279
378
  }, // temporarily replace 'divide' so we can further flatten the 'multiply' operator
280
379
  {
281
380
  l: 'n/n1',
282
381
  r: 'n*n1^-1'
382
+ }, {
383
+ s: '(n1*n2)^n3 -> n1^n3 * n2^n3',
384
+ assuming: {
385
+ multiply: {
386
+ commutative: true
387
+ }
388
+ }
389
+ }, {
390
+ s: '(n1*n2)^(-1) -> n2^(-1) * n1^(-1)',
391
+ assuming: {
392
+ multiply: {
393
+ commutative: false
394
+ }
395
+ }
283
396
  }, // expand nested exponentiation
284
397
  {
285
- l: '(n ^ n1) ^ n2',
286
- r: 'n ^ (n1 * n2)'
287
- }, // collect like factors
398
+ s: '(n ^ n1) ^ n2 -> n ^ (n1 * n2)',
399
+ assuming: {
400
+ divide: {
401
+ total: true
402
+ }
403
+ } // 1/(1/n) = n needs 1/n to exist
404
+
405
+ }, // collect like factors; into a sum, only do this for nonconstants
288
406
  {
407
+ l: ' v * ( v * n1 + n2)',
408
+ r: 'v^2 * n1 + v * n2'
409
+ }, {
410
+ s: ' v * (v^n4 * n1 + n2) -> v^(1+n4) * n1 + v * n2',
411
+ assuming: {
412
+ divide: {
413
+ total: true
414
+ }
415
+ } // v*1/v = v^(1+-1) needs 1/v
416
+
417
+ }, {
418
+ s: 'v^n3 * ( v * n1 + n2) -> v^(n3+1) * n1 + v^n3 * n2',
419
+ assuming: {
420
+ divide: {
421
+ total: true
422
+ }
423
+ }
424
+ }, {
425
+ s: 'v^n3 * (v^n4 * n1 + n2) -> v^(n3+n4) * n1 + v^n3 * n2',
426
+ assuming: {
427
+ divide: {
428
+ total: true
429
+ }
430
+ }
431
+ }, {
289
432
  l: 'n*n',
290
433
  r: 'n^2'
291
434
  }, {
292
- l: 'n * n^n1',
293
- r: 'n^(n1+1)'
435
+ s: 'n * n^n1 -> n^(n1+1)',
436
+ assuming: {
437
+ divide: {
438
+ total: true
439
+ }
440
+ } // n*1/n = n^(-1+1) needs 1/n
441
+
294
442
  }, {
295
- l: 'n^n1 * n^n2',
296
- r: 'n^(n1+n2)'
297
- }, // collect like terms
443
+ s: 'n^n1 * n^n2 -> n^(n1+n2)',
444
+ assuming: {
445
+ divide: {
446
+ total: true
447
+ }
448
+ } // ditto for n^2*1/n^2
449
+
450
+ }, // Unfortunately, to deal with more complicated cancellations, it
451
+ // becomes necessary to simplify constants twice per pass. It's not
452
+ // terribly expensive compared to matching rules, so this should not
453
+ // pose a performance problem.
454
+ simplifyConstant, // First: before collecting like terms
455
+ // collect like terms
298
456
  {
299
- l: 'n+n',
300
- r: '2*n'
457
+ s: 'n+n -> 2*n',
458
+ assuming: {
459
+ add: {
460
+ total: true
461
+ }
462
+ } // 2 = 1 + 1 needs to exist
463
+
301
464
  }, {
302
465
  l: 'n+-n',
303
466
  r: '0'
304
467
  }, {
305
- l: 'n1*n2 + n2',
306
- r: '(n1+1)*n2'
468
+ l: 'v*n + v',
469
+ r: 'v*(n+1)'
470
+ }, // NOTE: leftmost position is special:
471
+ {
472
+ l: 'n3*n1 + n3*n2',
473
+ r: 'n3*(n1+n2)'
474
+ }, // All sub-monomials tried there.
475
+ {
476
+ l: 'n3^(-n4)*n1 + n3 * n2',
477
+ r: 'n3^(-n4)*(n1 + n3^(n4+1) *n2)'
478
+ }, {
479
+ l: 'n3^(-n4)*n1 + n3^n5 * n2',
480
+ r: 'n3^(-n4)*(n1 + n3^(n4+n5)*n2)'
307
481
  }, {
308
- l: 'n1*n3 + n2*n3',
309
- r: '(n1+n2)*n3'
310
- }, // remove parenthesis in the case of negating a quantitiy
482
+ s: 'n*v + v -> (n+1)*v',
483
+ // noncommutative additional cases
484
+ assuming: {
485
+ multiply: {
486
+ commutative: false
487
+ }
488
+ }
489
+ }, {
490
+ s: 'n1*n3 + n2*n3 -> (n1+n2)*n3',
491
+ assuming: {
492
+ multiply: {
493
+ commutative: false
494
+ }
495
+ }
496
+ }, {
497
+ s: 'n1*n3^(-n4) + n2 * n3 -> (n1 + n2*n3^(n4 + 1))*n3^(-n4)',
498
+ assuming: {
499
+ multiply: {
500
+ commutative: false
501
+ }
502
+ }
503
+ }, {
504
+ s: 'n1*n3^(-n4) + n2 * n3^n5 -> (n1 + n2*n3^(n4 + n5))*n3^(-n4)',
505
+ assuming: {
506
+ multiply: {
507
+ commutative: false
508
+ }
509
+ }
510
+ }, {
511
+ l: 'n*c + c',
512
+ r: '(n+1)*c'
513
+ }, {
514
+ s: 'c*n + c -> c*(n+1)',
515
+ assuming: {
516
+ multiply: {
517
+ commutative: false
518
+ }
519
+ }
520
+ }, simplifyConstant, // Second: before returning expressions to "standard form"
521
+ // make factors positive (and undo 'make non-constant terms positive')
311
522
  {
312
- l: 'n1 + -1 * (n2 + n3)',
313
- r: 'n1 + -1 * n2 + -1 * n3'
314
- }, simplifyConstant, {
315
- l: '(-n)*n1',
316
- r: '-(n*n1)'
317
- }, // make factors positive (and undo 'make non-constant terms positive')
318
- // ordering of constants
523
+ s: '(-n)*n1 -> -(n*n1)',
524
+ assuming: {
525
+ subtract: {
526
+ total: true
527
+ }
528
+ }
529
+ }, {
530
+ s: 'n1*(-n) -> -(n1*n)',
531
+ // in case * non-commutative
532
+ assuming: {
533
+ subtract: {
534
+ total: true
535
+ },
536
+ multiply: {
537
+ commutative: false
538
+ }
539
+ }
540
+ }, // final ordering of constants
319
541
  {
320
- l: 'c+v',
321
- r: 'v+c',
322
- context: {
542
+ s: 'c+v -> v+c',
543
+ assuming: {
544
+ add: {
545
+ commutative: true
546
+ }
547
+ },
548
+ imposeContext: {
323
549
  add: {
324
550
  commutative: false
325
551
  }
326
552
  }
327
553
  }, {
328
- l: 'v*c',
329
- r: 'c*v',
330
- context: {
554
+ s: 'v*c -> c*v',
555
+ assuming: {
556
+ multiply: {
557
+ commutative: true
558
+ }
559
+ },
560
+ imposeContext: {
331
561
  multiply: {
332
562
  commutative: false
333
563
  }
@@ -339,36 +569,125 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
339
569
  r: 'n-n1'
340
570
  }, // undo replace 'subtract'
341
571
  {
342
- l: 'n*(n1^-1)',
343
- r: 'n/n1'
344
- }, // undo replace 'divide'
345
- {
346
- l: 'n*n1^-n2',
347
- r: 'n/n1^n2'
572
+ s: 'n*(n1^-1) -> n/n1',
573
+ // undo replace 'divide'; for * commutative
574
+ assuming: {
575
+ multiply: {
576
+ commutative: true
577
+ }
578
+ } // o.w. / not conventional
579
+
348
580
  }, {
349
- l: 'n1^-1',
350
- r: '1/n1'
581
+ s: 'n*n1^-n2 -> n/n1^n2',
582
+ assuming: {
583
+ multiply: {
584
+ commutative: true
585
+ }
586
+ } // o.w. / not conventional
587
+
588
+ }, {
589
+ s: 'n^-1 -> 1/n',
590
+ assuming: {
591
+ multiply: {
592
+ commutative: true
593
+ }
594
+ } // o.w. / not conventional
595
+
351
596
  }, {
352
- l: 'n*(n1/n2)',
353
- r: '(n*n1)/n2'
354
- }, // '*' before '/'
597
+ l: 'n^1',
598
+ r: 'n'
599
+ }, // can be produced by power cancellation
355
600
  {
356
- l: 'n-(n1+n2)',
357
- r: 'n-n1-n2'
358
- }, // '-' before '+'
359
- // { l: '(n1/n2)/n3', r: 'n1/(n2*n3)' },
601
+ s: 'n*(n1/n2) -> (n*n1)/n2',
602
+ // '*' before '/'
603
+ assuming: {
604
+ multiply: {
605
+ associative: true
606
+ }
607
+ }
608
+ }, {
609
+ s: 'n-(n1+n2) -> n-n1-n2',
610
+ // '-' before '+'
611
+ assuming: {
612
+ addition: {
613
+ associative: true,
614
+ commutative: true
615
+ }
616
+ }
617
+ }, // { l: '(n1/n2)/n3', r: 'n1/(n2*n3)' },
360
618
  // { l: '(n*n1)/(n*n2)', r: 'n1/n2' },
619
+ // simplifyConstant can leave an extra factor of 1, which can always
620
+ // be eliminated, since the identity always commutes
361
621
  {
362
622
  l: '1*n',
363
- r: 'n'
364
- }, // this pattern can be produced by simplifyConstant
365
- {
366
- l: 'n1/(n2/n3)',
367
- r: '(n1*n3)/n2'
623
+ r: 'n',
624
+ imposeContext: {
625
+ multiply: {
626
+ commutative: true
627
+ }
628
+ }
629
+ }, {
630
+ s: 'n1/(n2/n3) -> (n1*n3)/n2',
631
+ assuming: {
632
+ multiply: {
633
+ associative: true
634
+ }
635
+ }
368
636
  }, {
369
637
  l: 'n1/(-n2)',
370
638
  r: '-n1/n2'
371
639
  }];
640
+ /**
641
+ * Takes any rule object as allowed by the specification in simplify
642
+ * and puts it in a standard form used by applyRule
643
+ */
644
+
645
+ function _canonicalizeRule(ruleObject, context) {
646
+ var newRule = {};
647
+
648
+ if (ruleObject.s) {
649
+ var lr = ruleObject.s.split('->');
650
+
651
+ if (lr.length === 2) {
652
+ newRule.l = lr[0];
653
+ newRule.r = lr[1];
654
+ } else {
655
+ throw SyntaxError('Could not parse rule: ' + ruleObject.s);
656
+ }
657
+ } else {
658
+ newRule.l = ruleObject.l;
659
+ newRule.r = ruleObject.r;
660
+ }
661
+
662
+ newRule.l = removeParens(parse(newRule.l));
663
+ newRule.r = removeParens(parse(newRule.r));
664
+
665
+ for (var prop of ['imposeContext', 'repeat', 'assuming']) {
666
+ if (prop in ruleObject) {
667
+ newRule[prop] = ruleObject[prop];
668
+ }
669
+ }
670
+
671
+ if (ruleObject.evaluate) {
672
+ newRule.evaluate = parse(ruleObject.evaluate);
673
+ }
674
+
675
+ if (isAssociative(newRule.l, context)) {
676
+ var makeNode = createMakeNodeFunction(newRule.l);
677
+
678
+ var expandsym = _getExpandPlaceholderSymbol();
679
+
680
+ newRule.expanded = {};
681
+ newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
682
+ // This helps to match the newRule against nodes returned from getSplits() later on.
683
+
684
+ flatten(newRule.expanded.l, context);
685
+ unflattenr(newRule.expanded.l, context);
686
+ newRule.expanded.r = makeNode([newRule.r, expandsym]);
687
+ }
688
+
689
+ return newRule;
690
+ }
372
691
  /**
373
692
  * Parse the string array of rules into nodes
374
693
  *
@@ -386,7 +705,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
386
705
  * 'n1 * c1 -> c1 * n1'
387
706
  */
388
707
 
389
- function _buildRules(rules) {
708
+
709
+ function _buildRules(rules, context) {
390
710
  // Array of rules to be used to simplify expressions
391
711
  var ruleSet = [];
392
712
 
@@ -397,49 +717,14 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
397
717
 
398
718
  switch (ruleType) {
399
719
  case 'string':
400
- {
401
- var lr = rule.split('->');
402
-
403
- if (lr.length === 2) {
404
- rule = {
405
- l: lr[0],
406
- r: lr[1]
407
- };
408
- } else {
409
- throw SyntaxError('Could not parse rule: ' + rule);
410
- }
411
- }
720
+ rule = {
721
+ s: rule
722
+ };
412
723
 
413
724
  /* falls through */
414
725
 
415
726
  case 'object':
416
- newRule = {
417
- l: removeParens(parse(rule.l)),
418
- r: removeParens(parse(rule.r))
419
- };
420
-
421
- if (rule.context) {
422
- newRule.evaluate = rule.context;
423
- }
424
-
425
- if (rule.evaluate) {
426
- newRule.evaluate = parse(rule.evaluate);
427
- }
428
-
429
- if (isAssociative(newRule.l)) {
430
- var makeNode = createMakeNodeFunction(newRule.l);
431
-
432
- var expandsym = _getExpandPlaceholderSymbol();
433
-
434
- newRule.expanded = {};
435
- newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
436
- // This helps to match the newRule against nodes returned from getSplits() later on.
437
-
438
- flatten(newRule.expanded.l);
439
- unflattenr(newRule.expanded.l);
440
- newRule.expanded.r = makeNode([newRule.r, expandsym]);
441
- }
442
-
727
+ newRule = _canonicalizeRule(rule, context);
443
728
  break;
444
729
 
445
730
  case 'function':
@@ -463,71 +748,156 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
463
748
  function _getExpandPlaceholderSymbol() {
464
749
  return new SymbolNode('_p' + _lastsym++);
465
750
  }
751
+
752
+ function mapRule(nodes, rule, context) {
753
+ var resNodes = nodes;
754
+
755
+ if (nodes) {
756
+ for (var i = 0; i < nodes.length; ++i) {
757
+ var newNode = applyRule(nodes[i], rule, context);
758
+
759
+ if (newNode !== nodes[i]) {
760
+ if (resNodes === nodes) {
761
+ resNodes = nodes.slice();
762
+ }
763
+
764
+ resNodes[i] = newNode;
765
+ }
766
+ }
767
+ }
768
+
769
+ return resNodes;
770
+ }
466
771
  /**
467
772
  * Returns a simplfied form of node, or the original node if no simplification was possible.
468
773
  *
469
774
  * @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
775
+ * @param {Object | Function} rule
776
+ * @param {Object} context -- information about assumed properties of operators
470
777
  * @return {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} The simplified form of `expr`, or the original node if no simplification was possible.
471
778
  */
472
779
 
473
780
 
474
- var applyRule = typed('applyRule', {
475
- 'Node, Object': function NodeObject(node, rule) {
476
- // console.log('Entering applyRule(' + node.toString() + ')')
477
- // Do not clone node unless we find a match
478
- var res = node; // First replace our child nodes with their simplified versions
479
- // If a child could not be simplified, the assignments will have
480
- // no effect since the node is returned unchanged
481
-
482
- if (res instanceof OperatorNode || res instanceof FunctionNode) {
483
- if (res.args) {
484
- for (var i = 0; i < res.args.length; i++) {
485
- res.args[i] = applyRule(res.args[i], rule);
781
+ function applyRule(node, rule, context) {
782
+ // console.log('Entering applyRule("', rule.l.toString({parenthesis:'all'}), '->', rule.r.toString({parenthesis:'all'}), '",', node.toString({parenthesis:'all'}),')')
783
+ // check that the assumptions for this rule are satisfied by the current
784
+ // context:
785
+ if (rule.assuming) {
786
+ for (var symbol in rule.assuming) {
787
+ for (var property in rule.assuming[symbol]) {
788
+ if (hasProperty(symbol, property, context) !== rule.assuming[symbol][property]) {
789
+ return node;
486
790
  }
487
791
  }
488
- } else if (res instanceof ParenthesisNode) {
489
- if (res.content) {
490
- res.content = applyRule(res.content, rule);
792
+ }
793
+ }
794
+
795
+ var mergedContext = mergeContext(rule.imposeContext, context); // Do not clone node unless we find a match
796
+
797
+ var res = node; // First replace our child nodes with their simplified versions
798
+ // If a child could not be simplified, applying the rule to it
799
+ // will have no effect since the node is returned unchanged
800
+
801
+ if (res instanceof OperatorNode || res instanceof FunctionNode) {
802
+ var newArgs = mapRule(res.args, rule, context);
803
+
804
+ if (newArgs !== res.args) {
805
+ res = res.clone();
806
+ res.args = newArgs;
807
+ }
808
+ } else if (res instanceof ParenthesisNode) {
809
+ if (res.content) {
810
+ var newContent = applyRule(res.content, rule, context);
811
+
812
+ if (newContent !== res.content) {
813
+ res = new ParenthesisNode(newContent);
491
814
  }
492
- } // Try to match a rule against this node
815
+ }
816
+ } else if (res instanceof ArrayNode) {
817
+ var newItems = mapRule(res.items, rule, context);
493
818
 
819
+ if (newItems !== res.items) {
820
+ res = new ArrayNode(newItems);
821
+ }
822
+ } else if (res instanceof AccessorNode) {
823
+ var newObj = res.object;
494
824
 
495
- var repl = rule.r;
825
+ if (res.object) {
826
+ newObj = applyRule(res.object, rule, context);
827
+ }
496
828
 
497
- var matches = _ruleMatch(rule.l, res)[0]; // If the rule is associative operator, we can try matching it while allowing additional terms.
498
- // 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.
829
+ var newIndex = res.index;
499
830
 
831
+ if (res.index) {
832
+ newIndex = applyRule(res.index, rule, context);
833
+ }
500
834
 
501
- if (!matches && rule.expanded) {
502
- repl = rule.expanded.r;
503
- matches = _ruleMatch(rule.expanded.l, res)[0];
835
+ if (newObj !== res.object || newIndex !== res.index) {
836
+ res = new AccessorNode(newObj, newIndex);
504
837
  }
838
+ } else if (res instanceof IndexNode) {
839
+ var newDims = mapRule(res.dimensions, rule, context);
505
840
 
506
- if (matches) {
507
- // const before = res.toString({parenthesis: 'all'})
508
- // Create a new node by cloning the rhs of the matched rule
509
- // we keep any implicit multiplication state if relevant
510
- var implicit = res.implicit;
511
- res = repl.clone();
841
+ if (newDims !== res.dimensions) {
842
+ res = new IndexNode(newDims);
843
+ }
844
+ } else if (res instanceof ObjectNode) {
845
+ var changed = false;
846
+ var newProps = {};
512
847
 
513
- if (implicit && 'implicit' in repl) {
514
- res.implicit = true;
515
- } // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
848
+ for (var prop in res.properties) {
849
+ newProps[prop] = applyRule(res.properties[prop], rule, context);
516
850
 
851
+ if (newProps[prop] !== res.properties[prop]) {
852
+ changed = true;
853
+ }
854
+ }
517
855
 
518
- res = res.transform(function (node) {
519
- if (node.isSymbolNode && hasOwnProperty(matches.placeholders, node.name)) {
520
- return matches.placeholders[node.name].clone();
521
- } else {
522
- return node;
523
- }
524
- }); // const after = res.toString({parenthesis: 'all'})
525
- // console.log('Simplified ' + before + ' to ' + after)
856
+ if (changed) {
857
+ res = new ObjectNode(newProps);
526
858
  }
859
+ } // Try to match a rule against this node
527
860
 
528
- return res;
861
+
862
+ var repl = rule.r;
863
+
864
+ var matches = _ruleMatch(rule.l, res, mergedContext)[0]; // If the rule is associative operator, we can try matching it while allowing additional terms.
865
+ // 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.
866
+
867
+
868
+ if (!matches && rule.expanded) {
869
+ repl = rule.expanded.r;
870
+ matches = _ruleMatch(rule.expanded.l, res, mergedContext)[0];
529
871
  }
530
- });
872
+
873
+ if (matches) {
874
+ // const before = res.toString({parenthesis: 'all'})
875
+ // Create a new node by cloning the rhs of the matched rule
876
+ // we keep any implicit multiplication state if relevant
877
+ var implicit = res.implicit;
878
+ res = repl.clone();
879
+
880
+ if (implicit && 'implicit' in repl) {
881
+ res.implicit = true;
882
+ } // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
883
+
884
+
885
+ res = res.transform(function (node) {
886
+ if (node.isSymbolNode && hasOwnProperty(matches.placeholders, node.name)) {
887
+ return matches.placeholders[node.name].clone();
888
+ } else {
889
+ return node;
890
+ }
891
+ }); // const after = res.toString({parenthesis: 'all'})
892
+ // console.log('Simplified ' + before + ' to ' + after)
893
+ }
894
+
895
+ if (rule.repeat && res !== node) {
896
+ res = applyRule(res, rule, context);
897
+ }
898
+
899
+ return res;
900
+ }
531
901
  /**
532
902
  * Get (binary) combinations of a flattened binary node
533
903
  * e.g. +(node1, node2, node3) -> [
@@ -537,6 +907,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
537
907
  *
538
908
  */
539
909
 
910
+
540
911
  function getSplits(node, context) {
541
912
  var res = [];
542
913
  var right, rightArgs;
@@ -550,9 +921,18 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
550
921
  res.push(makeNode([node.args[i], right]));
551
922
  }
552
923
  } else {
553
- rightArgs = node.args.slice(1);
554
- right = rightArgs.length === 1 ? rightArgs[0] : makeNode(rightArgs);
555
- res.push(makeNode([node.args[0], right]));
924
+ // Keep order, but try all parenthesizations
925
+ for (var _i = 1; _i < node.args.length; _i++) {
926
+ var left = node.args[0];
927
+
928
+ if (_i > 1) {
929
+ left = makeNode(node.args.slice(0, _i));
930
+ }
931
+
932
+ rightArgs = node.args.slice(_i);
933
+ right = rightArgs.length === 1 ? rightArgs[0] : makeNode(rightArgs);
934
+ res.push(makeNode([left, right]));
935
+ }
556
936
  }
557
937
 
558
938
  return res;
@@ -655,15 +1035,19 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
655
1035
  *
656
1036
  * @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} rule
657
1037
  * @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
1038
+ * @param {Object} context -- provides assumed properties of operators
1039
+ * @param {Boolean} isSplit -- whether we are in process of splitting an
1040
+ * n-ary operator node into possible binary combinations.
1041
+ * Defaults to false.
658
1042
  * @return {Object} Information about the match, if it exists.
659
1043
  */
660
1044
 
661
1045
 
662
- function _ruleMatch(rule, node, isSplit) {
1046
+ function _ruleMatch(rule, node, context, isSplit) {
663
1047
  // console.log('Entering _ruleMatch(' + JSON.stringify(rule) + ', ' + JSON.stringify(node) + ')')
664
1048
  // console.log('rule = ' + rule)
665
1049
  // console.log('node = ' + node)
666
- // console.log('Entering _ruleMatch(' + rule.toString() + ', ' + node.toString() + ')')
1050
+ // console.log('Entering _ruleMatch(', rule.toString({parenthesis:'all'}), ', ', node.toString({parenthesis:'all'}), ', ', context, ')')
667
1051
  var res = [{
668
1052
  placeholders: {}
669
1053
  }];
@@ -681,32 +1065,65 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
681
1065
  } // rule and node match. Search the children of rule and node.
682
1066
 
683
1067
 
684
- if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node) && node.args.length === rule.args.length || isSplit) {
685
- // Expect non-associative operators to match exactly
1068
+ if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node, context) && node.args.length === rule.args.length || isSplit) {
1069
+ // Expect non-associative operators to match exactly,
1070
+ // except in any order if operator is commutative
686
1071
  var childMatches = [];
687
1072
 
688
1073
  for (var i = 0; i < rule.args.length; i++) {
689
- var childMatch = _ruleMatch(rule.args[i], node.args[i]);
1074
+ var childMatch = _ruleMatch(rule.args[i], node.args[i], context);
690
1075
 
691
1076
  if (childMatch.length === 0) {
692
1077
  // Child did not match, so stop searching immediately
693
- return [];
1078
+ break;
694
1079
  } // The child matched, so add the information returned from the child to our result
695
1080
 
696
1081
 
697
1082
  childMatches.push(childMatch);
698
1083
  }
699
1084
 
1085
+ if (childMatches.length !== rule.args.length) {
1086
+ if (!isCommutative(node, context) || // exact match in order needed
1087
+ rule.args.length === 1) {
1088
+ // nothing to commute
1089
+ return [];
1090
+ }
1091
+
1092
+ if (rule.args.length > 2) {
1093
+ /* Need to generate all permutations and try them.
1094
+ * It's a bit complicated, and unlikely to come up since there
1095
+ * are very few ternary or higher operators. So punt for now.
1096
+ */
1097
+ throw new Error('permuting >2 commutative non-associative rule arguments not yet implemented');
1098
+ }
1099
+ /* Exactly two arguments, try them reversed */
1100
+
1101
+
1102
+ var leftMatch = _ruleMatch(rule.args[0], node.args[1], context);
1103
+
1104
+ if (leftMatch.length === 0) {
1105
+ return [];
1106
+ }
1107
+
1108
+ var rightMatch = _ruleMatch(rule.args[1], node.args[0], context);
1109
+
1110
+ if (rightMatch.length === 0) {
1111
+ return [];
1112
+ }
1113
+
1114
+ childMatches = [leftMatch, rightMatch];
1115
+ }
1116
+
700
1117
  res = mergeChildMatches(childMatches);
701
1118
  } else if (node.args.length >= 2 && rule.args.length === 2) {
702
1119
  // node is flattened, rule is not
703
1120
  // Associative operators/functions can be split in different ways so we check if the rule matches each
704
1121
  // them and return their union.
705
- var splits = getSplits(node, rule.context);
1122
+ var splits = getSplits(node, context);
706
1123
  var splitMatches = [];
707
1124
 
708
- for (var _i = 0; _i < splits.length; _i++) {
709
- var matchSet = _ruleMatch(rule, splits[_i], true); // recursing at the same tree depth here
1125
+ for (var _i2 = 0; _i2 < splits.length; _i2++) {
1126
+ var matchSet = _ruleMatch(rule, splits[_i2], context, true); // recursing at the same tree depth here
710
1127
 
711
1128
 
712
1129
  splitMatches = splitMatches.concat(matchSet);