nerdamer 1.1.13 → 2.0.0-rc.2

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 (387) hide show
  1. package/BREAKING_CHANGES.md +244 -5
  2. package/LICENSE.md +184 -0
  3. package/README.md +232 -318
  4. package/dist/bundle.js +2 -0
  5. package/dist/bundle.js.LICENSE.txt +7 -0
  6. package/dist/parser.js +2 -0
  7. package/dist/parser.js.LICENSE.txt +7 -0
  8. package/docs-data/parser-functions.json +2248 -0
  9. package/index.d.ts +10 -426
  10. package/output/algebra/adapters.d.ts +3 -0
  11. package/output/algebra/adapters.js +11 -0
  12. package/output/algebra/algorithms/arith.d.ts +84 -0
  13. package/output/algebra/algorithms/arith.js +324 -0
  14. package/output/algebra/algorithms/groebnerBase.d.ts +161 -0
  15. package/output/algebra/algorithms/groebnerBase.js +929 -0
  16. package/output/algebra/dispatch.d.ts +1 -0
  17. package/output/algebra/dispatch.js +25 -0
  18. package/output/algebra/factor/factor.d.ts +77 -0
  19. package/output/algebra/factor/factor.js +245 -0
  20. package/output/algebra/gcd/gcd.d.ts +30 -0
  21. package/output/algebra/gcd/gcd.js +95 -0
  22. package/output/algebra/groebner.d.ts +21 -0
  23. package/output/algebra/groebner.js +36 -0
  24. package/output/algebra/partfrac.d.ts +19 -0
  25. package/output/algebra/partfrac.js +365 -0
  26. package/output/algebra/polynomial/ModularSparsePolynomial.d.ts +131 -0
  27. package/output/algebra/polynomial/ModularSparsePolynomial.js +378 -0
  28. package/output/algebra/polynomial/ModularSparsePolynomialFactor.d.ts +40 -0
  29. package/output/algebra/polynomial/ModularSparsePolynomialFactor.js +661 -0
  30. package/output/algebra/polynomial/SparsePolynomialFactor.d.ts +64 -0
  31. package/output/algebra/polynomial/SparsePolynomialFactor.js +492 -0
  32. package/output/algebra/polynomial/SparsePolynomialGcd.d.ts +29 -0
  33. package/output/algebra/polynomial/SparsePolynomialGcd.js +259 -0
  34. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.d.ts +82 -0
  35. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.js +604 -0
  36. package/output/algebra/polynomial/modularGcd.d.ts +40 -0
  37. package/output/algebra/polynomial/modularGcd.js +365 -0
  38. package/output/algebra/polynomialize.d.ts +20 -0
  39. package/output/algebra/polynomialize.js +26 -0
  40. package/output/algebra/simplify/complexsimp.d.ts +7 -0
  41. package/output/algebra/simplify/complexsimp.js +24 -0
  42. package/output/algebra/simplify/factorCommon.d.ts +13 -0
  43. package/output/algebra/simplify/factorCommon.js +136 -0
  44. package/output/algebra/simplify/funcsimp.d.ts +26 -0
  45. package/output/algebra/simplify/funcsimp.js +633 -0
  46. package/output/algebra/simplify/invtrigrewrite.d.ts +10 -0
  47. package/output/algebra/simplify/invtrigrewrite.js +96 -0
  48. package/output/algebra/simplify/ratsimp.d.ts +21 -0
  49. package/output/algebra/simplify/ratsimp.js +140 -0
  50. package/output/algebra/simplify/simplify.d.ts +25 -0
  51. package/output/algebra/simplify/simplify.js +237 -0
  52. package/output/algebra/simplify/trigreduce.d.ts +38 -0
  53. package/output/algebra/simplify/trigreduce.js +424 -0
  54. package/output/algebra/simplify/trigrewrite.d.ts +17 -0
  55. package/output/algebra/simplify/trigrewrite.js +156 -0
  56. package/output/algebra/simplify/trigsimp.d.ts +11 -0
  57. package/output/algebra/simplify/trigsimp.js +369 -0
  58. package/output/algebra/simplify/utils.d.ts +32 -0
  59. package/output/algebra/simplify/utils.js +56 -0
  60. package/output/algebra/utils.d.ts +32 -0
  61. package/output/algebra/utils.js +48 -0
  62. package/output/api/advanced.d.ts +8 -0
  63. package/output/api/advanced.js +18 -0
  64. package/output/api/algebra.d.ts +17 -0
  65. package/output/api/algebra.js +35 -0
  66. package/output/api/assumptions.d.ts +4 -0
  67. package/output/api/assumptions.js +11 -0
  68. package/output/api/calculus.d.ts +10 -0
  69. package/output/api/calculus.js +22 -0
  70. package/output/api/core.d.ts +17 -0
  71. package/output/api/core.js +41 -0
  72. package/output/api/debug.d.ts +16 -0
  73. package/output/api/debug.js +23 -0
  74. package/output/api/languages/deu.d.ts +3 -0
  75. package/output/api/languages/deu.js +266 -0
  76. package/output/api/languages/fra.d.ts +3 -0
  77. package/output/api/languages/fra.js +266 -0
  78. package/output/api/languages/ita.d.ts +3 -0
  79. package/output/api/languages/ita.js +266 -0
  80. package/output/api/languages/nld.d.ts +3 -0
  81. package/output/api/languages/nld.js +266 -0
  82. package/output/api/languages/por.d.ts +3 -0
  83. package/output/api/languages/por.js +266 -0
  84. package/output/api/languages/spa.d.ts +3 -0
  85. package/output/api/languages/spa.js +266 -0
  86. package/output/api/parser.d.ts +93 -0
  87. package/output/api/parser.js +18 -0
  88. package/output/api/solve.d.ts +10 -0
  89. package/output/api/solve.js +17 -0
  90. package/output/api/structures.d.ts +10 -0
  91. package/output/api/structures.js +23 -0
  92. package/output/calculus/adapters.d.ts +8 -0
  93. package/output/calculus/adapters.js +41 -0
  94. package/output/calculus/derivative/diff.d.ts +30 -0
  95. package/output/calculus/derivative/diff.js +241 -0
  96. package/output/calculus/dispatch.d.ts +1 -0
  97. package/output/calculus/dispatch.js +25 -0
  98. package/output/calculus/fresnel.d.ts +16 -0
  99. package/output/calculus/fresnel.js +39 -0
  100. package/output/calculus/integrate/byParts.d.ts +18 -0
  101. package/output/calculus/integrate/byParts.js +339 -0
  102. package/output/calculus/integrate/bySubstitution.d.ts +135 -0
  103. package/output/calculus/integrate/bySubstitution.js +411 -0
  104. package/output/calculus/integrate/integrate.d.ts +38 -0
  105. package/output/calculus/integrate/integrate.js +652 -0
  106. package/output/calculus/integrate/integrationTable.d.ts +2 -0
  107. package/output/calculus/integrate/integrationTable.js +914 -0
  108. package/output/calculus/integrate/utils.d.ts +28 -0
  109. package/output/calculus/integrate/utils.js +96 -0
  110. package/output/calculus/laplace/ilaplace.d.ts +31 -0
  111. package/output/calculus/laplace/ilaplace.js +192 -0
  112. package/output/calculus/laplace/ilaplaceTable.d.ts +2 -0
  113. package/output/calculus/laplace/ilaplaceTable.js +200 -0
  114. package/output/calculus/laplace/laplace.d.ts +22 -0
  115. package/output/calculus/laplace/laplace.js +109 -0
  116. package/output/calculus/laplace/laplaceTable.d.ts +2 -0
  117. package/output/calculus/laplace/laplaceTable.js +187 -0
  118. package/output/calculus/limit/limit.d.ts +35 -0
  119. package/output/calculus/limit/limit.js +1183 -0
  120. package/output/calculus/limit/limitsTable.d.ts +2 -0
  121. package/output/calculus/limit/limitsTable.js +7 -0
  122. package/output/core/Settings.d.ts +32 -0
  123. package/output/core/Settings.js +68 -0
  124. package/output/core/classes/assumption/Assumption.d.ts +218 -0
  125. package/output/core/classes/assumption/Assumption.js +609 -0
  126. package/output/core/classes/assumption/assertiveFunctions.d.ts +6 -0
  127. package/output/core/classes/assumption/assertiveFunctions.js +64 -0
  128. package/output/core/classes/assumption/assume.d.ts +90 -0
  129. package/output/core/classes/assumption/assume.js +145 -0
  130. package/output/core/classes/assumption/dispatch.d.ts +1 -0
  131. package/output/core/classes/assumption/dispatch.js +11 -0
  132. package/output/core/classes/collection/Collection.d.ts +107 -0
  133. package/output/core/classes/collection/Collection.js +240 -0
  134. package/output/core/classes/complex/Complex.d.ts +109 -0
  135. package/output/core/classes/complex/Complex.js +153 -0
  136. package/output/core/classes/decimalSet/DecimalSet.d.ts +226 -0
  137. package/output/core/classes/decimalSet/DecimalSet.js +454 -0
  138. package/output/core/classes/dictionary/Dictionary.d.ts +102 -0
  139. package/output/core/classes/dictionary/Dictionary.js +216 -0
  140. package/output/core/classes/equation/Equation.d.ts +256 -0
  141. package/output/core/classes/equation/Equation.js +350 -0
  142. package/output/core/classes/expression/CoeffObject.d.ts +100 -0
  143. package/output/core/classes/expression/CoeffObject.js +197 -0
  144. package/output/core/classes/expression/Expression.d.ts +1691 -0
  145. package/output/core/classes/expression/Expression.js +2381 -0
  146. package/output/core/classes/expression/analysis.d.ts +25 -0
  147. package/output/core/classes/expression/analysis.js +218 -0
  148. package/output/core/classes/expression/collect.d.ts +9 -0
  149. package/output/core/classes/expression/collect.js +49 -0
  150. package/output/core/classes/expression/format.d.ts +54 -0
  151. package/output/core/classes/expression/format.js +340 -0
  152. package/output/core/classes/expression/products.d.ts +23 -0
  153. package/output/core/classes/expression/products.js +115 -0
  154. package/output/core/classes/expression/shortcuts.d.ts +35 -0
  155. package/output/core/classes/expression/shortcuts.js +129 -0
  156. package/output/core/classes/expression/traversal.d.ts +31 -0
  157. package/output/core/classes/expression/traversal.js +216 -0
  158. package/output/core/classes/expression/trig.d.ts +25 -0
  159. package/output/core/classes/expression/trig.js +40 -0
  160. package/output/core/classes/expression/utils.d.ts +61 -0
  161. package/output/core/classes/expression/utils.js +235 -0
  162. package/output/core/classes/lookupTable/LookupTable.d.ts +12 -0
  163. package/output/core/classes/lookupTable/LookupTable.js +55 -0
  164. package/output/core/classes/matrix/Matrix.d.ts +227 -0
  165. package/output/core/classes/matrix/Matrix.js +901 -0
  166. package/output/core/classes/matrix/Sylvester.d.ts +11 -0
  167. package/output/core/classes/matrix/Sylvester.js +54 -0
  168. package/output/core/classes/matrix/dispatch.d.ts +1 -0
  169. package/output/core/classes/matrix/dispatch.js +19 -0
  170. package/output/core/classes/matrix/functions.d.ts +28 -0
  171. package/output/core/classes/matrix/functions.js +57 -0
  172. package/output/core/classes/matrix/utils.d.ts +9 -0
  173. package/output/core/classes/matrix/utils.js +22 -0
  174. package/output/core/classes/parser/Parser.d.ts +493 -0
  175. package/output/core/classes/parser/Parser.js +1863 -0
  176. package/output/core/classes/parser/Token.d.ts +58 -0
  177. package/output/core/classes/parser/Token.js +137 -0
  178. package/output/core/classes/parser/constants.d.ts +162 -0
  179. package/output/core/classes/parser/constants.js +229 -0
  180. package/output/core/classes/parser/controlFlowSignals.d.ts +38 -0
  181. package/output/core/classes/parser/controlFlowSignals.js +60 -0
  182. package/output/core/classes/parser/helpers.d.ts +21 -0
  183. package/output/core/classes/parser/helpers.js +42 -0
  184. package/output/core/classes/parser/operations/add.d.ts +15 -0
  185. package/output/core/classes/parser/operations/add.js +236 -0
  186. package/output/core/classes/parser/operations/comma.d.ts +7 -0
  187. package/output/core/classes/parser/operations/comma.js +11 -0
  188. package/output/core/classes/parser/operations/compare.d.ts +21 -0
  189. package/output/core/classes/parser/operations/compare.js +474 -0
  190. package/output/core/classes/parser/operations/divide.d.ts +2 -0
  191. package/output/core/classes/parser/operations/divide.js +72 -0
  192. package/output/core/classes/parser/operations/functions.d.ts +46 -0
  193. package/output/core/classes/parser/operations/functions.js +438 -0
  194. package/output/core/classes/parser/operations/multiply.d.ts +11 -0
  195. package/output/core/classes/parser/operations/multiply.js +328 -0
  196. package/output/core/classes/parser/operations/power.d.ts +48 -0
  197. package/output/core/classes/parser/operations/power.js +673 -0
  198. package/output/core/classes/parser/operations/subtract.d.ts +3 -0
  199. package/output/core/classes/parser/operations/subtract.js +36 -0
  200. package/output/core/classes/parser/preprocess.d.ts +7 -0
  201. package/output/core/classes/parser/preprocess.js +246 -0
  202. package/output/core/classes/parser/scripting/controlFlow.d.ts +23 -0
  203. package/output/core/classes/parser/scripting/controlFlow.js +279 -0
  204. package/output/core/classes/parser/scripting/deferred.d.ts +4 -0
  205. package/output/core/classes/parser/scripting/deferred.js +65 -0
  206. package/output/core/classes/parser/scripting/dispatch.d.ts +1 -0
  207. package/output/core/classes/parser/scripting/dispatch.js +62 -0
  208. package/output/core/classes/parser/scripting/evaluate.d.ts +23 -0
  209. package/output/core/classes/parser/scripting/evaluate.js +128 -0
  210. package/output/core/classes/parser/scripting/functions.d.ts +14 -0
  211. package/output/core/classes/parser/scripting/functions.js +59 -0
  212. package/output/core/classes/parser/scripting/scope.d.ts +8 -0
  213. package/output/core/classes/parser/scripting/scope.js +132 -0
  214. package/output/core/classes/parser/types.d.ts +130 -0
  215. package/output/core/classes/parser/types.js +2 -0
  216. package/output/core/classes/parser/wrappers/IndexedReference.d.ts +31 -0
  217. package/output/core/classes/parser/wrappers/IndexedReference.js +68 -0
  218. package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +24 -0
  219. package/output/core/classes/parser/wrappers/KeyValuePair.js +51 -0
  220. package/output/core/classes/polynomial/Polynomial.d.ts +504 -0
  221. package/output/core/classes/polynomial/Polynomial.js +1195 -0
  222. package/output/core/classes/polynomial/SparsePolynomial.d.ts +221 -0
  223. package/output/core/classes/polynomial/SparsePolynomial.js +824 -0
  224. package/output/core/classes/polynomial/SparsePolynomialAdapter.d.ts +56 -0
  225. package/output/core/classes/polynomial/SparsePolynomialAdapter.js +241 -0
  226. package/output/core/classes/polynomial/Term.d.ts +222 -0
  227. package/output/core/classes/polynomial/Term.js +430 -0
  228. package/output/core/classes/polynomial/adapters.d.ts +18 -0
  229. package/output/core/classes/polynomial/adapters.js +33 -0
  230. package/output/core/classes/polynomial/dispatch.d.ts +1 -0
  231. package/output/core/classes/polynomial/dispatch.js +14 -0
  232. package/output/core/classes/polynomial/functions.d.ts +77 -0
  233. package/output/core/classes/polynomial/functions.js +189 -0
  234. package/output/core/classes/polynomial/utils.d.ts +62 -0
  235. package/output/core/classes/polynomial/utils.js +207 -0
  236. package/output/core/classes/rational/Rational.d.ts +501 -0
  237. package/output/core/classes/rational/Rational.js +829 -0
  238. package/output/core/classes/seq/SEQ.d.ts +13 -0
  239. package/output/core/classes/seq/SEQ.js +137 -0
  240. package/output/core/classes/valuesSet/ValuesSet.d.ts +187 -0
  241. package/output/core/classes/valuesSet/ValuesSet.js +399 -0
  242. package/output/core/classes/vector/Vector.d.ts +222 -0
  243. package/output/core/classes/vector/Vector.js +501 -0
  244. package/output/core/classes/vector/dispatch.d.ts +1 -0
  245. package/output/core/classes/vector/dispatch.js +11 -0
  246. package/output/core/classes/vector/functions.d.ts +28 -0
  247. package/output/core/classes/vector/functions.js +47 -0
  248. package/output/core/common/classes/MathematicalAggregate.d.ts +53 -0
  249. package/output/core/common/classes/MathematicalAggregate.js +149 -0
  250. package/output/core/common/classes/Scope.d.ts +62 -0
  251. package/output/core/common/classes/Scope.js +122 -0
  252. package/output/core/common/classes/StructuredEntity.d.ts +55 -0
  253. package/output/core/common/classes/StructuredEntity.js +151 -0
  254. package/output/core/common/common.d.ts +62 -0
  255. package/output/core/common/common.js +74 -0
  256. package/output/core/common/functions/functions.d.ts +14 -0
  257. package/output/core/common/functions/functions.js +33 -0
  258. package/output/core/common/functions/structuredEntityUtils.d.ts +27 -0
  259. package/output/core/common/functions/structuredEntityUtils.js +40 -0
  260. package/output/core/converters/BaseConverter.d.ts +97 -0
  261. package/output/core/converters/BaseConverter.js +405 -0
  262. package/output/core/converters/Converter.d.ts +111 -0
  263. package/output/core/converters/Converter.js +806 -0
  264. package/output/core/converters/Pattern.d.ts +71 -0
  265. package/output/core/converters/Pattern.js +302 -0
  266. package/output/core/dispatch.d.ts +52 -0
  267. package/output/core/dispatch.js +26 -0
  268. package/output/core/errors.d.ts +316 -0
  269. package/output/core/errors.js +349 -0
  270. package/output/core/fullFunctions.d.ts +7 -0
  271. package/output/core/fullFunctions.js +31 -0
  272. package/output/core/functions/bigint/bigint.d.ts +133 -0
  273. package/output/core/functions/bigint/bigint.js +444 -0
  274. package/output/core/functions/bigint/primeFactor.d.ts +51 -0
  275. package/output/core/functions/bigint/primeFactor.js +267 -0
  276. package/output/core/functions/bigint/primes.d.ts +1 -0
  277. package/output/core/functions/bigint/primes.js +11 -0
  278. package/output/core/functions/build/definitions.d.ts +12 -0
  279. package/output/core/functions/build/definitions.js +139 -0
  280. package/output/core/functions/build/index.d.ts +32 -0
  281. package/output/core/functions/build/index.js +136 -0
  282. package/output/core/functions/complex.d.ts +90 -0
  283. package/output/core/functions/complex.dispatch.d.ts +1 -0
  284. package/output/core/functions/complex.dispatch.js +16 -0
  285. package/output/core/functions/complex.js +482 -0
  286. package/output/core/functions/decimal.d.ts +24 -0
  287. package/output/core/functions/decimal.js +665 -0
  288. package/output/core/functions/expand/expand.d.ts +42 -0
  289. package/output/core/functions/expand/expand.js +376 -0
  290. package/output/core/functions/fresnelNumeric.d.ts +12 -0
  291. package/output/core/functions/fresnelNumeric.js +123 -0
  292. package/output/core/functions/numeric.d.ts +140 -0
  293. package/output/core/functions/numeric.js +790 -0
  294. package/output/core/functions/rationalNormalization.d.ts +11 -0
  295. package/output/core/functions/rationalNormalization.js +117 -0
  296. package/output/core/functions/setFunction.d.ts +19 -0
  297. package/output/core/functions/setFunction.js +75 -0
  298. package/output/core/functions/string.d.ts +26 -0
  299. package/output/core/functions/string.js +102 -0
  300. package/output/core/functions/subst.d.ts +90 -0
  301. package/output/core/functions/subst.js +506 -0
  302. package/output/core/functions/utils.d.ts +24 -0
  303. package/output/core/functions/utils.js +51 -0
  304. package/output/core/parserFunctions.d.ts +7 -0
  305. package/output/core/parserFunctions.js +25 -0
  306. package/output/core/types.d.ts +48 -0
  307. package/output/core/types.js +2 -0
  308. package/output/index.d.ts +359 -0
  309. package/output/index.js +739 -0
  310. package/output/math/defint/defint.d.ts +18 -0
  311. package/output/math/defint/defint.js +60 -0
  312. package/output/math/defint/defintDecimal.d.ts +37 -0
  313. package/output/math/defint/defintDecimal.js +321 -0
  314. package/output/math/defint/defintNative.d.ts +57 -0
  315. package/output/math/defint/defintNative.js +281 -0
  316. package/output/math/dispatch.d.ts +1 -0
  317. package/output/math/dispatch.js +101 -0
  318. package/output/math/geometry.d.ts +12 -0
  319. package/output/math/geometry.js +55 -0
  320. package/output/math/math.d.ts +695 -0
  321. package/output/math/math.js +1955 -0
  322. package/output/math/trig.d.ts +518 -0
  323. package/output/math/trig.js +1444 -0
  324. package/output/math/trunc.d.ts +19 -0
  325. package/output/math/trunc.js +36 -0
  326. package/output/math/utils.d.ts +66 -0
  327. package/output/math/utils.js +219 -0
  328. package/output/solve/classes/DecimalMatrix.d.ts +17 -0
  329. package/output/solve/classes/DecimalMatrix.js +86 -0
  330. package/output/solve/classes/FunctionSolver.d.ts +135 -0
  331. package/output/solve/classes/FunctionSolver.js +433 -0
  332. package/output/solve/classes/MultivariateSolver.d.ts +84 -0
  333. package/output/solve/classes/MultivariateSolver.js +240 -0
  334. package/output/solve/classes/PolynomialSolver.d.ts +104 -0
  335. package/output/solve/classes/PolynomialSolver.js +492 -0
  336. package/output/solve/classes/SolutionSet.d.ts +172 -0
  337. package/output/solve/classes/SolutionSet.js +434 -0
  338. package/output/solve/classes/Solver.d.ts +17 -0
  339. package/output/solve/classes/Solver.js +132 -0
  340. package/output/solve/classes/SymbolicSolver.d.ts +74 -0
  341. package/output/solve/classes/SymbolicSolver.js +601 -0
  342. package/output/solve/dispatch.d.ts +1 -0
  343. package/output/solve/dispatch.js +13 -0
  344. package/output/solve/linsolve.d.ts +53 -0
  345. package/output/solve/linsolve.js +233 -0
  346. package/output/solve/solve.d.ts +44 -0
  347. package/output/solve/solve.js +368 -0
  348. package/output/solve/solveSystem.d.ts +31 -0
  349. package/output/solve/solveSystem.js +266 -0
  350. package/output/solve/utils.d.ts +10 -0
  351. package/output/solve/utils.js +58 -0
  352. package/output/utils/array.d.ts +42 -0
  353. package/output/utils/array.js +98 -0
  354. package/output/utils/debug.d.ts +131 -0
  355. package/output/utils/debug.js +296 -0
  356. package/output/utils/decimal.d.ts +3 -0
  357. package/output/utils/decimal.js +16 -0
  358. package/output/utils/numeric.d.ts +14 -0
  359. package/output/utils/numeric.js +51 -0
  360. package/output/utils/object.d.ts +26 -0
  361. package/output/utils/object.js +56 -0
  362. package/package.json +178 -57
  363. package/.travis.yml +0 -3
  364. package/Algebra.js +0 -4568
  365. package/CODE_OF_CONDUCT.md +0 -46
  366. package/CONTRIBUTING.md +0 -14
  367. package/Calculus.js +0 -2675
  368. package/Extra.js +0 -622
  369. package/Solve.js +0 -1783
  370. package/all.js +0 -16
  371. package/all.min.js +0 -1
  372. package/gulpfile.js +0 -16
  373. package/index.html +0 -158
  374. package/license.txt +0 -19
  375. package/nerdamer.core.js +0 -12510
  376. package/spec/LaTeX.spec.js +0 -302
  377. package/spec/TeXConvert.spec.js +0 -8
  378. package/spec/algebra.spec.js +0 -287
  379. package/spec/basic_parser.spec.js +0 -134
  380. package/spec/build.spec.js +0 -131
  381. package/spec/calculus.spec.js +0 -183
  382. package/spec/core.spec.js +0 -2970
  383. package/spec/extra.spec.js +0 -54
  384. package/spec/solve.spec.js +0 -126
  385. package/spec/support/jasmine.json +0 -11
  386. package/spec/support/utils.js +0 -42
  387. package/spec/text.spec.js +0 -132
@@ -0,0 +1,929 @@
1
+ "use strict";
2
+ /**
3
+ * @module groebner
4
+ *
5
+ * Gröbner basis computation, elimination, ideal membership, and solving.
6
+ *
7
+ * This implementation is a Buchberger-style engine with:
8
+ * - configurable monomial order (LEX, GRLEX, GREVLEX)
9
+ * - sugar-strategy pair selection for performance
10
+ * - optional budgets and stats
11
+ * - fraction-free normal form helpers
12
+ * - elimination ideals
13
+ * - ideal membership testing
14
+ * - triangular back-substitution solver
15
+ *
16
+ * External references consulted:
17
+ * - SymPy Gröbner basis implementation:
18
+ * https://github.com/sympy/sympy/blob/120ee85f346f6292b763cc195afda4f907260d4a/sympy/polys/groebnertools.py
19
+ * - Giovini, Mora, Niesi, Robbiano, Traverso, "One Sugar Cube, Please":
20
+ * https://doi.org/10.1145/120694.120701
21
+ * - Bigatti, Caboara, Robbiano, "Computing inhomogeneous Gröbner bases":
22
+ * https://doi.org/10.1016/j.jsc.2010.10.002
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.GroebnerBudgetExceeded = void 0;
26
+ exports.Groebner = Groebner;
27
+ exports.groebnerBasisWithOptions = groebnerBasisWithOptions;
28
+ exports.eliminate = eliminate;
29
+ exports.idealMembership = idealMembership;
30
+ exports.reduceByBasis = reduceByBasis;
31
+ exports.solve = solve;
32
+ const SparsePolynomial_1 = require("../../core/classes/polynomial/SparsePolynomial");
33
+ const errors_1 = require("../../core/errors");
34
+ const bigint_1 = require("../../core/functions/bigint/bigint");
35
+ /**
36
+ * Thrown when a Groebner pair-count or basis-size budget is exhausted.
37
+ *
38
+ * {@link GroebnerBudgetExceeded.stats} is the live counter snapshot from the aborted
39
+ * computation. The error keeps that object by reference and does not freeze it.
40
+ */
41
+ class GroebnerBudgetExceeded extends Error {
42
+ /** Work counters at the point the budget was exceeded. */
43
+ stats;
44
+ /**
45
+ * @param message - Human-readable budget condition.
46
+ * @param stats - Counter snapshot retained on the error.
47
+ */
48
+ constructor(message, stats) {
49
+ super(message);
50
+ this.name = 'GroebnerBudgetExceeded';
51
+ this.stats = stats;
52
+ }
53
+ }
54
+ exports.GroebnerBudgetExceeded = GroebnerBudgetExceeded;
55
+ function sparseOrder(order) {
56
+ if (order === 'LEX') {
57
+ return 'lex';
58
+ }
59
+ if (order === 'GRLEX') {
60
+ return 'grlex';
61
+ }
62
+ return 'grevlex';
63
+ }
64
+ function ltOrNull(p, order) {
65
+ const leading = p.leadingTerm(sparseOrder(order));
66
+ return leading === null ? null : { exp: leading.exponents, coeff: leading.coefficient };
67
+ }
68
+ function polyKey(p) {
69
+ const parts = p
70
+ .terms()
71
+ .map(term => `${term.exponents.join(',')}:${term.coefficient.toString()}`);
72
+ parts.sort();
73
+ return parts.join('|');
74
+ }
75
+ /**
76
+ * Primitive normalization under a given order:
77
+ * - divide by coefficient content
78
+ * - ensure leading coefficient under `order` is positive
79
+ * - make monic when exact integer division permits it
80
+ */
81
+ function primitiveNormalizeOrder(p0, order) {
82
+ if (p0.isZero()) {
83
+ return SparsePolynomial_1.SparsePolynomial.zero(p0.variableCount);
84
+ }
85
+ let p = p0.primitivePart().normalizeLeadingSign(sparseOrder(order));
86
+ const lt = ltOrNull(p, order);
87
+ if (lt && lt.coeff !== 0n && lt.coeff !== 1n) {
88
+ let exact = true;
89
+ for (const term of p.terms()) {
90
+ if (term.coefficient % lt.coeff !== 0n) {
91
+ exact = false;
92
+ break;
93
+ }
94
+ }
95
+ if (exact) {
96
+ p = p.divideByScalarExact(lt.coeff);
97
+ }
98
+ }
99
+ return p;
100
+ }
101
+ function expLcmDense(a, b) {
102
+ if (a.length !== b.length) {
103
+ throw new RangeError((0, errors_1.message)('multidegreeMismatch'));
104
+ }
105
+ const out = new Array(a.length);
106
+ for (let i = 0; i < a.length; i++) {
107
+ out[i] = a[i] > b[i] ? a[i] : b[i];
108
+ }
109
+ return out;
110
+ }
111
+ function monoDividesDense(a, b) {
112
+ if (a.length !== b.length) {
113
+ return false;
114
+ }
115
+ for (let i = 0; i < a.length; i++) {
116
+ if (a[i] > b[i]) {
117
+ return false;
118
+ }
119
+ }
120
+ return true;
121
+ }
122
+ function monoSubDense(b, a) {
123
+ if (a.length !== b.length) {
124
+ throw new RangeError((0, errors_1.message)('multidegreeMismatch'));
125
+ }
126
+ const out = new Array(a.length);
127
+ for (let i = 0; i < a.length; i++) {
128
+ out[i] = b[i] - a[i];
129
+ }
130
+ return out;
131
+ }
132
+ function monomialTotalDegreeDense(monomial) {
133
+ let degree = 0n;
134
+ for (const exponent of monomial) {
135
+ degree += exponent;
136
+ }
137
+ return degree;
138
+ }
139
+ // ============================================================================
140
+ // S-polynomial (fraction-free)
141
+ // ============================================================================
142
+ function sPolynomialFF(f, g, ltF, ltG) {
143
+ const lcm = expLcmDense(ltF.exp, ltG.exp);
144
+ const fMultiplier = monoSubDense(lcm, ltF.exp);
145
+ const gMultiplier = monoSubDense(lcm, ltG.exp);
146
+ return f.monomialScaleSubtract(ltG.coeff, fMultiplier, g, ltF.coeff, gMultiplier);
147
+ }
148
+ function reducerViews(basis, order, normalize) {
149
+ const reducers = [];
150
+ for (const source of basis) {
151
+ const poly = normalize ? primitiveNormalizeOrder(source, order) : source;
152
+ if (poly.isZero()) {
153
+ continue;
154
+ }
155
+ const lt = ltOrNull(poly, order);
156
+ if (lt !== null) {
157
+ reducers.push({ poly, lt });
158
+ }
159
+ }
160
+ return reducers;
161
+ }
162
+ /** Head reduction using leading terms only and exact integer arithmetic. */
163
+ function normalFormFractionFree(f0, basis, order, reducers = reducerViews(basis, order, false), sugarState) {
164
+ let f = f0;
165
+ if (f.isZero()) {
166
+ return f;
167
+ }
168
+ while (true) {
169
+ const ltF = ltOrNull(f, order);
170
+ if (!ltF) {
171
+ break;
172
+ }
173
+ let reduced = false;
174
+ for (let reducerIndex = 0; reducerIndex < reducers.length; reducerIndex++) {
175
+ const { poly: g, lt: ltG } = reducers[reducerIndex];
176
+ if (!monoDividesDense(ltG.exp, ltF.exp)) {
177
+ continue;
178
+ }
179
+ const multExp = monoSubDense(ltF.exp, ltG.exp);
180
+ if (sugarState) {
181
+ const reductionSugar = sugarState.reducerSugars[reducerIndex] + monomialTotalDegreeDense(multExp);
182
+ if (reductionSugar > sugarState.value) {
183
+ sugarState.value = reductionSugar;
184
+ }
185
+ }
186
+ f = f.scaleSubtractMonomial(ltG.coeff, g, ltF.coeff, multExp);
187
+ reduced = true;
188
+ break;
189
+ }
190
+ if (!reduced) {
191
+ break;
192
+ }
193
+ }
194
+ return f;
195
+ }
196
+ /**
197
+ * Fraction-free reduction allowing reduction of any term.
198
+ *
199
+ * For a term t in f and a reducer g whose leading monomial divides t:
200
+ * f := lc(g) * f - coeff(t) * x^(tExp - LM(g)) * g
201
+ */
202
+ function normalFormFractionFreeAllTerms(f0, basis, order, normalizedBasis = reducerViews(basis, order, true), sugarState) {
203
+ let f = primitiveNormalizeOrder(f0, order);
204
+ if (f.isZero() || normalizedBasis.length === 0) {
205
+ return f;
206
+ }
207
+ const monomialOrder = sparseOrder(order);
208
+ while (true) {
209
+ let selected = null;
210
+ let selectedReducer = null;
211
+ let selectedReducerIndex = -1;
212
+ for (const term of f.terms()) {
213
+ let reducer = null;
214
+ let reducerIndex = -1;
215
+ for (let i = 0; i < normalizedBasis.length; i++) {
216
+ const candidate = normalizedBasis[i];
217
+ if (monoDividesDense(candidate.lt.exp, term.exponents)) {
218
+ reducer = candidate;
219
+ reducerIndex = i;
220
+ break;
221
+ }
222
+ }
223
+ if (reducer !== null &&
224
+ (selected === null ||
225
+ SparsePolynomial_1.SparsePolynomial.compareMonomials(term.exponents, selected.exponents, monomialOrder) > 0)) {
226
+ selected = term;
227
+ selectedReducer = reducer;
228
+ selectedReducerIndex = reducerIndex;
229
+ }
230
+ }
231
+ if (selected === null || selectedReducer === null) {
232
+ break;
233
+ }
234
+ const multExp = monoSubDense(selected.exponents, selectedReducer.lt.exp);
235
+ if (sugarState) {
236
+ const reductionSugar = sugarState.reducerSugars[selectedReducerIndex] +
237
+ monomialTotalDegreeDense(multExp);
238
+ if (reductionSugar > sugarState.value) {
239
+ sugarState.value = reductionSugar;
240
+ }
241
+ }
242
+ f = primitiveNormalizeOrder(f.scaleSubtractMonomial(selectedReducer.lt.coeff, selectedReducer.poly, selected.coefficient, multExp), order);
243
+ }
244
+ return f;
245
+ }
246
+ // ============================================================================
247
+ // Canonicalization
248
+ // ============================================================================
249
+ function variablePresence(p) {
250
+ const presence = new Array(p.variableCount).fill(false);
251
+ for (const variableIndex of p.variables()) {
252
+ presence[variableIndex] = true;
253
+ }
254
+ return presence;
255
+ }
256
+ function canonicalizeBasis(inputBasis, order) {
257
+ const kept = [];
258
+ const keptHeadReducers = [];
259
+ const keptNormalizedReducers = [];
260
+ const input = inputBasis.filter(p => !p.isZero());
261
+ // 1) Reduce each element against what we've already kept, then normalize.
262
+ for (const p of input) {
263
+ const headReduced = normalFormFractionFree(p, kept, order, keptHeadReducers);
264
+ const normalized = normalFormFractionFreeAllTerms(headReduced, kept, order, keptNormalizedReducers);
265
+ if (!normalized.isZero()) {
266
+ kept.push(normalized);
267
+ keptHeadReducers.push(reducerViews([normalized], order, false)[0]);
268
+ keptNormalizedReducers.push(reducerViews([normalized], order, true)[0]);
269
+ }
270
+ }
271
+ // 2) Interreduce: each polynomial reduced by all others.
272
+ const out = [];
273
+ for (let i = 0; i < kept.length; i++) {
274
+ const others = kept.filter((_, j) => j !== i);
275
+ const otherHeadReducers = keptHeadReducers.filter((_, j) => j !== i);
276
+ const otherNormalizedReducers = keptNormalizedReducers.filter((_, j) => j !== i);
277
+ const headReduced = normalFormFractionFree(kept[i], others, order, otherHeadReducers);
278
+ const normalized = normalFormFractionFreeAllTerms(headReduced, others, order, otherNormalizedReducers);
279
+ if (!normalized.isZero()) {
280
+ out.push(normalized);
281
+ }
282
+ }
283
+ // 3) Remove exact duplicates produced by independent interreduction.
284
+ const byPoly = new Map();
285
+ for (const p of out) {
286
+ byPoly.set(polyKey(p), p);
287
+ }
288
+ const result = Array.from(byPoly.values());
289
+ const monomialOrder = sparseOrder(order);
290
+ const sortInfo = new Map();
291
+ for (const p of result) {
292
+ sortInfo.set(p, {
293
+ presence: variablePresence(p),
294
+ lt: ltOrNull(p, order),
295
+ });
296
+ }
297
+ result.sort((p, q) => {
298
+ const pInfo = sortInfo.get(p);
299
+ const qInfo = sortInfo.get(q);
300
+ for (let i = 0; i < p.variableCount; i++) {
301
+ const pv = pInfo.presence[i] ? 1 : 0;
302
+ const qv = qInfo.presence[i] ? 1 : 0;
303
+ if (pv !== qv) {
304
+ return pv - qv;
305
+ }
306
+ }
307
+ if (pInfo.lt && qInfo.lt) {
308
+ const comparison = SparsePolynomial_1.SparsePolynomial.compareMonomials(pInfo.lt.exp, qInfo.lt.exp, monomialOrder);
309
+ if (comparison !== 0) {
310
+ return comparison;
311
+ }
312
+ }
313
+ return p.termCount - q.termCount;
314
+ });
315
+ return result;
316
+ }
317
+ // ============================================================================
318
+ // Sugar strategy
319
+ // ============================================================================
320
+ /**
321
+ * Sugar degree of an S-polynomial S(f,g).
322
+ *
323
+ * sugar(S(f,g)) = max(sugar(f) + deg(lcm/LM(f)), sugar(g) + deg(lcm/LM(g)))
324
+ */
325
+ function sPairSugar(sugarF, sugarG, ltFDegree, ltGDegree, lcmDegree) {
326
+ const candidateF = sugarF + lcmDegree - ltFDegree;
327
+ const candidateG = sugarG + lcmDegree - ltGDegree;
328
+ return candidateF > candidateG ? candidateF : candidateG;
329
+ }
330
+ /**
331
+ * Inserts a pair in reverse processing order so the next pair can be removed with pop().
332
+ * Lower sugar and lower lcmDeg are processed first. Exact ties retain the previous
333
+ * last-in-first-out behavior.
334
+ */
335
+ function insertPairSorted(queue, pair) {
336
+ let lo = 0;
337
+ let hi = queue.length;
338
+ while (lo < hi) {
339
+ const mid = (lo + hi) >>> 1;
340
+ const current = queue[mid];
341
+ if (current.sugar > pair.sugar ||
342
+ (current.sugar === pair.sugar && current.lcmDeg >= pair.lcmDeg)) {
343
+ lo = mid + 1;
344
+ }
345
+ else {
346
+ hi = mid;
347
+ }
348
+ }
349
+ queue.splice(lo, 0, pair);
350
+ }
351
+ // ============================================================================
352
+ // Core Buchberger algorithm
353
+ // ============================================================================
354
+ function groebnerBasisSparse(polys, orderOrOpts = 'LEX') {
355
+ const opts = typeof orderOrOpts === 'string' ? { order: orderOrOpts } : (orderOrOpts ?? {});
356
+ const order = opts.order ?? 'LEX';
357
+ const reduced = opts.reduced ?? true;
358
+ const maxPairsPopped = opts.maxPairsPopped;
359
+ const maxBasisSize = opts.maxBasisSize;
360
+ const strategy = opts.strategy ?? 'sugar';
361
+ const stats = {
362
+ pairsPopped: 0,
363
+ pairsSkippedProduct: 0,
364
+ pairsSkippedChain: 0,
365
+ pairsReducedToZero: 0,
366
+ basisAppends: 0,
367
+ };
368
+ const basisInput = polys.filter(p => !p.isZero());
369
+ if (basisInput.length === 0) {
370
+ return [];
371
+ }
372
+ const variableCount = basisInput[0].variableCount;
373
+ for (const polynomial of basisInput) {
374
+ if (polynomial.variableCount !== variableCount) {
375
+ throw new RangeError((0, errors_1.message)('multidegreeMismatch'));
376
+ }
377
+ }
378
+ const basis = basisInput.slice();
379
+ const headReducers = reducerViews(basis, order, false);
380
+ const normalizedReducers = reducerViews(basis, order, true);
381
+ const lmDegreeCache = headReducers.map(reducer => monomialTotalDegreeDense(reducer.lt.exp));
382
+ const sugarArr = basis.map(polynomial => polynomial.totalDegree() ?? 0n);
383
+ const zeroPairNeighbors = basis.map(() => new Set());
384
+ const markZeroPair = (i, j) => {
385
+ zeroPairNeighbors[i].add(j);
386
+ zeroPairNeighbors[j].add(i);
387
+ };
388
+ const areCoprimeLM = (a, b) => {
389
+ for (let i = 0; i < variableCount; i++) {
390
+ if (a[i] > 0n && b[i] > 0n) {
391
+ return false;
392
+ }
393
+ }
394
+ return true;
395
+ };
396
+ const chainCriterionApplies = (i, j) => {
397
+ const li = headReducers[i].lt.exp;
398
+ const lj = headReducers[j].lt.exp;
399
+ const lcm = expLcmDense(li, lj);
400
+ const iNeighbors = zeroPairNeighbors[i];
401
+ const jNeighbors = zeroPairNeighbors[j];
402
+ const candidates = iNeighbors.size <= jNeighbors.size ? iNeighbors : jNeighbors;
403
+ const otherNeighbors = candidates === iNeighbors ? jNeighbors : iNeighbors;
404
+ for (const k of candidates) {
405
+ if (k !== i &&
406
+ k !== j &&
407
+ otherNeighbors.has(k) &&
408
+ monoDividesDense(headReducers[k].lt.exp, lcm)) {
409
+ return true;
410
+ }
411
+ }
412
+ return false;
413
+ };
414
+ const appendBasis = (h) => {
415
+ const index = basis.length;
416
+ basis.push(h);
417
+ const headReducer = reducerViews([h], order, false)[0];
418
+ const normalizedReducer = reducerViews([h], order, true)[0];
419
+ headReducers.push(headReducer);
420
+ normalizedReducers.push(normalizedReducer);
421
+ lmDegreeCache.push(monomialTotalDegreeDense(headReducer.lt.exp));
422
+ zeroPairNeighbors.push(new Set());
423
+ stats.basisAppends++;
424
+ if (maxBasisSize !== undefined && basis.length > maxBasisSize) {
425
+ throw new GroebnerBudgetExceeded((0, errors_1.message)('groebnerBasisSizeBudgetExceeded', { max: String(maxBasisSize) }), stats);
426
+ }
427
+ return index;
428
+ };
429
+ const reducePair = (i, j, initialSugar) => {
430
+ const sPolynomial = sPolynomialFF(basis[i], basis[j], headReducers[i].lt, headReducers[j].lt);
431
+ const sugarState = initialSugar === undefined
432
+ ? undefined
433
+ : { value: initialSugar, reducerSugars: sugarArr };
434
+ const headReduced = normalFormFractionFree(sPolynomial, basis, order, headReducers, sugarState);
435
+ const polynomial = normalFormFractionFreeAllTerms(headReduced, basis, order, normalizedReducers, sugarState);
436
+ return { polynomial, sugar: sugarState?.value };
437
+ };
438
+ // Build initial pair queue.
439
+ if (strategy === 'sugar') {
440
+ const pairQueue = [];
441
+ const makePair = (i, j) => {
442
+ const li = headReducers[i].lt.exp;
443
+ const lj = headReducers[j].lt.exp;
444
+ const lcm = expLcmDense(li, lj);
445
+ const lcmDegree = monomialTotalDegreeDense(lcm);
446
+ return {
447
+ i,
448
+ j,
449
+ sugar: sPairSugar(sugarArr[i], sugarArr[j], lmDegreeCache[i], lmDegreeCache[j], lcmDegree),
450
+ lcmDeg: lcmDegree,
451
+ };
452
+ };
453
+ for (let i = 0; i < basis.length; i++) {
454
+ for (let j = i + 1; j < basis.length; j++) {
455
+ insertPairSorted(pairQueue, makePair(i, j));
456
+ }
457
+ }
458
+ while (pairQueue.length > 0) {
459
+ const { i, j, sugar: pairSugar } = pairQueue.pop();
460
+ stats.pairsPopped++;
461
+ if (maxPairsPopped !== undefined && stats.pairsPopped > maxPairsPopped) {
462
+ throw new GroebnerBudgetExceeded((0, errors_1.message)('groebnerPairsBudgetExceeded', { max: String(maxPairsPopped) }), stats);
463
+ }
464
+ const lmi = headReducers[i].lt.exp;
465
+ const lmj = headReducers[j].lt.exp;
466
+ if (areCoprimeLM(lmi, lmj)) {
467
+ stats.pairsSkippedProduct++;
468
+ markZeroPair(i, j);
469
+ continue;
470
+ }
471
+ if (chainCriterionApplies(i, j)) {
472
+ stats.pairsSkippedChain++;
473
+ markZeroPair(i, j);
474
+ continue;
475
+ }
476
+ const reduction = reducePair(i, j, pairSugar);
477
+ const h = reduction.polynomial;
478
+ if (h.isZero()) {
479
+ stats.pairsReducedToZero++;
480
+ markZeroPair(i, j);
481
+ continue;
482
+ }
483
+ if (h.isConstant() && h.constantTerm() !== 0n) {
484
+ return [SparsePolynomial_1.SparsePolynomial.constant(variableCount, 1n)];
485
+ }
486
+ const k = appendBasis(h);
487
+ const hTotalDegree = h.totalDegree() ?? 0n;
488
+ const reducedSugar = reduction.sugar ?? pairSugar;
489
+ sugarArr.push(reducedSugar > hTotalDegree ? reducedSugar : hTotalDegree);
490
+ for (let t = 0; t < k; t++) {
491
+ insertPairSorted(pairQueue, makePair(t, k));
492
+ }
493
+ }
494
+ }
495
+ else {
496
+ // FIFO strategy.
497
+ const pairs = [];
498
+ for (let i = 0; i < basis.length; i++) {
499
+ for (let j = i + 1; j < basis.length; j++) {
500
+ pairs.push([i, j]);
501
+ }
502
+ }
503
+ let pairIndex = 0;
504
+ while (pairIndex < pairs.length) {
505
+ const [i, j] = pairs[pairIndex++];
506
+ stats.pairsPopped++;
507
+ if (maxPairsPopped !== undefined && stats.pairsPopped > maxPairsPopped) {
508
+ throw new GroebnerBudgetExceeded((0, errors_1.message)('groebnerPairsBudgetExceeded', { max: String(maxPairsPopped) }), stats);
509
+ }
510
+ const lmi = headReducers[i].lt.exp;
511
+ const lmj = headReducers[j].lt.exp;
512
+ if (areCoprimeLM(lmi, lmj)) {
513
+ stats.pairsSkippedProduct++;
514
+ markZeroPair(i, j);
515
+ continue;
516
+ }
517
+ if (chainCriterionApplies(i, j)) {
518
+ stats.pairsSkippedChain++;
519
+ markZeroPair(i, j);
520
+ continue;
521
+ }
522
+ const h = reducePair(i, j).polynomial;
523
+ if (h.isZero()) {
524
+ stats.pairsReducedToZero++;
525
+ markZeroPair(i, j);
526
+ continue;
527
+ }
528
+ if (h.isConstant() && h.constantTerm() !== 0n) {
529
+ return [SparsePolynomial_1.SparsePolynomial.constant(variableCount, 1n)];
530
+ }
531
+ const k = appendBasis(h);
532
+ for (let t = 0; t < k; t++) {
533
+ pairs.push([t, k]);
534
+ }
535
+ }
536
+ }
537
+ return reduced ? canonicalizeBasis(basis, order) : basis;
538
+ }
539
+ function reduceSparseByBasis(f, basis, order) {
540
+ if (f.isZero() || basis.length === 0) {
541
+ return f;
542
+ }
543
+ const headReducers = reducerViews(basis, order, false);
544
+ const normalizedReducers = reducerViews(basis, order, true);
545
+ const headReduced = normalFormFractionFree(f, basis, order, headReducers);
546
+ return normalFormFractionFreeAllTerms(headReduced, basis, order, normalizedReducers);
547
+ }
548
+ // ============================================================================
549
+ // Public API: Groebner basis
550
+ // ============================================================================
551
+ /**
552
+ * Computes a Groebner basis for exact sparse integer polynomials.
553
+ *
554
+ * The input polynomials must belong to the same ring. With `reduced: true`, the
555
+ * basis is interreduced, coefficient content is removed, leading signs are normalized,
556
+ * and exact monic normalization is applied when possible. Results are sorted
557
+ * deterministically and the supplied polynomials are not modified.
558
+ *
559
+ * @param polys - Ideal generators in one sparse polynomial ring.
560
+ * @param order - Monomial order; defaults to `LEX`.
561
+ * @param reduced - Return the normalized/interreduced basis; defaults to `true`.
562
+ * @returns New sparse basis polynomials in deterministic presentation order.
563
+ */
564
+ function Groebner(polys, order = 'LEX', reduced = true) {
565
+ if (polys.length === 0) {
566
+ return [];
567
+ }
568
+ const basis = groebnerBasisSparse(polys, { order, reduced });
569
+ const variableCount = basis[0]?.variableCount ?? polys[0].variableCount;
570
+ const cache = new Map();
571
+ const getInfo = (p) => {
572
+ let info = cache.get(p);
573
+ if (!info) {
574
+ info = { pv: variablePresence(p), lt: ltOrNull(p, order) };
575
+ cache.set(p, info);
576
+ }
577
+ return info;
578
+ };
579
+ return [...basis].sort((p, q) => {
580
+ const pInfo = getInfo(p);
581
+ const qInfo = getInfo(q);
582
+ for (let i = 0; i < variableCount; i++) {
583
+ const pv = pInfo.pv[i] ? 1 : 0;
584
+ const qv = qInfo.pv[i] ? 1 : 0;
585
+ if (pv !== qv) {
586
+ return pv > qv ? -1 : 1;
587
+ }
588
+ }
589
+ if (pInfo.lt && qInfo.lt) {
590
+ const comparison = SparsePolynomial_1.SparsePolynomial.compareMonomials(pInfo.lt.exp, qInfo.lt.exp, sparseOrder(order));
591
+ if (comparison !== 0) {
592
+ return comparison;
593
+ }
594
+ }
595
+ return p.termCount - q.termCount;
596
+ });
597
+ }
598
+ /**
599
+ * Computes a Groebner basis with ordering, strategy, and budget control.
600
+ *
601
+ * @param polys - Exact sparse integer-coefficient generators in one ring.
602
+ * @param opts - Ordering, normalization, pair-selection, and deterministic budget options.
603
+ * @returns New basis polynomials. Work statistics are exposed only when a budget is
604
+ * exceeded; successful calls return the basis itself.
605
+ * @throws {@link GroebnerBudgetExceeded} Thrown after a configured pair-count or
606
+ * basis-size limit is exceeded.
607
+ */
608
+ function groebnerBasisWithOptions(polys, opts) {
609
+ return groebnerBasisSparse(polys, opts);
610
+ }
611
+ // ============================================================================
612
+ // Elimination
613
+ // ============================================================================
614
+ /**
615
+ * Computes the part of the ideal that lies in the polynomial ring generated by `keepVars`.
616
+ *
617
+ * @param polys - Exact integer-coefficient generators.
618
+ * @param vars - All variables in exponent-index order. Variables to eliminate must
619
+ * precede retained variables for lexicographic elimination.
620
+ * @param keepVars - Variables to retain, expected to be a suffix of `vars`.
621
+ * @param opts - Reduction, pair strategy, and budgets; order is always `LEX`.
622
+ * @returns New basis polynomials involving only retained variables.
623
+ * @throws {@link GroebnerBudgetExceeded} Thrown when a configured budget is exceeded.
624
+ */
625
+ function eliminate(polys, vars, keepVars, opts) {
626
+ if (polys.length === 0) {
627
+ return [];
628
+ }
629
+ // Determine which variable indices to eliminate.
630
+ const keepSet = new Set(keepVars);
631
+ const eliminateIndices = new Set();
632
+ for (let i = 0; i < vars.length; i++) {
633
+ if (!keepSet.has(vars[i])) {
634
+ eliminateIndices.add(i);
635
+ }
636
+ }
637
+ for (const polynomial of polys) {
638
+ for (const variableIndex of polynomial.variables()) {
639
+ if (variableIndex >= vars.length) {
640
+ throw new RangeError((0, errors_1.message)('multidegreeMismatch'));
641
+ }
642
+ }
643
+ }
644
+ // Compute a LEX basis with variables to eliminate first in the supplied order.
645
+ const basis = groebnerBasisSparse(polys, { ...opts, order: 'LEX', reduced: true });
646
+ const result = basis.filter(poly => {
647
+ const presence = variablePresence(poly);
648
+ for (const variableIndex of eliminateIndices) {
649
+ if (presence[variableIndex]) {
650
+ return false;
651
+ }
652
+ }
653
+ return true;
654
+ });
655
+ return result;
656
+ }
657
+ // ============================================================================
658
+ // Ideal membership
659
+ // ============================================================================
660
+ /**
661
+ * Tests exact ideal membership by reducing against a computed Groebner basis.
662
+ *
663
+ * @param f - Polynomial to test.
664
+ * @param polys - Exact integer-coefficient ideal generators.
665
+ * @param order - Monomial order; defaults to `LEX`.
666
+ * @param opts - Pair strategy and deterministic budgets.
667
+ * @returns Whether the normal form of `f` is zero.
668
+ * @throws {@link GroebnerBudgetExceeded} Thrown when basis computation exceeds a budget.
669
+ */
670
+ function idealMembership(f, polys, order = 'LEX', opts) {
671
+ if (f.isZero()) {
672
+ return true;
673
+ }
674
+ if (polys.length === 0) {
675
+ return false;
676
+ }
677
+ const basis = groebnerBasisSparse(polys, { ...opts, order, reduced: true });
678
+ return reduceSparseByBasis(f, basis, order).isZero();
679
+ }
680
+ /**
681
+ * Reduces a polynomial by a basis or arbitrary reducer set using fraction-free arithmetic.
682
+ *
683
+ * @remarks
684
+ * This does not compute or verify a Groebner basis. The result is a canonical ideal
685
+ * normal form only when `basis` is already a basis for the selected order.
686
+ *
687
+ * @param f - Polynomial to reduce.
688
+ * @param basis - Reducers, normally a Groebner basis.
689
+ * @param order - Monomial order used to select leading terms.
690
+ * @returns The primitive-normalized remainder.
691
+ */
692
+ function reduceByBasis(f, basis, order = 'LEX') {
693
+ return f.isZero() || basis.length === 0 ? f : reduceSparseByBasis(f, basis, order);
694
+ }
695
+ /**
696
+ * Solves a zero-dimensional polynomial system for rational coordinates.
697
+ *
698
+ * @remarks
699
+ * This is the low-level exact solver used with the Groebner representation, not the
700
+ * ordinary expression solver. It computes a reduced lexicographic basis, walks variables
701
+ * from least to most significant, applies the Rational Root Theorem to univariate
702
+ * constraints, and substitutes each partial assignment into its own basis copy.
703
+ * Irrational and complex roots are outside this routine's result set.
704
+ *
705
+ * @param polys - Exact integer-coefficient system generators.
706
+ * @param vars - Variables in lexicographic elimination order, most significant first.
707
+ * @param opts - Pair strategy and budgets forwarded to basis computation.
708
+ * @returns New solution maps. An empty array can mean inconsistency, no rational roots,
709
+ * or a non-finite/unsupported triangular result; these cases are not distinguished.
710
+ * @throws {@link GroebnerBudgetExceeded} Thrown when basis computation exceeds a budget.
711
+ */
712
+ function solve(polys, vars, opts) {
713
+ if (polys.length === 0 || vars.length === 0) {
714
+ return [new Map()];
715
+ }
716
+ for (const polynomial of polys) {
717
+ for (const variableIndex of polynomial.variables()) {
718
+ if (variableIndex >= vars.length) {
719
+ throw new RangeError((0, errors_1.message)('multidegreeMismatch'));
720
+ }
721
+ }
722
+ }
723
+ const basis = groebnerBasisSparse(polys, { ...opts, order: 'LEX', reduced: true });
724
+ // Trivial: if the basis is {1}, the system is inconsistent.
725
+ if (basis.length === 1 && basis[0].isConstant() && basis[0].constantTerm() !== 0n) {
726
+ return [];
727
+ }
728
+ if (basis.length === 0) {
729
+ // Ideal is {0}, meaning every point is a solution — infinite solutions.
730
+ return [];
731
+ }
732
+ return backSubstitute(basis, vars);
733
+ }
734
+ /**
735
+ * Triangular back-substitution on a LEX Gröbner basis.
736
+ *
737
+ * Walks variables from last (least significant) to first, finding univariate
738
+ * polynomials, extracting rational roots, and substituting back.
739
+ *
740
+ * Each partial solution carries its own partially-substituted copy of the basis,
741
+ * so when we extend with a new variable binding we only need to substitute that
742
+ * one new value — not redo all prior substitutions.
743
+ */
744
+ function backSubstitute(basis, vars) {
745
+ let partials = [
746
+ {
747
+ assignment: new Map(),
748
+ basis: [...basis],
749
+ },
750
+ ];
751
+ for (let variableIndex = vars.length - 1; variableIndex >= 0; variableIndex--) {
752
+ const nextPartials = [];
753
+ for (const { assignment, basis: partialBasis } of partials) {
754
+ const univariates = partialBasis.filter(poly => {
755
+ if (poly.isZero()) {
756
+ return false;
757
+ }
758
+ const variables = poly.variables();
759
+ if (variables.some(index => index !== variableIndex)) {
760
+ return false;
761
+ }
762
+ const degree = poly.degree(variableIndex);
763
+ return degree !== null && degree > 0n;
764
+ });
765
+ if (univariates.length === 0) {
766
+ // No constraint on this variable — push forward as-is.
767
+ nextPartials.push({
768
+ assignment: new Map(assignment),
769
+ basis: partialBasis,
770
+ });
771
+ continue;
772
+ }
773
+ const roots = rationalRootsUnivariate(univariates[0], variableIndex);
774
+ for (const root of roots) {
775
+ let consistent = true;
776
+ for (let polynomialIndex = 1; polynomialIndex < univariates.length; polynomialIndex++) {
777
+ if (!evaluatesToZero(univariates[polynomialIndex], variableIndex, root)) {
778
+ consistent = false;
779
+ break;
780
+ }
781
+ }
782
+ if (!consistent) {
783
+ continue;
784
+ }
785
+ const nextBasis = partialBasis.map(poly => {
786
+ const degree = poly.degree(variableIndex);
787
+ if (degree === null || degree === 0n) {
788
+ return poly;
789
+ }
790
+ const scaled = root.d === 1n ? poly : scaleByDenomPow(poly, variableIndex, root.d);
791
+ return scaled.evaluateVariable(variableIndex, root.n);
792
+ });
793
+ const extended = new Map(assignment);
794
+ extended.set(variableIndex, root);
795
+ nextPartials.push({ assignment: extended, basis: nextBasis });
796
+ }
797
+ }
798
+ partials = nextPartials;
799
+ }
800
+ return partials.map(({ assignment }) => {
801
+ const named = new Map();
802
+ for (const [variableIndex, value] of assignment) {
803
+ if (variableIndex < vars.length) {
804
+ named.set(vars[variableIndex], value);
805
+ }
806
+ }
807
+ return named;
808
+ });
809
+ }
810
+ /**
811
+ * Scales a polynomial before integer substitution of a rational value n/d.
812
+ *
813
+ * For each term containing x_v^k, the coefficient is multiplied by
814
+ * d^(maxDegree-k), so evaluating x_v at n gives p(n/d) * d^maxDegree.
815
+ */
816
+ function scaleByDenomPow(poly, variableIndex, denominator) {
817
+ const maxDegree = poly.degree(variableIndex);
818
+ if (maxDegree === null || maxDegree === 0n || denominator === 1n) {
819
+ return poly;
820
+ }
821
+ return new SparsePolynomial_1.SparsePolynomial(poly.variableCount, poly.terms().map(term => ({
822
+ coefficient: term.coefficient *
823
+ denominator ** (maxDegree - term.exponents[variableIndex]),
824
+ exponents: term.exponents,
825
+ })));
826
+ }
827
+ /**
828
+ * Finds all rational roots p/q of a univariate polynomial.
829
+ *
830
+ * Uses the Rational Root Theorem: p divides the constant term and q divides the
831
+ * leading coefficient. Polynomial degree and term exponents remain bigint values.
832
+ */
833
+ function rationalRootsUnivariate(poly, variableIndex) {
834
+ const degree = poly.degree(variableIndex);
835
+ if (degree === null || degree === 0n) {
836
+ return [];
837
+ }
838
+ const leadingCoefficient = poly.coefficientIn(variableIndex, degree).constantTerm();
839
+ const constantTerm = poly.constantTerm();
840
+ if (constantTerm === 0n) {
841
+ const roots = [{ n: 0n, d: 1n }];
842
+ let commonPower = degree;
843
+ for (const term of poly.terms()) {
844
+ if (term.exponents[variableIndex] < commonPower) {
845
+ commonPower = term.exponents[variableIndex];
846
+ }
847
+ }
848
+ const shifted = new SparsePolynomial_1.SparsePolynomial(poly.variableCount, poly.terms().map(term => {
849
+ const exponents = [...term.exponents];
850
+ exponents[variableIndex] -= commonPower;
851
+ return { coefficient: term.coefficient, exponents };
852
+ }));
853
+ for (const root of rationalRootsUnivariate(shifted, variableIndex)) {
854
+ if (root.n !== 0n) {
855
+ roots.push(root);
856
+ }
857
+ }
858
+ return roots;
859
+ }
860
+ const numeratorDivisors = positiveDivisors((0, bigint_1.abs)(constantTerm));
861
+ const denominatorDivisors = positiveDivisors((0, bigint_1.abs)(leadingCoefficient));
862
+ const roots = [];
863
+ const seen = new Set();
864
+ for (const numeratorFactor of numeratorDivisors) {
865
+ for (const denominatorFactor of denominatorDivisors) {
866
+ for (const sign of [1n, -1n]) {
867
+ const numerator = sign * numeratorFactor;
868
+ const divisor = (0, bigint_1.GCD)((0, bigint_1.abs)(numerator), denominatorFactor);
869
+ const reducedNumerator = numerator / divisor;
870
+ const reducedDenominator = denominatorFactor / divisor;
871
+ const key = `${reducedNumerator}/${reducedDenominator}`;
872
+ if (seen.has(key)) {
873
+ continue;
874
+ }
875
+ seen.add(key);
876
+ if (evaluatesAtRationalToZero(poly, variableIndex, degree, reducedNumerator, reducedDenominator)) {
877
+ roots.push({ n: reducedNumerator, d: reducedDenominator });
878
+ }
879
+ }
880
+ }
881
+ }
882
+ return roots;
883
+ }
884
+ /**
885
+ * Evaluates a univariate polynomial at n/d after clearing d^degree.
886
+ */
887
+ function evaluatesAtRationalToZero(poly, variableIndex, degree, numerator, denominator) {
888
+ let result = 0n;
889
+ for (const term of poly.terms()) {
890
+ const exponent = term.exponents[variableIndex];
891
+ result +=
892
+ term.coefficient *
893
+ numerator ** exponent *
894
+ denominator ** (degree - exponent);
895
+ }
896
+ return result === 0n;
897
+ }
898
+ /** Checks whether substituting one rational value makes a univariate polynomial zero. */
899
+ function evaluatesToZero(poly, variableIndex, value) {
900
+ const degree = poly.degree(variableIndex);
901
+ if (degree === null) {
902
+ return true;
903
+ }
904
+ if (degree === 0n) {
905
+ return poly.constantTerm() === 0n;
906
+ }
907
+ return evaluatesAtRationalToZero(poly, variableIndex, degree, value.n, value.d);
908
+ }
909
+ /** Positive divisors of a positive bigint. */
910
+ function positiveDivisors(n) {
911
+ if (n === 0n) {
912
+ return [0n];
913
+ }
914
+ if (n < 0n) {
915
+ n = -n;
916
+ }
917
+ const divisors = [];
918
+ let candidate = 1n;
919
+ while (candidate * candidate <= n) {
920
+ if (n % candidate === 0n) {
921
+ divisors.push(candidate);
922
+ if (candidate !== n / candidate) {
923
+ divisors.push(n / candidate);
924
+ }
925
+ }
926
+ candidate++;
927
+ }
928
+ return divisors;
929
+ }