mathjs 10.0.2 → 10.2.0

Sign up to get free protection for your applications and to get access to all the features.
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);