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