pimath 0.0.127 → 0.0.129

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 (212) hide show
  1. package/dist/main.d.ts +39 -0
  2. package/{esm → dist}/maths/algebra/equation.d.ts +11 -10
  3. package/{esm → dist}/maths/algebra/linearSystem.d.ts +5 -4
  4. package/{esm → dist}/maths/algebra/monom.d.ts +5 -4
  5. package/{esm → dist}/maths/algebra/polynom.d.ts +11 -13
  6. package/{esm → dist}/maths/algebra/rational.d.ts +7 -9
  7. package/dist/maths/algebra/study/rationalStudy.d.ts +14 -0
  8. package/{esm → dist}/maths/algebra/study.d.ts +4 -7
  9. package/{esm → dist}/maths/geometry/circle.d.ts +9 -8
  10. package/{esm → dist}/maths/geometry/line.d.ts +17 -14
  11. package/{esm → dist}/maths/geometry/point.d.ts +11 -9
  12. package/{esm → dist}/maths/geometry/triangle.d.ts +4 -3
  13. package/{esm → dist}/maths/geometry/vector.d.ts +7 -10
  14. package/{esm → dist}/maths/randomization/random.d.ts +10 -7
  15. package/{esm → dist}/maths/randomization/rndFraction.d.ts +4 -3
  16. package/dist/maths/randomization/rndGeometryCircle.d.ts +13 -0
  17. package/{esm → dist}/maths/randomization/rndGeometryLine.d.ts +4 -3
  18. package/{esm → dist}/maths/randomization/rndGeometryPoint.d.ts +4 -3
  19. package/{esm → dist}/maths/randomization/rndMonom.d.ts +5 -4
  20. package/{esm → dist}/maths/randomization/rndPolynom.d.ts +5 -4
  21. package/{esm → dist}/maths/randomization/rndTypes.d.ts +7 -1
  22. package/dist/pimath.js +4239 -7819
  23. package/package.json +13 -7
  24. package/.eslintrc.js +0 -24
  25. package/.idea/$CACHE_FILE$ +0 -6
  26. package/.idea/PI.iml +0 -14
  27. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  28. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  29. package/.idea/misc.xml +0 -6
  30. package/.idea/modules.xml +0 -8
  31. package/.idea/php.xml +0 -19
  32. package/.idea/shelf/Uncommitted_changes_before_Checkout_at_07_11_2023_08_30_[Default_Changelist]/shelved.patch +0 -192
  33. package/.idea/shelf/Uncommitted_changes_before_Checkout_at_07_11_2023_08_30_[Default_Changelist]1/shelved.patch +0 -0
  34. package/.idea/shelf/Uncommitted_changes_before_Checkout_at_07_11_2023_08_30__Default_Changelist_.xml +0 -4
  35. package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_10_43_[Default_Changelist]/shelved.patch +0 -2404
  36. package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_10_43__Default_Changelist_.xml +0 -4
  37. package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_11_01_[Default_Changelist]/shelved.patch +0 -1362
  38. package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_11_01__Default_Changelist_.xml +0 -4
  39. package/.idea/shelf/Uncommitted_changes_before_Update_at_24_07_2023_15_31_[Default_Changelist]/shelved.patch +0 -90
  40. package/.idea/shelf/Uncommitted_changes_before_Update_at_24_07_2023_15_31__Default_Changelist_.xml +0 -4
  41. package/.idea/vcs.xml +0 -6
  42. package/dev/pimath.js +0 -7945
  43. package/dev/pimath.js.map +0 -1
  44. package/dist/pimath.js.map +0 -1
  45. package/dist/pimath.min.js +0 -2
  46. package/dist/pimath.min.js.map +0 -1
  47. package/docs/.nojekyll +0 -1
  48. package/docs/assets/highlight.css +0 -78
  49. package/docs/assets/main.js +0 -59
  50. package/docs/assets/navigation.js +0 -1
  51. package/docs/assets/search.js +0 -1
  52. package/docs/assets/style.css +0 -1383
  53. package/docs/classes/Logicalset.Logicalset.html +0 -217
  54. package/docs/classes/Polynom.Rational.html +0 -397
  55. package/docs/classes/Vector-1.Vector.html +0 -490
  56. package/docs/classes/Vector.Point.html +0 -337
  57. package/docs/classes/algebra_equation.Equation.html +0 -790
  58. package/docs/classes/algebra_linearSystem.LinearSystem.html +0 -404
  59. package/docs/classes/algebra_monom.Monom.html +0 -962
  60. package/docs/classes/algebra_polynom.Polynom.html +0 -1275
  61. package/docs/classes/coefficients_fraction.Fraction.html +0 -934
  62. package/docs/classes/geometry_circle.Circle.html +0 -472
  63. package/docs/classes/geometry_line.Line.html +0 -774
  64. package/docs/classes/geometry_triangle.Triangle.html +0 -429
  65. package/docs/classes/numeric.Numeric.html +0 -265
  66. package/docs/classes/shutingyard.Shutingyard.html +0 -250
  67. package/docs/enums/algebra_equation.PARTICULAR_SOLUTION.html +0 -83
  68. package/docs/enums/geometry_line.LinePropriety.html +0 -97
  69. package/docs/enums/shutingyard.ShutingyardMode.html +0 -97
  70. package/docs/enums/shutingyard.ShutingyardType.html +0 -111
  71. package/docs/index.html +0 -63
  72. package/docs/interfaces/algebra_equation.ISolution.html +0 -105
  73. package/docs/interfaces/algebra_polynom.IEuclidian.html +0 -87
  74. package/docs/interfaces/geometry_triangle.remarquableLines.html +0 -163
  75. package/docs/modules/Logicalset.html +0 -65
  76. package/docs/modules/Polynom.html +0 -65
  77. package/docs/modules/Vector-1.html +0 -65
  78. package/docs/modules/Vector.html +0 -65
  79. package/docs/modules/algebra_equation.html +0 -69
  80. package/docs/modules/algebra_linearSystem.html +0 -61
  81. package/docs/modules/algebra_monom.html +0 -65
  82. package/docs/modules/algebra_polynom.html +0 -69
  83. package/docs/modules/coefficients_fraction.html +0 -65
  84. package/docs/modules/geometry_circle.html +0 -61
  85. package/docs/modules/geometry_line.html +0 -65
  86. package/docs/modules/geometry_triangle.html +0 -65
  87. package/docs/modules/numeric.html +0 -61
  88. package/docs/modules/shutingyard.html +0 -75
  89. package/docs/types/algebra_monom.literalType.html +0 -61
  90. package/docs/types/algebra_polynom.PolynomParsingType.html +0 -56
  91. package/docs/types/coefficients_fraction.FractionParsingType.html +0 -56
  92. package/docs/types/shutingyard.Token.html +0 -63
  93. package/docs/types/shutingyard.tokenType.html +0 -68
  94. package/docs/variables/shutingyard.tokenConstant.html +0 -61
  95. package/esm/index.d.ts +0 -38
  96. package/esm/index.js +0 -44
  97. package/esm/index.js.map +0 -1
  98. package/esm/maths/algebra/equation.js +0 -797
  99. package/esm/maths/algebra/equation.js.map +0 -1
  100. package/esm/maths/algebra/linearSystem.js +0 -279
  101. package/esm/maths/algebra/linearSystem.js.map +0 -1
  102. package/esm/maths/algebra/logicalset.js +0 -158
  103. package/esm/maths/algebra/logicalset.js.map +0 -1
  104. package/esm/maths/algebra/monom.js +0 -909
  105. package/esm/maths/algebra/monom.js.map +0 -1
  106. package/esm/maths/algebra/polynom.js +0 -1305
  107. package/esm/maths/algebra/polynom.js.map +0 -1
  108. package/esm/maths/algebra/rational.js +0 -195
  109. package/esm/maths/algebra/rational.js.map +0 -1
  110. package/esm/maths/algebra/study/rationalStudy.d.ts +0 -28
  111. package/esm/maths/algebra/study/rationalStudy.js +0 -244
  112. package/esm/maths/algebra/study/rationalStudy.js.map +0 -1
  113. package/esm/maths/algebra/study.js +0 -380
  114. package/esm/maths/algebra/study.js.map +0 -1
  115. package/esm/maths/coefficients/fraction.js +0 -517
  116. package/esm/maths/coefficients/fraction.js.map +0 -1
  117. package/esm/maths/coefficients/nthRoot.js +0 -137
  118. package/esm/maths/coefficients/nthRoot.js.map +0 -1
  119. package/esm/maths/geometry/circle.js +0 -324
  120. package/esm/maths/geometry/circle.js.map +0 -1
  121. package/esm/maths/geometry/line.js +0 -485
  122. package/esm/maths/geometry/line.js.map +0 -1
  123. package/esm/maths/geometry/point.js +0 -167
  124. package/esm/maths/geometry/point.js.map +0 -1
  125. package/esm/maths/geometry/triangle.js +0 -276
  126. package/esm/maths/geometry/triangle.js.map +0 -1
  127. package/esm/maths/geometry/vector.js +0 -198
  128. package/esm/maths/geometry/vector.js.map +0 -1
  129. package/esm/maths/numeric.js +0 -136
  130. package/esm/maths/numeric.js.map +0 -1
  131. package/esm/maths/numexp.js +0 -186
  132. package/esm/maths/numexp.js.map +0 -1
  133. package/esm/maths/randomization/random.js +0 -79
  134. package/esm/maths/randomization/random.js.map +0 -1
  135. package/esm/maths/randomization/randomCore.js +0 -22
  136. package/esm/maths/randomization/randomCore.js.map +0 -1
  137. package/esm/maths/randomization/rndFraction.js +0 -44
  138. package/esm/maths/randomization/rndFraction.js.map +0 -1
  139. package/esm/maths/randomization/rndGeometryLine.js +0 -46
  140. package/esm/maths/randomization/rndGeometryLine.js.map +0 -1
  141. package/esm/maths/randomization/rndGeometryPoint.js +0 -61
  142. package/esm/maths/randomization/rndGeometryPoint.js.map +0 -1
  143. package/esm/maths/randomization/rndHelpers.js +0 -98
  144. package/esm/maths/randomization/rndHelpers.js.map +0 -1
  145. package/esm/maths/randomization/rndMonom.js +0 -53
  146. package/esm/maths/randomization/rndMonom.js.map +0 -1
  147. package/esm/maths/randomization/rndPolynom.js +0 -75
  148. package/esm/maths/randomization/rndPolynom.js.map +0 -1
  149. package/esm/maths/randomization/rndTypes.js +0 -3
  150. package/esm/maths/randomization/rndTypes.js.map +0 -1
  151. package/esm/maths/shutingyard.js +0 -443
  152. package/esm/maths/shutingyard.js.map +0 -1
  153. package/public/demo.css +0 -3
  154. package/public/index.html +0 -283
  155. package/public/matrices.html +0 -100
  156. package/public/playground.html +0 -168
  157. package/src/index.ts +0 -42
  158. package/src/maths/algebra/equation.ts +0 -897
  159. package/src/maths/algebra/linearSystem.ts +0 -370
  160. package/src/maths/algebra/logicalset.ts +0 -183
  161. package/src/maths/algebra/monom.ts +0 -1028
  162. package/src/maths/algebra/polynom.ts +0 -1537
  163. package/src/maths/algebra/rational.ts +0 -240
  164. package/src/maths/algebra/study/rationalStudy.ts +0 -287
  165. package/src/maths/algebra/study.ts +0 -506
  166. package/src/maths/coefficients/fraction.ts +0 -593
  167. package/src/maths/coefficients/nthRoot.ts +0 -148
  168. package/src/maths/geometry/circle.ts +0 -382
  169. package/src/maths/geometry/line.ts +0 -604
  170. package/src/maths/geometry/point.ts +0 -215
  171. package/src/maths/geometry/triangle.ts +0 -368
  172. package/src/maths/geometry/vector.ts +0 -242
  173. package/src/maths/numeric.ts +0 -162
  174. package/src/maths/numexp.ts +0 -184
  175. package/src/maths/randomization/random.ts +0 -80
  176. package/src/maths/randomization/randomCore.ts +0 -19
  177. package/src/maths/randomization/rndFraction.ts +0 -47
  178. package/src/maths/randomization/rndGeometryCircle.ts +0 -50
  179. package/src/maths/randomization/rndGeometryLine.ts +0 -53
  180. package/src/maths/randomization/rndGeometryPoint.ts +0 -69
  181. package/src/maths/randomization/rndHelpers.ts +0 -107
  182. package/src/maths/randomization/rndMonom.ts +0 -57
  183. package/src/maths/randomization/rndPolynom.ts +0 -90
  184. package/src/maths/randomization/rndTypes.ts +0 -43
  185. package/src/maths/shutingyard.ts +0 -496
  186. package/tests/algebra/equation.test.ts +0 -64
  187. package/tests/algebra/linear.test.ts +0 -58
  188. package/tests/algebra/monom.test.ts +0 -78
  189. package/tests/algebra/polynom.test.ts +0 -343
  190. package/tests/algebra/rationnal.test.ts +0 -64
  191. package/tests/algebra/study.test.ts +0 -48
  192. package/tests/coefficients/fraction.test.ts +0 -131
  193. package/tests/custom.test.ts +0 -33
  194. package/tests/geometry/circle.test.ts +0 -404
  195. package/tests/geometry/line.test.ts +0 -36
  196. package/tests/numeric.test.ts +0 -43
  197. package/tests/numexp.test.ts +0 -89
  198. package/tests/shutingyard.test.ts +0 -58
  199. package/tsconfig.json +0 -41
  200. package/tsconfig.testing.json +0 -28
  201. package/typedoc.katex.js +0 -11
  202. package/webpack-production-min.config.js +0 -26
  203. package/webpack-production.config.js +0 -26
  204. package/webpack.config.js +0 -26
  205. package/{esm → dist}/maths/algebra/logicalset.d.ts +6 -6
  206. package/{esm → dist}/maths/coefficients/fraction.d.ts +0 -0
  207. package/{esm → dist}/maths/coefficients/nthRoot.d.ts +0 -0
  208. package/{esm → dist}/maths/numeric.d.ts +0 -0
  209. package/{esm → dist}/maths/numexp.d.ts +3 -3
  210. /package/{esm → dist}/maths/randomization/randomCore.d.ts +0 -0
  211. /package/{esm → dist}/maths/randomization/rndHelpers.d.ts +0 -0
  212. /package/{esm → dist}/maths/shutingyard.d.ts +0 -0
@@ -1,1537 +0,0 @@
1
- /**
2
- * Polynom module contains everything necessary to handle polynoms.*
3
- */
4
-
5
- import {literalType, Monom} from './monom';
6
- import {Shutingyard, ShutingyardType, Token} from '../shutingyard';
7
- import {Numeric} from '../numeric';
8
- import {Fraction} from "../coefficients/fraction";
9
- import {Equation, ISolution} from "./equation";
10
-
11
- export type PolynomParsingType = string | Polynom | number | Fraction | Monom
12
-
13
- export interface IEuclidian {
14
- quotient: Polynom,
15
- reminder: Polynom
16
- }
17
-
18
- /**
19
- * Polynom class can handle polynoms, reorder, resolve, ...
20
- * ```
21
- * let P = new Polynom('3x-4')
22
- * ```
23
- */
24
- export class Polynom {
25
- private _rawString: string;
26
- private _dirty_factors: boolean
27
- private _dirty_zeroes: boolean
28
- private _euclidianCache: { [Key: string]: IEuclidian }
29
- private _factors: Polynom[];
30
- private _monoms: Monom[];
31
- private _texString: string;
32
- private _zeroes: ISolution[]
33
-
34
- /**
35
- *
36
- * @param {string} polynomString (optional) Default polynom to parse on class creation
37
- * @param values
38
- */
39
- constructor(polynomString?: PolynomParsingType, ...values: unknown[]) {
40
- this._monoms = [];
41
- this._factors = [];
42
- this.mark_as_dirty()
43
-
44
- if (polynomString !== undefined) {
45
- this.parse(polynomString, ...values);
46
- }
47
- return this;
48
- }
49
-
50
- // ------------------------------------------
51
- get dirty_factors(): boolean {
52
- return this._dirty_factors;
53
- }
54
-
55
- set dirty_factors(value: boolean) {
56
- this._dirty_factors = value;
57
- }
58
-
59
- get dirty_zeroes(): boolean {
60
- return this._dirty_zeroes;
61
- }
62
-
63
- set dirty_zeroes(value: boolean) {
64
- this._dirty_zeroes = value;
65
- }
66
-
67
- get euclidianCache(): { [p: string]: IEuclidian } {
68
- return this._euclidianCache;
69
- }
70
-
71
- set euclidianCache(value: { [p: string]: IEuclidian }) {
72
- this._euclidianCache = value;
73
- }
74
-
75
- get factors(): Polynom[] {
76
- return this.factorize()
77
- }
78
-
79
- set factors(value: Polynom[]) {
80
- this.mark_as_dirty()
81
- this._factors = value;
82
- }
83
-
84
- // ------------------------------------------
85
- get monoms() {
86
- return this._monoms;
87
- }
88
-
89
- set monoms(M: Monom[]) {
90
- this._monoms = M;
91
- }
92
-
93
- get texString(): string {
94
- return this._texString;
95
- }
96
-
97
- get zeroes(): ISolution[] {
98
- return this.getZeroes()
99
- }
100
-
101
- get texFactors(): string {
102
- this.factorize()
103
-
104
- if (this.factors.length <= 1) {
105
- return this.tex
106
- }
107
-
108
- // Build an array of texFactors with the number of similar items.
109
- let factorsCount: { [Key: string]: { degree: number, factor: Polynom } } = {}
110
- for (let f of this.factors) {
111
- if (factorsCount[f.tex] !== undefined) {
112
- factorsCount[f.tex].degree++
113
- } else {
114
- factorsCount[f.tex] = {
115
- degree: 1,
116
- factor: f
117
- }
118
- }
119
- }
120
-
121
- // First round to put the 'monom' first
122
- let simpleFactor = new Polynom().one()
123
-
124
- for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length === 1)) {
125
- simpleFactor.multiply(item.factor)
126
- }
127
-
128
- let tex = simpleFactor.isOne() ? '' : simpleFactor.tex
129
-
130
- // Loop through all factors that contains at least 2 monoms.
131
- for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length > 1)) {
132
- if (item.factor.length > 1) {
133
- tex += `\\left( ${item.factor.tex} \\right)${item.degree > 1 ? '^{ ' + item.degree + ' }' : ''}`
134
- }
135
- }
136
-
137
- return tex;
138
- }
139
-
140
- get displayFactors() {
141
- this.factorize()
142
-
143
- if (this.factors.length <= 1) {
144
- return this.display
145
- }
146
-
147
- // Build an array of texFactors with the number of similar items.
148
- let factorsCount: { [Key: string]: { degree: number, factor: Polynom } } = {}
149
- for (let f of this.factors) {
150
- if (factorsCount[f.display] !== undefined) {
151
- factorsCount[f.display].degree++
152
- } else {
153
- factorsCount[f.display] = {
154
- degree: 1,
155
- factor: f
156
- }
157
- }
158
- }
159
-
160
- // First round to put the 'monom' first
161
- let simpleFactor = new Polynom().one()
162
-
163
- for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length === 1)) {
164
- simpleFactor.multiply(item.factor)
165
- }
166
-
167
- let display = simpleFactor.isOne() ? '' : simpleFactor.display
168
-
169
- // Loop through all factors that contains at least 2 monoms.
170
- for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length > 1)) {
171
- if (item.factor.length > 1) {
172
- display += `(${item.factor.display})${item.degree > 1 ? '^(' + item.degree + ')' : ''}`
173
- }
174
- }
175
-
176
- return display;
177
- }
178
-
179
- get length() {
180
- // TODO: Must reduce the monoms list to remove the zero coefficient.
181
- return this._monoms.length;
182
- }
183
-
184
- get display(): string {
185
- return this.genDisplay();
186
- }
187
-
188
- get raw(): string {
189
- return this._rawString
190
- }
191
-
192
- get tex(): string {
193
- return this.genDisplay('tex');
194
- }
195
-
196
- get isMultiVariable(): boolean {
197
- const B = false;
198
- for (const m of this._monoms) {
199
- if (m.variables.length > 1) {
200
- return true;
201
- }
202
- }
203
- return B;
204
- }
205
-
206
- get variables(): string[] {
207
- let V: string[] = [];
208
-
209
- for (const m of this._monoms) {
210
- V = V.concat(m.variables);
211
- }
212
-
213
- // Remove duplicates.
214
- V = [...new Set(V)];
215
- V.sort()
216
- return V;
217
- }
218
-
219
- get numberOfVars(): number {
220
- return this.variables.length;
221
- }
222
-
223
- get plotFunction(): string {
224
- return this.genDisplay('tex', false, false, true)
225
- }
226
-
227
- mark_as_dirty = (): void => {
228
- this.dirty_factors = true
229
- this.dirty_zeroes = true
230
- this.euclidianCache = {}
231
- }
232
-
233
- addToken = (stack: Polynom[], element: Token): void => {
234
- switch (element.tokenType) {
235
- case ShutingyardType.COEFFICIENT:
236
- stack.push(new Polynom(element.token))
237
- break
238
-
239
- case ShutingyardType.VARIABLE:
240
- stack.push(new Polynom().add(new Monom(element.token)))
241
- break
242
-
243
- case ShutingyardType.CONSTANT:
244
- // TODO: add constant support to Polynom parsing.
245
- console.log('Actually, not supported - will be added later !')
246
- break
247
-
248
- case ShutingyardType.OPERATION:
249
- if (stack.length >= 2) {
250
- const b = stack.pop(),
251
- a = stack.pop()
252
-
253
- if (element.token === '+') {
254
- stack.push(a.add(b))
255
- } else if (element.token === '-') {
256
- stack.push(a.subtract(b))
257
- } else if (element.token === '*') {
258
- stack.push(a.multiply(b))
259
- } else if (element.token === '/') {
260
- if (b.degree().isStrictlyPositive()) {
261
- console.log('divide by a polynom -> should create a rational polynom !')
262
- } else {
263
- stack.push(a.divide(b.monoms[0].coefficient))
264
-
265
- }
266
- } else if (element.token === '^') {
267
- if (b.degree().isStrictlyPositive()) {
268
- console.error('Cannot elevate a polynom with another polynom !', a.tex, b.tex)
269
- } else {
270
- if (b.monoms[0].coefficient.isRelative()) {
271
- // Integer power
272
- stack.push(a.pow(b.monoms[0].coefficient.value))
273
- } else {
274
- // Only allow power if the previous polynom is only a monom, without coefficient.
275
- if (a.monoms.length === 1 && a.monoms[0].coefficient.isOne()) {
276
- for (let letter in a.monoms[0].literal) {
277
- a.monoms[0].literal[letter].multiply(b.monoms[0].coefficient)
278
- }
279
- stack.push(a)
280
- } else {
281
- console.error('Cannot have power with fraction')
282
- }
283
- }
284
- }
285
- }
286
- } else {
287
- if (element.token === '-') {
288
- stack.push(stack.pop().opposed())
289
- } else {
290
- throw "Error parsing the polynom " + this._rawString
291
- }
292
- }
293
- break
294
-
295
- case ShutingyardType.MONOM:
296
- // Should never appear.
297
- console.error('The monom token should not appear here')
298
- break;
299
-
300
- case ShutingyardType.FUNCTION:
301
- // Should never appear.
302
- console.error('The function token should not appear here - might be introduced later.')
303
- break;
304
- }
305
- }
306
-
307
-
308
- // ------------------------------------------
309
- // Creation / parsing functions
310
-
311
- // ------------------------------------------
312
- /**
313
- * Parse a string to a polynom.
314
- * @param inputStr
315
- * @param values: as string, numbers or fractions
316
- */
317
- parse = (inputStr: PolynomParsingType, ...values: unknown[]): Polynom => {
318
- // Reset the main variables.
319
- this._monoms = []
320
- this._factors = []
321
- this.mark_as_dirty()
322
-
323
- // TODO: allow to enter a liste of Fraction (a, b, c, ...) to make a polynom ax^n + bx^(n-1) + cx^(n-2) + ...
324
- if (typeof inputStr === 'string') {
325
- return this._parseString(inputStr, ...values)
326
- } else if (
327
- (typeof inputStr === 'number' || inputStr instanceof Fraction || inputStr instanceof Monom)
328
- && (values === undefined || values.length === 0)
329
- ) {
330
- this._monoms.push(new Monom(inputStr))
331
- } else if (inputStr instanceof Monom && values.length > 0) {
332
- this._monoms.push(new Monom(inputStr))
333
- values.forEach(m => {
334
- this._monoms.push(new Monom(m))
335
- })
336
- } else if (inputStr instanceof Polynom) {
337
- for (const m of inputStr.monoms) {
338
- this._monoms.push(m.clone())
339
- }
340
- }
341
-
342
- return this
343
- };
344
-
345
- /**
346
- * Clone the polynom
347
- */
348
- clone = (): Polynom => {
349
- const P = new Polynom();
350
- const M: Monom[] = [];
351
-
352
- for (const m of this._monoms) {
353
- M.push(m.clone());
354
- }
355
-
356
- P.monoms = M;
357
-
358
- return P;
359
- };
360
-
361
- /**
362
- * Set the polynom to zero.
363
- * @returns {this}
364
- */
365
- zero = (): Polynom => {
366
- this._monoms = [];
367
- this._monoms.push(new Monom().zero());
368
- this._rawString = '0';
369
- this.mark_as_dirty()
370
- return this;
371
- };
372
-
373
- one = (): Polynom => {
374
- this._monoms = [];
375
- this._monoms.push(new Monom().one());
376
- this._rawString = '1';
377
- this.mark_as_dirty()
378
- return this;
379
- }
380
-
381
- empty = (): Polynom => {
382
- this._monoms = [];
383
- this._rawString = '';
384
- this.mark_as_dirty()
385
- return this;
386
- };
387
-
388
- // ------------------------------------------
389
- opposed = (): Polynom => {
390
- this._monoms = this._monoms.map(m => m.opposed());
391
- this.mark_as_dirty()
392
- return this;
393
- };
394
-
395
-
396
- // ------------------------------------------
397
- // Mathematical operations
398
-
399
- add = (...values: unknown[]): Polynom => {
400
- this.mark_as_dirty()
401
-
402
- // @ts-ignore
403
- for (let value of values) {
404
- if (value instanceof Polynom) {
405
- this._monoms = this._monoms.concat(value.monoms);
406
- } else if (value instanceof Monom) {
407
- this._monoms.push(value.clone());
408
- } else if (Number.isSafeInteger(value)) {
409
- this._monoms.push(new Monom(value.toString()));
410
- } else {
411
- this._monoms.push(new Monom(value));
412
- }
413
- }
414
-
415
- return this.reduce();
416
- };
417
-
418
- subtract = (...values: unknown[]): Polynom => {
419
- this.mark_as_dirty()
420
-
421
- for (let value of values) {
422
- if (value instanceof Polynom) {
423
- this._monoms = this._monoms.concat(value.clone().opposed().monoms);
424
- } else if (value instanceof Monom) {
425
- this._monoms.push(value.clone().opposed());
426
- } else if (Number.isSafeInteger(value)) {
427
- this._monoms.push(new Monom(value.toString()).opposed());
428
- } else {
429
- this._monoms.push(new Monom(value).opposed());
430
- }
431
- }
432
-
433
- return this.reduce();
434
- };
435
-
436
- multiply = (value: unknown): Polynom => {
437
- this.mark_as_dirty()
438
-
439
- if (value instanceof Polynom) {
440
- return this.multiplyByPolynom(value)
441
- } else if (value instanceof Fraction) {
442
- return this.multiplyByFraction(value);
443
- } else if (value instanceof Monom) {
444
- return this.multiplyByMonom(value);
445
- } else if (Number.isSafeInteger(value) && typeof value === 'number') {
446
- return this.multiplyByInteger(value);
447
- }
448
-
449
- // Something went wrong...
450
- return this;
451
- }
452
-
453
- /**
454
- * Divide the current polynom by another polynom.
455
- * @param P
456
- * returns {quotient: Polynom, reminder: Polynom}
457
- */
458
- euclidian = (P: Polynom): IEuclidian => {
459
-
460
- if (this.euclidianCache[P.tex] !== undefined) {
461
- return this.euclidianCache[P.tex]
462
- }
463
-
464
- const letter: string = P.variables[0];
465
- const quotient: Polynom = new Polynom().zero();
466
- const reminder: Polynom = this.clone().reorder(letter);
467
-
468
- // There is no variable - means it's a number
469
- if (P.variables.length === 0) {
470
- let q = this.clone().divide(P)
471
- return {
472
- quotient: this.clone().divide(P).reduce(),
473
- reminder: new Polynom().zero()
474
- }
475
- }
476
-
477
- // Get at least a letter
478
- const maxMP: Monom = P.monomByDegree(undefined, letter);
479
- const degreeP: Fraction = P.degree(letter);
480
-
481
- let newM: Monom;
482
-
483
- // Make the euclidian division of the two polynoms.
484
- let MaxIteration = this.degree(letter).value * 2;
485
- while (reminder.degree(letter).geq(degreeP) && MaxIteration > 0) {
486
- MaxIteration--
487
-
488
- // Get the greatest monom divided by the max monom of the divider
489
- newM = reminder.monomByDegree(undefined, letter).clone().divide(maxMP);
490
-
491
- if (newM.isZero()) continue;
492
-
493
- // Get the new quotient and reminder.
494
- quotient.add(newM);
495
- reminder.subtract(P.clone().multiply(newM)).reduce();
496
-
497
- // Check if the reminder is zero.
498
- if (newM.degree(letter).isZero()) break
499
- }
500
-
501
- quotient.reduce()
502
- reminder.reduce()
503
- return {quotient, reminder};
504
- };
505
-
506
- divide = (value: unknown): Polynom => {
507
- this.mark_as_dirty()
508
-
509
- if (value instanceof Fraction) {
510
- return this.divideByFraction(value);
511
- } else if (typeof value === 'number' && Number.isSafeInteger(value)) {
512
- return this.divideByInteger(value);
513
- } else if (value instanceof Monom) {
514
- return this.divide(new Polynom(value))
515
- } else if (value instanceof Polynom) {
516
- if (value.monoms.length === 1 && value.variables.length === 0) {
517
- return this.divideByFraction(value.monoms[0].coefficient)
518
- } else {
519
- let {quotient, reminder} = this.euclidian(value)
520
- if (reminder.isZero()) {
521
- return quotient
522
- } else {
523
- console.log(`${this.tex} is not divideable by ${value.tex}`)
524
- return new Polynom().zero()
525
- }
526
- }
527
- }
528
- }
529
-
530
- pow = (nb: number): Polynom => {
531
- this.mark_as_dirty()
532
-
533
- if (!Number.isSafeInteger(nb)) {
534
- return this.zero();
535
- }
536
- if (nb < 0) {
537
- return this.zero();
538
- }
539
- if (nb === 0) {
540
- return new Polynom();
541
- }
542
-
543
- const P = this.clone();
544
- for (let i = 1; i < nb; i++) {
545
- this.multiply(P);
546
- }
547
- return this.reduce();
548
- };
549
-
550
- // ------------------------------------------
551
- /**
552
- * Compare the current coefficient with another coefficient
553
- * @param P
554
- * @param sign (string| default is =): authorized values: =, <, <=, >, >= with some variations.
555
- */
556
- compare = (P: Polynom, sign?: string): boolean => {
557
- if (sign === undefined) {
558
- sign = '='
559
- }
560
-
561
- // Create clone version to reduce them without altering the original polynoms.
562
- const cP1 = this.clone().reduce().reorder();
563
- const cP2 = P.clone().reduce().reorder();
564
-
565
- switch (sign) {
566
- case '=':
567
- // They must have the isSame length and the isSame degree
568
- if (cP1.length !== cP2.length || cP1.degree().isNotEqual(cP2.degree())) {
569
- return false;
570
- }
571
-
572
- // Check if the coefficients are the isSame.
573
- for (const i in cP1.monoms) {
574
- if (!cP1.monoms[i].isEqual(cP2.monoms[i])) {
575
- return false;
576
- }
577
- }
578
- return true;
579
- case 'same':
580
- // They must have the isSame length and the isSame degree
581
- if (cP1.length !== cP2.length || cP1.degree() !== cP2.degree()) {
582
- return false;
583
- }
584
-
585
- for (const i in cP1.monoms) {
586
- if (!cP1.monoms[i].isSameAs(cP2.monoms[i])) {
587
- return false;
588
- }
589
- }
590
-
591
- return true;
592
- default:
593
- return false;
594
- }
595
- };
596
-
597
- isZero(): boolean {
598
- return (this._monoms.length === 1 && this._monoms[0].coefficient.isZero()) || this._monoms.length === 0;
599
- }
600
-
601
- isOne(): boolean {
602
- return this._monoms.length === 1 && this._monoms[0].coefficient.isOne();
603
- }
604
-
605
- isEqual = (P: Polynom): boolean => {
606
- return this.compare(P, '=');
607
- };
608
-
609
- isSameAs = (P: Polynom): boolean => {
610
- return this.compare(P, 'same');
611
- };
612
-
613
- isOpposedAt = (P: Polynom): boolean => {
614
- return this.compare(P.clone().opposed(), '=');
615
- };
616
-
617
- isFactorized = (polynomString: string, soft?: boolean): boolean => {
618
- let P;
619
-
620
- // Check if polynom is complete...
621
- if (polynomString.split('(').length !== polynomString.split(')').length) {
622
- return false
623
- }
624
-
625
- // Try to build the polynom
626
- try {
627
- P = new Polynom(polynomString);
628
- } catch (e) {
629
- return false;
630
- }
631
-
632
- // Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
633
- if (!this.isEqual(P)) {
634
- return false;
635
- }
636
-
637
- // Check if the provided (string) version is fully factorized.
638
- // Run a regex on the string.
639
- let polynomStringNormalized = polynomString.replaceAll('*', ''),
640
- polynomStringReduced = '' + polynomStringNormalized,
641
- factors: string[] = [];
642
-
643
- for (let x of polynomStringNormalized.matchAll(/\(([a-z0-9+\-]+)\)(\^[0-9]*)?/g)) {
644
-
645
- if (x[2] !== undefined) {
646
- // if there is an exponential value, add it multiple times
647
- for (let i = 0; i < +x[2].substring(1); i++) {
648
- factors.push(x[1])
649
- }
650
- } else {
651
- // no power - add it once.
652
- factors.push(x[1]);
653
- }
654
-
655
- // Remove the current polynom
656
- polynomStringReduced = polynomStringReduced.replaceAll(x[0], '');
657
- }
658
- if (polynomStringReduced !== '') {
659
- factors.push(polynomStringReduced);
660
- }
661
- let polyFactors = factors.map(x => new Polynom(x));
662
-
663
- // polyFactors contain all polynoms.
664
- let checkPolyFactors = polyFactors.filter(x => x.degree().geq(1) && !x.commonMonom().isOne())
665
-
666
- // Some polynoms are not completely factorized.
667
- if (checkPolyFactors.length > 0 && !soft) {
668
- return false
669
- }
670
- if (checkPolyFactors.length > 0 && soft) {
671
- polyFactors = polyFactors.filter(x => x.commonMonom().isOne())
672
-
673
- let FactorizedConstant = new Fraction().one()
674
- for (let p of checkPolyFactors) {
675
- let k = p.commonMonom(),
676
- pFactor = p.clone().divide(k)
677
-
678
- if (k.degree().isZero()) {
679
- FactorizedConstant.multiply(k.coefficient)
680
- polyFactors.push(pFactor.clone())
681
- }
682
- }
683
- }
684
-
685
-
686
- // Factorize the current polynom.
687
- this.factorize();
688
-
689
- // Compare the given factors with the generated factors
690
- let sign = 1,
691
- notFoundedFactors = []
692
- for (let f of this.factors) {
693
- // The factor is just a coefficient. Might be opposed
694
- if (f.degree().isZero()) {
695
- if (f.monoms[0].coefficient.isNegativeOne()) {
696
- sign = -sign
697
- }
698
- }
699
-
700
- let factorFound = false
701
- for (let i = 0; i < polyFactors.length; i++) {
702
- if (f.isEqual(polyFactors[i])) {
703
- polyFactors.splice(i, 1);
704
- factorFound = true
705
- break;
706
- } else if (f.isOpposedAt(polyFactors[i])) {
707
- polyFactors.splice(i, 1);
708
- sign = -sign;
709
- factorFound = true
710
- break;
711
- }
712
- }
713
-
714
- if (!factorFound) {
715
- notFoundedFactors.push(f.clone())
716
- }
717
- }
718
-
719
- // The polyfactors must be empty and the cumulative opposite factors must be 1.
720
- return (polyFactors.length === 0 && sign === 1);
721
- }
722
-
723
-
724
- // ------------------------------------------
725
- // Compare functions
726
-
727
- isReduced = (polynomString: string): Boolean => {
728
- // The polynom must be developed to be reduced.
729
- if (!this.isDeveloped(polynomString)) {
730
- return false
731
- }
732
-
733
- let P = new Polynom(polynomString)
734
- if (P.monoms.length > this.monoms.length) {
735
- return false
736
- }
737
-
738
- // TODO: Not ur the reduced systme checking is working properly !
739
- for (let m of P.monoms) {
740
- if (!m.coefficient.isReduced()) {
741
- return false
742
- }
743
- }
744
-
745
- return false
746
- }
747
-
748
- isDeveloped = (polynomString: string): Boolean => {
749
- let P: Polynom;
750
-
751
- // Start by removing the parenthis after a "power"
752
- let pString = polynomString.replaceAll(/\^\(([-0-9/]+)\)/g, '$1')
753
-
754
- // There is at least one parenthese - it is not developed.
755
- if (pString.includes('(') || pString.includes(')')) {
756
- return false
757
- }
758
-
759
- // Try to build the polynom
760
- try {
761
- // Build the polynom
762
- P = new Polynom(polynomString);
763
- } catch (e) {
764
- return false;
765
- }
766
-
767
- // Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
768
- if (!this.isEqual(P)) {
769
- return false;
770
- }
771
-
772
- // Check that everything is completely developed. Actually, there are no parentheses... so it is fully developed
773
- return true
774
-
775
- // // maybe it wasn't reduced and not ordered...
776
- // // compare polynom string.
777
- //
778
- // // normalize the string
779
- // let polynomStringNormalized = polynomString.replaceAll('[*\s]', '')
780
- //
781
- // // Determine if it's the exact same string.
782
- // // TODO: Maybe it's enough to just make this test !a
783
- // return polynomStringNormalized === P.reduce().reorder().display
784
- }
785
-
786
- // -------------------------------------
787
- reduce = (): Polynom => {
788
- // Reduce the polynom
789
- let values = this._monoms.map(x => x.clone()),
790
- vars = [...this.variables]
791
-
792
- // Group the monoms by similarity
793
- let i = 0
794
- while (i < this._monoms.length) {
795
- for (let j = i + 1; j < this._monoms.length; j++) {
796
- if (this._monoms[i].isSameAs(this._monoms[j])) {
797
- this._monoms[i].add(this._monoms[j])
798
- this._monoms.splice(j, 1)
799
- if (this._monoms[i].isZero()) {
800
- this._monoms[i] = new Monom().zero()
801
- }
802
- j--
803
- }
804
- }
805
- i++
806
- }
807
-
808
- //
809
- //
810
- //
811
- // let coeffs = values.filter(x => x.variables.length === 0)
812
- //
813
- // if (coeffs.length > 0) {
814
- // this._monoms.push(coeffs.reduce((a, b) => a.add(b)))
815
- // }
816
- //
817
- // // Build the new monoms
818
- // for (let letter of vars) {
819
- // // Monom with same letters, but might be of different degrees
820
- // let M = values.filter(x => x.hasLetter(letter))
821
- //
822
- // while (M.length > 0) {
823
- // // Take the first element
824
- // const m = M.shift(), degree = m.degree(letter)
825
- //
826
- // for (let a of M.filter(x => x.degree(letter).isEqual(degree))) {
827
- // m.add(a)
828
- // }
829
- //
830
- // this._monoms.push(m)
831
- //
832
- // // Make the new array.
833
- // M = M.filter(x => x.degree(letter).isNotEqual(degree))
834
- // }
835
- // // reduce the monom
836
- //
837
- // }
838
-
839
-
840
- // Remove all null monoms
841
- this._monoms = this._monoms.filter((m) => {
842
- return m.coefficient.value !== 0
843
- });
844
-
845
- // Reduce all monoms coefficient.
846
- for (const m of this._monoms) {
847
- m.coefficient.reduce();
848
- }
849
-
850
- if (this.length === 0) {
851
- return new Polynom().zero();
852
- }
853
-
854
- return this.reorder();
855
- };
856
-
857
- reorder = (letter: string = 'x', revert?: boolean): Polynom => {
858
- if (revert === undefined) {
859
- revert = false
860
- }
861
-
862
- // TODO: Must handle multiple setLetter reorder system
863
- let otherLetters = this.variables.filter(x => x !== letter)
864
- this._monoms.sort(function (a, b) {
865
- let da = a.degree(letter).value,
866
- db = b.degree(letter).value
867
-
868
- // Values are different
869
- if (da !== db) return revert ? da - db : db - da
870
-
871
- // if values are equals, check other letters - it must be revert in that case !
872
- if (otherLetters.length > 0) {
873
- for (let L of otherLetters) {
874
- let da = a.degree(L).value,
875
- db = b.degree(L).value
876
-
877
- // Values are different
878
- if (da !== db) return revert ? da - db : db - da
879
- }
880
- }
881
-
882
- return 0
883
- // return b.degree(letter).clone().subtract(a.degree(letter)).value
884
- });
885
-
886
- return this;
887
- };
888
-
889
- degree = (letter?: string): Fraction => {
890
- let d: Fraction = new Fraction().zero();
891
- for (const m of this._monoms) {
892
- d = Fraction.max(m.degree(letter).value, d);
893
- }
894
- return d;
895
- };
896
-
897
- letters = (): string[] => {
898
- let L: string[] = [], S = new Set();
899
-
900
- for (let m of this._monoms) {
901
- S = new Set([...S, ...m.variables]);
902
- }
903
-
904
- // @ts-ignore
905
- return [...S];
906
- }
907
-
908
- /**
909
- * Replace a variable (letter) by a polynom.
910
- * @param letter
911
- * @param P
912
- */
913
- replaceBy = (letter: string, P: Polynom): Polynom => {
914
- this.mark_as_dirty()
915
-
916
- let pow: Fraction;
917
- const resultPolynom: Polynom = new Polynom().zero();
918
-
919
- for (const m of this.monoms) {
920
- if (m.literal[letter] === undefined || m.literal[letter].isZero()) {
921
- resultPolynom.add(m.clone());
922
- } else {
923
- // We have found a setLetter.
924
- // Get the power and reset it.
925
- pow = m.literal[letter].clone();
926
- delete m.literal[letter];
927
-
928
- // TODO: replaceBy works only with positive and natural pow
929
- resultPolynom.add(P.clone().pow(Math.abs(pow.numerator)).multiply(m));
930
- }
931
- }
932
-
933
- this._monoms = resultPolynom.reduce().reorder().monoms;
934
- return this;
935
- };
936
-
937
- // Evaluate a polynom.
938
- evaluate = (values: literalType | Fraction | number): Fraction => {
939
- const r = new Fraction().zero();
940
-
941
- this._monoms.forEach(monom => {
942
- //console.log('Evaluate polynom: ', monom.display, values, monom.evaluate(values).display);
943
- r.add(monom.evaluate(values));
944
- });
945
-
946
- return r;
947
- };
948
-
949
- evaluateAsNumeric = (values: { [Key: string]: number } | number): number => {
950
- let r = 0
951
- this._monoms.forEach(monom => {
952
- r += monom.evaluateAsNumeric(values)
953
- })
954
-
955
- return r
956
- }
957
-
958
- derivative = (letter?: string): Polynom => {
959
- let dP = new Polynom();
960
-
961
- for (let m of this._monoms) {
962
- dP.add(m.derivative(letter));
963
- }
964
- return dP;
965
- }
966
- // ------------------------------------------
967
- // Misc polynoms functions
968
-
969
- primitive = (letter?: string): Polynom => {
970
- let dP = new Polynom();
971
-
972
- for (let m of this._monoms) {
973
- dP.add(m.primitive(letter))
974
- }
975
- return dP
976
- }
977
-
978
- integrate = (a: Fraction | number, b: Fraction | number, letter?: string): Fraction => {
979
- const primitive = this.primitive(letter)
980
-
981
- if (letter === undefined) {
982
- letter = 'x'
983
- }
984
-
985
- let valuesA: literalType = {},
986
- valuesB: literalType = {}
987
- valuesA[letter] = new Fraction(a);
988
- valuesB[letter] = new Fraction(b);
989
-
990
- return primitive.evaluate(valuesB).subtract(primitive.evaluate(valuesA))
991
- }
992
-
993
- // -------------------------------------
994
- /**
995
- * Factorize a polynom and store the best results in factors.
996
- * @param maxValue Defines the greatest value to search to (default is 20).
997
- */
998
- factorize = (letter?: string): Polynom[] => {
999
- if (!this.dirty_factors) {
1000
- return this._factors
1001
- }
1002
-
1003
- let factors: Polynom[] = [];
1004
- let P = this.clone().reorder()
1005
-
1006
- // Extract the common monom
1007
- // 2x^3+6x^2 => 2x^2
1008
- let M = P.commonMonom()
1009
- // If the polynom starts with a negative monom, factorize it.
1010
- if (P.monomByDegree().coefficient.isStrictlyNegative() && M.coefficient.isStrictlyPositive() && !M.isOne()) {
1011
- M.opposed()
1012
- }
1013
-
1014
- if (!M.isOne()) {
1015
- let tempPolynom: Polynom = new Polynom(M)
1016
- factors = [tempPolynom.clone()]
1017
- P = P.euclidian(tempPolynom).quotient;
1018
- }
1019
-
1020
- // Main loop
1021
- let securityLoop = P.degree().clone().multiply(2).value,
1022
- maxDegree = 1
1023
- while (securityLoop >= 0) {
1024
- securityLoop--
1025
- if (P.monoms.length < 2) {
1026
- // The polynom has only one monom => 7x^2
1027
- // No need to continue.
1028
- if (!P.isOne()) {
1029
- factors.push(P.clone())
1030
- P.one()
1031
- }
1032
- break
1033
- } else if (P.degree(letter).isOne()) {
1034
- // The polynom is a first degree polynom => 3x-5
1035
- // No need to continue
1036
- factors.push(P.clone())
1037
- P.one()
1038
- break
1039
- } else {
1040
- // Create the list of all "potential" polynom dividers.
1041
- let allDividers: Polynom[] = this._getAllPotentialFactors(P, maxDegree, letter)
1042
- maxDegree = P.degree(letter).value
1043
-
1044
- // Actually: 100ms
1045
- while (allDividers.length > 0) {
1046
- let div = allDividers[0]
1047
-
1048
- if (!P.isDividableBy(div)) {
1049
- // Not dividable. Remove it from the list
1050
- allDividers.shift()
1051
- } else {
1052
- // It's dividable - so make the division
1053
- let result = P.euclidian(div)
1054
-
1055
- // Add the factor
1056
- factors.push(div)
1057
-
1058
- // As it's dividable, get the quotient.
1059
- P = result.quotient.clone()
1060
-
1061
- // filter all dividers that are no more suitable.
1062
- allDividers = allDividers.filter(x => {
1063
- let pX = P.monoms[0],
1064
- pC = P.monoms[P.monoms.length - 1],
1065
- dX = x.monoms[0],
1066
- dC = x.monoms[x.monoms.length - 1]
1067
-
1068
- // Check last item (degree zero)
1069
- if (!pC.isDivisible(dC)) return false
1070
-
1071
- // Check the first item (degree max)
1072
- return pX.isDivisible(dX);
1073
- })
1074
- }
1075
- }
1076
- }
1077
- }
1078
-
1079
- // Maybe there is still something in the Polynom (not everything was possible to factorize)
1080
- if (!P.isOne()) {
1081
- factors.push(P.clone())
1082
- }
1083
-
1084
- // Save the factors
1085
- this._factors = factors
1086
-
1087
- // The factors list is no more dirty
1088
- this.dirty_factors = false
1089
-
1090
- return this._factors;
1091
- }
1092
-
1093
- isDividableBy = (div: Polynom): boolean => {
1094
- // Quick evaluation.
1095
- if (div.degree().isOne()) {
1096
- let zero = div.getZeroes()[0]
1097
-
1098
- if (zero.exact instanceof Fraction) {
1099
- return this.evaluate(zero.exact).isZero()
1100
- } else {
1101
- return false
1102
- }
1103
- } else {
1104
- this.euclidianCache[div.tex] = this.euclidian(div)
1105
- return this.euclidianCache[div.tex].reminder.isZero()
1106
- }
1107
- }
1108
- // TODO: get zeroes for more than first degree and for more than natural degrees
1109
- getZeroes = (): ISolution[] => {
1110
- if (this.dirty_zeroes) {
1111
- let equ = new Equation(this.clone(), 0)
1112
- equ.solve()
1113
- this._zeroes = equ.solutions
1114
- this.dirty_zeroes = false
1115
- }
1116
-
1117
- return this._zeroes
1118
- };
1119
-
1120
- // TODO: analyse the next functions to determine if they are useful or not...
1121
- monomByDegree = (degree?: Fraction | number, letter?: string): Monom => {
1122
- if (degree === undefined) {
1123
- // return the highest degree monom.
1124
- return this.monomByDegree(this.degree(letter), letter);
1125
- }
1126
-
1127
- // Reduce the polynom.
1128
- const M = this.clone().reduce();
1129
- for (const m of M._monoms) {
1130
- if (m.degree(letter).isEqual(degree)) {
1131
- return m.clone();
1132
- }
1133
- }
1134
-
1135
- // Nothing was found - return the null monom.
1136
- return new Monom().zero();
1137
- };
1138
-
1139
- monomsByDegree = (degree?: number | Fraction, letter?: string): Monom[] => {
1140
- if (degree === undefined) {
1141
- // return the highest degree monom.
1142
- return this.monomsByDegree(this.degree(letter));
1143
- }
1144
-
1145
- // Reduce the polynom.
1146
- let Ms: Monom[] = [];
1147
-
1148
- const M = this.clone().reduce();
1149
- for (const m of M._monoms) {
1150
- if (m.degree(letter) === degree) {
1151
- Ms.push(m.clone())
1152
- }
1153
- }
1154
-
1155
- return Ms
1156
- // Nothing was found - retur
1157
- }
1158
-
1159
- // Used in LinearSystem.tex
1160
- monomByLetter = (letter: string): Monom => {
1161
- const M = this.clone().reduce();
1162
- for (const m of M._monoms) {
1163
- if (m.hasLetter(letter)) {
1164
- return m.clone();
1165
- }
1166
- }
1167
-
1168
- return new Monom().zero();
1169
- };
1170
-
1171
- // Next functions are used for for commonMonom, which is used in the factorize method.
1172
- getDenominators = (): number[] => {
1173
- const denominators: number[] = [];
1174
- for (const m of this._monoms) {
1175
- denominators.push(m.coefficient.denominator);
1176
- }
1177
- return denominators;
1178
- };
1179
-
1180
- getNumerators = (): number[] => {
1181
- const numerators: number[] = [];
1182
- for (const m of this._monoms) {
1183
- numerators.push(m.coefficient.numerator);
1184
- }
1185
- return numerators;
1186
- };
1187
-
1188
- lcmDenominator = (): number => {
1189
- return Numeric.lcm(...this.getDenominators());
1190
- };
1191
- // ------------------------------------------
1192
- // Polynoms factorization functions
1193
-
1194
- gcdDenominator = (): number => {
1195
- return Numeric.gcd(...this.getDenominators());
1196
- };
1197
-
1198
- lcmNumerator = (): number => {
1199
- return Numeric.lcm(...this.getNumerators());
1200
- };
1201
-
1202
- gcdNumerator = (): number => {
1203
- return Numeric.gcd(...this.getNumerators());
1204
- };
1205
- // ------------------------------------------
1206
- // Polynoms helpers functions
1207
- // -------------------------------------
1208
-
1209
- commonMonom = (): Monom => {
1210
- let M = new Monom().one(), numerator: number, denominator: number, degree = this.degree();
1211
-
1212
- numerator = this.gcdNumerator();
1213
- denominator = this.gcdDenominator();
1214
-
1215
- M.coefficient = new Fraction(numerator, denominator);
1216
- for (let L of this.variables) {
1217
- // Initialize the setLetter with the max degree
1218
- M.setLetter(L, degree);
1219
- for (let m of this._monoms) {
1220
- M.setLetter(L, Fraction.min(m.degree(L), M.degree(L)));
1221
- if (M.degree(L).isZero()) {
1222
- break;
1223
- }
1224
- }
1225
- }
1226
- return M;
1227
- }
1228
-
1229
- limitToInfinity = (letter?: string): Fraction => {
1230
- const M = this.monomByDegree(undefined, letter),
1231
- sign = M.coefficient.sign(),
1232
- degree = M.degree(letter)
1233
-
1234
- if (degree.isStrictlyPositive()) {
1235
- return sign === 1 ? (new Fraction()).infinite() : (new Fraction()).infinite().opposed()
1236
- } else if (degree.isZero()) {
1237
- return M.coefficient
1238
- }
1239
-
1240
- // Any other cases
1241
- return (new Fraction()).zero()
1242
- }
1243
- limitToNegativeInfinity = (letter?: string): Fraction => {
1244
- const M = this.monomByDegree(undefined, letter),
1245
- sign = M.coefficient.sign(),
1246
- degree = M.degree(letter)
1247
-
1248
- if (degree.isStrictlyPositive()) {
1249
- return sign === -1 ? (new Fraction()).infinite() : (new Fraction()).infinite().opposed()
1250
- } else if (degree.isZero()) {
1251
- return M.coefficient
1252
- }
1253
-
1254
- // Any other cases
1255
- return (new Fraction()).zero()
1256
- }
1257
-
1258
- private _getAllPotentialFactors = (P: Polynom, maxDegree: number, letter: string): Polynom[] => {
1259
- let m1 = P.monoms[0].dividers,
1260
- m2 = P.monoms[P.monoms.length - 1].dividers
1261
-
1262
- let allDividers: Polynom[] = []
1263
- m1.forEach(m1d => {
1264
- // Get only polynom that has a degree less than a specific value
1265
- if (m1d.degree(letter).leq(maxDegree)) {
1266
- m2.forEach(m2d => {
1267
- if (m1d.degree(letter).isNotEqual(m2d.degree(letter))) {
1268
- allDividers.push(new Polynom(m1d, m2d))
1269
- allDividers.push(new Polynom(m1d, m2d.clone().opposed()))
1270
- }
1271
- })
1272
- }
1273
- })
1274
-
1275
- return allDividers
1276
-
1277
- }
1278
-
1279
- private _parseString(inputStr: string, ...values: unknown[]): Polynom {
1280
- if (values === undefined || values.length === 0) {
1281
- inputStr = '' + inputStr;
1282
- this._rawString = inputStr.trim().replaceAll(' ', '');
1283
-
1284
- // Parse the polynom using the shutting yard algorithm
1285
- if (inputStr !== '' && !isNaN(Number(inputStr))) {
1286
- this.empty();
1287
- // It's a simple number.
1288
- let m = new Monom(inputStr);
1289
- // m.coefficient = new Fraction(inputStr);
1290
- // m.literalStr = '';
1291
- this.add(m);
1292
- return this;
1293
- }
1294
-
1295
- // Parse the string.
1296
- return this.shutingYardToReducedPolynom(inputStr);
1297
- } else if (/^[a-z]/.test(inputStr)) {
1298
- // We assume the inputStr contains only letters.
1299
- this.empty();
1300
-
1301
- let fractions = values.map(x => new Fraction(x));
1302
- // Multiple setLetter version
1303
- if (inputStr.length > 1) {
1304
- // TODO: check that the number of values given correspond to the letters (+1 eventually)
1305
- let letters = inputStr.split(''),
1306
- i = 0;
1307
- for (let F of fractions) {
1308
- let m = new Monom();
1309
- m.coefficient = F.clone();
1310
- m.literalStr = letters[i] || '';
1311
- this.add(m);
1312
- i++;
1313
- }
1314
- }
1315
- // Single setLetter version
1316
- else {
1317
- let n = fractions.length - 1;
1318
- for (let F of fractions) {
1319
- let m = new Monom()
1320
- m.coefficient = F.clone();
1321
- m.literalStr = `${inputStr}^${n}`
1322
- this.add(m);
1323
- n--;
1324
- }
1325
- }
1326
- return this;
1327
- } else {
1328
- return this.zero();
1329
- }
1330
- }
1331
-
1332
- private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean, withAllMultSign?: boolean): string => {
1333
- let P: string = '';
1334
-
1335
- for (const k of this._monoms) {
1336
- if (k.coefficient.value === 0) {
1337
- continue;
1338
- }
1339
-
1340
- // The monom to be displayed
1341
- let m
1342
- if (withAllMultSign) {
1343
- m = k.plotFunction
1344
- } else {
1345
- m = (output === 'tex') ? k.tex : k.display
1346
- }
1347
-
1348
- P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${m}`;
1349
- }
1350
-
1351
- if (wrapParentheses === true && this.length > 1) {
1352
- if (output === 'tex') {
1353
- P = `\\left( ${P} \\right)`;
1354
- } else {
1355
- P = `(${P})`;
1356
- }
1357
- }
1358
-
1359
- if (P === '') {
1360
- P = '0';
1361
- }
1362
- return P;
1363
- };
1364
-
1365
- /**
1366
- * Main parse using a shutting yard class
1367
- * @param inputStr
1368
- */
1369
- private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
1370
- // Get the RPN array of the current expression
1371
- const SY: Shutingyard = new Shutingyard().parse(inputStr);
1372
- const rpn: { token: string, tokenType: string }[] = SY.rpn;
1373
-
1374
- // New version for reducing shuting yard.
1375
- this.zero()
1376
-
1377
- let stack: Polynom[] = [],
1378
- monom: Monom = new Monom()
1379
-
1380
- // Loop through the
1381
- for (const element of rpn) {
1382
- this.addToken(stack, element);
1383
- }
1384
-
1385
- if (stack.length === 1) {
1386
- this.add(stack[0])
1387
- }
1388
-
1389
- return this.reorder()
1390
- }
1391
-
1392
- private multiplyByPolynom = (P: Polynom): Polynom => {
1393
- const M: Monom[] = [];
1394
- for (const m1 of this._monoms) {
1395
- for (const m2 of P.monoms) {
1396
- M.push(Monom.xmultiply(m1, m2));
1397
- }
1398
- }
1399
-
1400
- this._monoms = M;
1401
- return this.reduce();
1402
- };
1403
-
1404
- private multiplyByFraction = (F: Fraction): Polynom => {
1405
- for (const m of this._monoms) {
1406
- m.coefficient.multiply(F);
1407
- }
1408
-
1409
- return this.reduce();
1410
- };
1411
-
1412
- private multiplyByInteger = (nb: number): Polynom => {
1413
- return this.multiplyByFraction(new Fraction(nb));
1414
- };
1415
-
1416
- private multiplyByMonom = (M: Monom): Polynom => {
1417
- for (const m of this._monoms) {
1418
- m.multiply(M)
1419
- }
1420
- return this.reduce();
1421
- };
1422
-
1423
- private divideByInteger = (nb: number): Polynom => {
1424
- const nbF = new Fraction(nb);
1425
- for (const m of this._monoms) {
1426
- m.coefficient.divide(nbF);
1427
- }
1428
- return this;
1429
- };
1430
-
1431
- private divideByFraction = (F: Fraction): Polynom => {
1432
- for (const m of this._monoms) {
1433
- m.coefficient.divide(F);
1434
- }
1435
- return this;
1436
- };
1437
-
1438
- private _factorize2ndDegree = (letter: string): Polynom[] => {
1439
- let P1: Polynom, P2: Polynom,
1440
- a, b, c, delta, x1, x2, factor;
1441
-
1442
- // One variable only
1443
- if (this.numberOfVars === 1) {
1444
- a = this.monomByDegree(2, letter).coefficient;
1445
- b = this.monomByDegree(1, letter).coefficient;
1446
- c = this.monomByDegree(0, letter).coefficient;
1447
- delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
1448
-
1449
- if (delta.isZero()) {
1450
- x1 = b.clone().opposed().divide(a.clone().multiply(2))
1451
- P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
1452
- P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
1453
- factor = a.divide(x1.denominator).divide(x1.denominator);
1454
-
1455
- if (!factor.isOne()) {
1456
- // TODO: Update new Polynom to accept anything...
1457
- return [new Polynom(factor.display), P1, P2]
1458
- } else {
1459
- return [P1, P2]
1460
- }
1461
- } else if (delta.isPositive() && delta.isSquare()) {
1462
- x1 = b.clone().opposed()
1463
- .add(delta.clone().sqrt())
1464
- .divide(a.clone().multiply(2))
1465
- x2 = b.clone().opposed()
1466
- .subtract(delta.clone().sqrt())
1467
- .divide(a.clone().multiply(2))
1468
-
1469
- // (2x+5)(3x-2)
1470
- // 6x^2+11x-10
1471
- // a = 6, b = 11, c = -10
1472
- // delta = 121-4*6*(-10) = 361= 19^2
1473
- // x1 = (-11 + 19) / 12 = 8/12 = 2/3
1474
- // x2 = (-11 - 19) / 12 = -30/12 = -5/2
1475
- factor = a.divide(x1.denominator).divide(x2.denominator);
1476
- if (factor.isOne()) {
1477
- return [
1478
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1479
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1480
- ]
1481
- } else {
1482
- return [
1483
- new Polynom(factor.display),
1484
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1485
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1486
- ]
1487
-
1488
- }
1489
- } else {
1490
- // No solution possible - return the complete value.
1491
- return [this.clone()]
1492
- }
1493
- } else {
1494
- // If multiple variables, only handle perfect squares...
1495
- a = this.monomByDegree(2, letter);
1496
- b = this.monomByDegree(1, letter);
1497
- c = this.monomByDegree(0, letter);
1498
-
1499
-
1500
- if (a.isLiteralSquare() && c.isLiteralSquare()) {
1501
- // Check the middle item is same as...
1502
- if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
1503
- // Determine if the coefficient values matches.
1504
-
1505
- // Search 4 values (r, s, t, u) that matches:
1506
- // (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
1507
-
1508
- let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
1509
- let xFactors = xPolynom._factorize2ndDegree('x');
1510
-
1511
- let factors = [], xyzPolynom: Polynom;
1512
-
1513
- if (xFactors.length >= 2) {
1514
- for (let p of xFactors) {
1515
- if (p.degree().isZero()) {
1516
- factors.push(p.clone())
1517
- } else {
1518
- xyzPolynom = p.clone();
1519
- xyzPolynom.monoms[0].literal = a.literalSqrt
1520
- xyzPolynom.monoms[1].literal = c.literalSqrt
1521
- factors.push(xyzPolynom.clone())
1522
- }
1523
- }
1524
- return factors
1525
- }
1526
- }
1527
- }
1528
-
1529
- return [this.clone()]
1530
- }
1531
- }
1532
-
1533
- private _factorizeByGroups = (): Polynom[] => {
1534
- // TODO: Factorize by groups.
1535
- return [];
1536
- }
1537
- }