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