pimath 0.0.13 → 0.0.17

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 (123) hide show
  1. package/dev/index.html +9 -3
  2. package/dev/pi.js +364 -229
  3. package/dev/pi.js.map +1 -1
  4. package/dist/pi.js +1 -1
  5. package/dist/pi.js.map +1 -1
  6. package/docs/assets/search.js +1 -1
  7. package/docs/classes/algebra.Algebra.Equation.html +26 -0
  8. package/docs/classes/algebra.Algebra.LinearSystem.html +1 -0
  9. package/docs/classes/algebra.Algebra.LogicalSet.html +3 -0
  10. package/docs/classes/algebra.Algebra.Monom.html +36 -36
  11. package/docs/classes/algebra.Algebra.Polynom.html +11 -11
  12. package/docs/classes/algebra.Algebra.Rational.html +2 -0
  13. package/docs/classes/algebra.Equation.html +9 -9
  14. package/docs/classes/algebra.LinearSystem.html +1 -1
  15. package/docs/classes/algebra.Logicalset.html +2 -2
  16. package/docs/classes/algebra.Monom.html +36 -36
  17. package/docs/classes/algebra.Polynom.html +12 -12
  18. package/docs/classes/algebra.Rational.html +2 -2
  19. package/docs/classes/coefficients.Fraction.html +4 -4
  20. package/docs/classes/coefficients.Nthroot.html +1 -1
  21. package/docs/classes/geometry.Circle.html +1 -1
  22. package/docs/classes/geometry.Geometry.Circle.html +1 -0
  23. package/docs/classes/geometry.Geometry.Line.html +1 -0
  24. package/docs/classes/geometry.Geometry.Point.html +1 -0
  25. package/docs/classes/geometry.Geometry.Triangle.html +9 -0
  26. package/docs/classes/geometry.Geometry.Vector.html +1 -0
  27. package/docs/classes/geometry.Line.html +1 -1
  28. package/docs/classes/geometry.Point.html +1 -1
  29. package/docs/classes/geometry.Triangle.html +6 -6
  30. package/docs/classes/geometry.Vector.html +1 -1
  31. package/docs/classes/numeric.Numeric.html +5 -5
  32. package/docs/classes/shutingyard.Shutingyard.html +5 -5
  33. package/docs/interfaces/geometry.remarquableLines.html +1 -1
  34. package/docs/modules/algebra.Algebra.html +1 -1
  35. package/docs/modules/geometry.Geometry.html +1 -0
  36. package/docs/modules/geometry.html +1 -1
  37. package/docs/modules/random.Random.html +1 -1
  38. package/docs/modules/random.html +1 -1
  39. package/esm/main.js +24 -22
  40. package/esm/main.js.map +1 -1
  41. package/esm/maths/algebra/equation.d.ts +2 -1
  42. package/esm/maths/algebra/equation.js +29 -25
  43. package/esm/maths/algebra/equation.js.map +1 -1
  44. package/esm/maths/algebra/index.d.ts +0 -8
  45. package/esm/maths/algebra/index.js +18 -17
  46. package/esm/maths/algebra/index.js.map +1 -1
  47. package/esm/maths/algebra/linearSystem.d.ts +1 -1
  48. package/esm/maths/algebra/linearSystem.js +19 -15
  49. package/esm/maths/algebra/linearSystem.js.map +1 -1
  50. package/esm/maths/algebra/logicalset.js +7 -3
  51. package/esm/maths/algebra/logicalset.js.map +1 -1
  52. package/esm/maths/algebra/monom.d.ts +14 -17
  53. package/esm/maths/algebra/monom.js +164 -75
  54. package/esm/maths/algebra/monom.js.map +1 -1
  55. package/esm/maths/algebra/polynom.d.ts +6 -24
  56. package/esm/maths/algebra/polynom.js +57 -206
  57. package/esm/maths/algebra/polynom.js.map +1 -1
  58. package/esm/maths/algebra/rational.js +15 -10
  59. package/esm/maths/algebra/rational.js.map +1 -1
  60. package/esm/maths/coefficients/fraction.d.ts +20 -10
  61. package/esm/maths/coefficients/fraction.js +83 -15
  62. package/esm/maths/coefficients/fraction.js.map +1 -1
  63. package/esm/maths/coefficients/index.js +14 -2
  64. package/esm/maths/coefficients/index.js.map +1 -1
  65. package/esm/maths/coefficients/nthroot.js +5 -1
  66. package/esm/maths/coefficients/nthroot.js.map +1 -1
  67. package/esm/maths/geometry/circle.js +12 -8
  68. package/esm/maths/geometry/circle.js.map +1 -1
  69. package/esm/maths/geometry/index.js +17 -5
  70. package/esm/maths/geometry/index.js.map +1 -1
  71. package/esm/maths/geometry/line.js +26 -22
  72. package/esm/maths/geometry/line.js.map +1 -1
  73. package/esm/maths/geometry/point.js +16 -12
  74. package/esm/maths/geometry/point.js.map +1 -1
  75. package/esm/maths/geometry/triangle.js +31 -27
  76. package/esm/maths/geometry/triangle.js.map +1 -1
  77. package/esm/maths/geometry/vector.js +21 -17
  78. package/esm/maths/geometry/vector.js.map +1 -1
  79. package/esm/maths/numeric.js +5 -1
  80. package/esm/maths/numeric.js.map +1 -1
  81. package/esm/maths/random/index.d.ts +3 -1
  82. package/esm/maths/random/index.js +32 -14
  83. package/esm/maths/random/index.js.map +1 -1
  84. package/esm/maths/random/randomCore.js +5 -1
  85. package/esm/maths/random/randomCore.js.map +1 -1
  86. package/esm/maths/random/rndFraction.d.ts +9 -0
  87. package/esm/maths/random/rndFraction.js +30 -0
  88. package/esm/maths/random/rndFraction.js.map +1 -0
  89. package/esm/maths/random/rndHelpers.js +5 -1
  90. package/esm/maths/random/rndHelpers.js.map +1 -1
  91. package/esm/maths/random/rndMonom.d.ts +2 -2
  92. package/esm/maths/random/rndMonom.js +15 -8
  93. package/esm/maths/random/rndMonom.js.map +1 -1
  94. package/esm/maths/random/rndPolynom.d.ts +1 -1
  95. package/esm/maths/random/rndPolynom.js +22 -10
  96. package/esm/maths/random/rndPolynom.js.map +1 -1
  97. package/esm/maths/random/rndTypes.d.ts +5 -0
  98. package/esm/maths/random/rndTypes.js +2 -1
  99. package/esm/maths/shutingyard.js +5 -1
  100. package/esm/maths/shutingyard.js.map +1 -1
  101. package/package.json +5 -5
  102. package/src/maths/algebra/equation.ts +6 -5
  103. package/src/maths/algebra/index.ts +1 -9
  104. package/src/maths/algebra/linearSystem.ts +3 -3
  105. package/src/maths/algebra/monom.ts +759 -622
  106. package/src/maths/algebra/monom_bck.backup +746 -0
  107. package/src/maths/algebra/polynom.ts +980 -1170
  108. package/src/maths/algebra/rational.ts +6 -6
  109. package/src/maths/coefficients/fraction.ts +98 -27
  110. package/src/maths/geometry/index.ts +1 -1
  111. package/src/maths/geometry/line.ts +1 -1
  112. package/src/maths/random/index.ts +9 -3
  113. package/src/maths/random/rndFraction.ts +37 -0
  114. package/src/maths/random/rndMonom.ts +6 -3
  115. package/src/maths/random/rndPolynom.ts +15 -5
  116. package/src/maths/random/rndTypes.ts +5 -0
  117. package/src/maths/shutingyard.ts +2 -0
  118. package/tests/algebra/monom.test.ts +29 -8
  119. package/tests/algebra/polynom.test.ts +13 -22
  120. package/tests/coefficients/fraction.test.ts +35 -38
  121. package/tests/shutingyard.test.ts +0 -1
  122. package/tsconfig.json +1 -1
  123. package/tsconfig.testing.json +28 -0
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * Polynom module contains everything necessary to handle polynoms.*
3
- * @module Polynom
4
3
  */
5
4
 
6
- import {Monom} from './monom';
5
+ import {literalType, Monom} from './monom';
7
6
  import {Shutingyard} from '../shutingyard';
8
7
  import {Numeric} from '../numeric';
9
- import {Random} from "../random";
10
- import {Fraction} from "../coefficients/fraction";
8
+ import {Random, randomPolynomConfig} from "../random";
9
+ import {Fraction} from "../coefficients";
11
10
 
12
11
  /**
13
12
  * Polynom class can handle polynoms, reorder, resolve, ...
@@ -15,1373 +14,1184 @@ import {Fraction} from "../coefficients/fraction";
15
14
  * let P = new Polynom('3x-4')
16
15
  * ```
17
16
  */
18
- export class Polynom {
19
- private _rawString: string;
20
- private _monoms: Monom[];
21
- private _factors: Polynom[];
22
- private _texString: string;
23
-
24
- /**
25
- *
26
- * @param {string} polynomString (optional) Default polynom to parse on class creation
27
- * @param values
28
- */
29
- constructor(polynomString?: string, ...values: any[]) {
30
- this._monoms = [];
31
- this._factors = [];
32
- if (polynomString !== undefined) {
33
- this.parse(polynomString, ...values);
34
- }
35
- return this;
17
+ export class Polynom {
18
+ private _rawString: string;
19
+ private _monoms: Monom[];
20
+ private _factors: Polynom[];
21
+ private _texString: string;
22
+
23
+ /**
24
+ *
25
+ * @param {string} polynomString (optional) Default polynom to parse on class creation
26
+ * @param values
27
+ */
28
+ constructor(polynomString?: string, ...values: any[]) {
29
+ this._monoms = [];
30
+ this._factors = [];
31
+ if (polynomString !== undefined) {
32
+ this.parse(polynomString, ...values);
36
33
  }
34
+ return this;
35
+ }
37
36
 
38
- get isPolynom() {
39
- return true;
40
- };
37
+ get isPolynom() {
38
+ return true;
39
+ };
41
40
 
42
41
 
43
- // ------------------------------------------
44
- // Getter and setter
45
- // ------------------------------------------
46
- get monoms() {
47
- return this._monoms;
48
- }
42
+ // ------------------------------------------
43
+ // Getter and setter
44
+ // ------------------------------------------
45
+ get monoms() {
46
+ return this._monoms;
47
+ }
49
48
 
50
- set monoms(M: Monom[]) {
51
- this._monoms = M;
52
- }
49
+ set monoms(M: Monom[]) {
50
+ this._monoms = M;
51
+ }
53
52
 
54
- get factors(): Polynom[] {
55
- return this._factors;
56
- }
53
+ get factors(): Polynom[] {
54
+ return this._factors;
55
+ }
57
56
 
58
- set factors(value: Polynom[]) {
59
- this._factors = value;
60
- }
57
+ set factors(value: Polynom[]) {
58
+ this._factors = value;
59
+ }
61
60
 
62
- get texFactors(): string {
63
- this.factorize()
61
+ get texFactors(): string {
62
+ this.factorize()
64
63
 
65
- let tex = ''
66
- for (let f of this.factors) {
67
- if (f.monoms.length > 1) {
68
- tex += `(${f.tex})`
69
- } else {
70
- tex = f.tex + tex;
71
- }
64
+ let tex = ''
65
+ for (let f of this.factors) {
66
+ if (f.monoms.length > 1) {
67
+ tex += `(${f.tex})`
68
+ } else {
69
+ tex = f.tex + tex;
72
70
  }
73
- return tex;
74
71
  }
72
+ return tex;
73
+ }
75
74
 
76
- get texString(): string {
77
- return this._texString;
78
- }
75
+ get texString(): string {
76
+ return this._texString;
77
+ }
79
78
 
80
- get length() {
81
- // TODO: Must reduce the monoms list to remove the zero coefficient.
82
- return this._monoms.length;
83
- }
79
+ get length() {
80
+ // TODO: Must reduce the monoms list to remove the zero coefficient.
81
+ return this._monoms.length;
82
+ }
84
83
 
85
- get display(): string {
86
- return this.genDisplay();
87
- }
84
+ get display(): string {
85
+ return this.genDisplay();
86
+ }
88
87
 
89
- get raw(): string {
90
- return this._rawString
91
- }
88
+ get raw(): string {
89
+ return this._rawString
90
+ }
92
91
 
93
- get tex(): string {
94
- return this.genDisplay('tex');
95
- }
92
+ get tex(): string {
93
+ return this.genDisplay('tex');
94
+ }
96
95
 
97
- get isMultiVariable(): boolean {
98
- const B = false;
99
- for (const m of this._monoms) {
100
- if (m.variables.length > 1) {
101
- return true;
102
- }
96
+ get isMultiVariable(): boolean {
97
+ const B = false;
98
+ for (const m of this._monoms) {
99
+ if (m.variables.length > 1) {
100
+ return true;
103
101
  }
104
- return B;
105
102
  }
103
+ return B;
104
+ }
106
105
 
107
- get variables(): string[] {
108
- let V: string[] = [];
109
-
110
- for (const m of this._monoms) {
111
- V = V.concat(m.variables);
112
- }
113
-
114
- // Remove duplicates.
115
- V = [...new Set(V)];
106
+ get variables(): string[] {
107
+ let V: string[] = [];
116
108
 
117
- return V;
109
+ for (const m of this._monoms) {
110
+ V = V.concat(m.variables);
118
111
  }
119
112
 
120
- get numberOfVars(): number {
121
- return this.variables.length;
122
- }
113
+ // Remove duplicates.
114
+ V = [...new Set(V)];
123
115
 
124
- private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean): string => {
125
- let P: string = '';
116
+ return V;
117
+ }
126
118
 
127
- for (const k of this._monoms) {
128
- if (k.coefficient.value === 0) {
129
- continue;
130
- }
119
+ get numberOfVars(): number {
120
+ return this.variables.length;
121
+ }
131
122
 
132
- P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${(output === 'tex') ? k.tex : k.display}`;
133
- }
123
+ private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean): string => {
124
+ let P: string = '';
134
125
 
135
- if (wrapParentheses === true && this.length > 1) {
136
- if (output === 'tex') {
137
- P = `\\left( ${P} \\right)`;
138
- } else {
139
- P = `(${P})`;
140
- }
126
+ for (const k of this._monoms) {
127
+ if (k.coefficient.value === 0) {
128
+ continue;
141
129
  }
142
130
 
143
- if (P === '') {
144
- P = '0';
131
+ P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${(output === 'tex') ? k.tex : k.display}`;
132
+ }
133
+
134
+ if (wrapParentheses === true && this.length > 1) {
135
+ if (output === 'tex') {
136
+ P = `\\left( ${P} \\right)`;
137
+ } else {
138
+ P = `(${P})`;
145
139
  }
146
- return P;
147
- };
148
-
149
-
150
- // ------------------------------------------
151
- // Creation / parsing functions
152
- // ------------------------------------------
153
- /**
154
- * Parse a string to a polynom.
155
- * @param inputStr
156
- * @param values: as string, numbers or fractions
157
- */
158
- parse = (inputStr: string, ...values: any[]): Polynom => {
159
- if (values === undefined || values.length === 0) {
160
- inputStr = '' + inputStr;
161
- this._rawString = inputStr;
162
-
163
- // Parse the polynom using the shuting yard algorithm
164
- if (inputStr !== '' && !isNaN(Number(inputStr))) {
165
- this.empty();
166
- // It's a simple number.
167
- let m = new Monom();
168
- m.coefficient = new Fraction(inputStr);
169
- m.literalStr = '';
170
- this.add(m);
171
- return this;
172
- }
140
+ }
173
141
 
174
- // Parse the string.
175
- return this.shutingYardToReducedPolynom(inputStr);
176
- } else if (/^[a-z]/.test(inputStr)) {
177
- // We assume the inputStr contains only letters.
142
+ if (P === '') {
143
+ P = '0';
144
+ }
145
+ return P;
146
+ };
147
+
148
+
149
+ // ------------------------------------------
150
+ // Creation / parsing functions
151
+ // ------------------------------------------
152
+ /**
153
+ * Parse a string to a polynom.
154
+ * @param inputStr
155
+ * @param values: as string, numbers or fractions
156
+ */
157
+ parse = (inputStr: string, ...values: any[]): Polynom => {
158
+
159
+ if (values === undefined || values.length === 0) {
160
+ inputStr = '' + inputStr;
161
+ this._rawString = inputStr;
162
+
163
+ // Parse the polynom using the shuting yard algorithm
164
+ if (inputStr !== '' && !isNaN(Number(inputStr))) {
178
165
  this.empty();
179
-
180
- let fractions = values.map(x => new Fraction(x));
181
- // Multiple setLetter version
182
- if (inputStr.length > 1) {
183
- // TODO: check that the number of values given correspond to the letters (+1 eventually)
184
- let letters = inputStr.split(''),
185
- i = 0;
186
- for (let F of fractions) {
187
- let m = new Monom();
188
- m.coefficient = F.clone();
189
- m.literalStr = letters[i] || '';
190
- this.add(m);
191
- i++;
192
- }
193
- }
194
- // Single setLetter version
195
- else {
196
- let n = fractions.length - 1;
197
- for (let F of fractions) {
198
- let m = new Monom()
199
- m.coefficient = F.clone();
200
- m.literalStr = `${inputStr}^${n}`
201
- this.add(m);
202
- n--;
203
- }
204
- }
166
+ // It's a simple number.
167
+ let m = new Monom(inputStr);
168
+ // m.coefficient = new Fraction(inputStr);
169
+ // m.literalStr = '';
170
+ this.add(m);
205
171
  return this;
206
- } else {
207
- return this.zero();
208
172
  }
209
173
 
210
- };
211
-
212
- /**
213
- * Main parse using a shutting yard class
214
- * @param inputStr
215
- */
216
- private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
217
- // Get the RPN array of the current expression
218
- const SY: Shutingyard = new Shutingyard().parse(inputStr);
219
- const rpn: { token: string, tokenType: string }[] = SY.rpn;
220
- let m1: Polynom;
221
- let m2: Polynom;
222
-
223
- let stack: Polynom[] = [],
224
- previousToken: string = null,
225
- tempPolynom
226
- for (const element of rpn) {
227
- if (element.tokenType === 'coefficient' || element.tokenType === 'variable') {
228
- tempPolynom = new Polynom().zero();
229
- tempPolynom.monoms = [new Monom(element.token)]
230
- stack.push(tempPolynom.clone())
231
- } else if (element.tokenType === 'operation') {
232
- m2 = (stack.pop()) || new Polynom().zero();
233
- m1 = (stack.pop()) || new Polynom().zero();
234
- switch (element.token) {
235
- case '+':
236
- stack.push(m1.add(m2))
237
- break;
238
- case '-':
239
- stack.push(m1.subtract(m2))
240
- break;
241
- case '*':
242
- stack.push(m1.multiply(m2))
243
- break;
244
- case '^':
245
- stack.push(m1.pow(+previousToken))
246
- }
174
+ // Parse the string.
175
+ return this.shutingYardToReducedPolynom(inputStr);
176
+ } else if (/^[a-z]/.test(inputStr)) {
177
+ // We assume the inputStr contains only letters.
178
+ this.empty();
179
+
180
+ let fractions = values.map(x => new Fraction(x));
181
+ // Multiple setLetter version
182
+ if (inputStr.length > 1) {
183
+ // TODO: check that the number of values given correspond to the letters (+1 eventually)
184
+ let letters = inputStr.split(''),
185
+ i = 0;
186
+ for (let F of fractions) {
187
+ let m = new Monom();
188
+ m.coefficient = F.clone();
189
+ m.literalStr = letters[i] || '';
190
+ this.add(m);
191
+ i++;
247
192
  }
248
- previousToken = element.token;
249
193
  }
250
-
251
- this._monoms = stack[0].monoms;
252
- return this;
253
- }
254
-
255
- /**
256
- * Clone the polynom
257
- */
258
- clone = (): Polynom => {
259
- const P = new Polynom();
260
- const M: Monom[] = [];
261
-
262
- for (const m of this._monoms) {
263
- M.push(m.clone());
194
+ // Single setLetter version
195
+ else {
196
+ let n = fractions.length - 1;
197
+ for (let F of fractions) {
198
+ let m = new Monom()
199
+ m.coefficient = F.clone();
200
+ m.literalStr = `${inputStr}^${n}`
201
+ this.add(m);
202
+ n--;
203
+ }
264
204
  }
265
-
266
- P.monoms = M;
267
- return P;
268
- };
269
-
270
- /**
271
- * Set the polynom to zero.
272
- * @returns {this}
273
- */
274
- zero = (): Polynom => {
275
- this._monoms = [];
276
- this._monoms.push(new Monom().zero());
277
- this._rawString = '0';
278
205
  return this;
279
- };
280
-
281
- one = (): Polynom => {
282
- this._monoms = [];
283
- this._monoms.push(new Monom().one());
284
- this._rawString = '1';
285
- return this;
286
- }
287
-
288
- empty = (): Polynom => {
289
- this._monoms = [];
290
- this._rawString = '';
291
- return this;
292
- };
293
-
294
- // -----------------------------------------------
295
- // Polynom generators and randomizers
296
- // -----------------------------------------------
297
- private _randomizeDefaults: { [key: string]: number | string | boolean } = {
298
- degree: 2,
299
- unit: true,
300
- fractions: false,
301
- factorable: false,
302
- letters: 'x',
303
- allowNullMonom: false,
304
- numberOfMonoms: false
305
- };
306
- get randomizeDefaults(): { [key: string]: number | string | boolean } {
307
- return this._randomizeDefaults;
206
+ } else {
207
+ return this.zero();
308
208
  }
309
209
 
310
- set randomizeDefaults(value) {
311
- this._randomizeDefaults = value;
312
- }
313
-
314
- randomize = (config: { [key: string]: number | string | boolean }): Polynom => {
315
- let P = new Polynom();
316
-
317
- // Check the config file and use the default values.
318
- if (config === undefined) {
319
- config = {};
320
- }
321
- for (let k in this._randomizeDefaults) {
322
- if (config[k] === undefined) {
323
- config[k] = this._randomizeDefaults[k];
210
+ };
211
+
212
+ /**
213
+ * Main parse using a shutting yard class
214
+ * @param inputStr
215
+ */
216
+ private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
217
+ // Get the RPN array of the current expression
218
+ const SY: Shutingyard = new Shutingyard().parse(inputStr);
219
+ const rpn: { token: string, tokenType: string }[] = SY.rpn;
220
+ let m1: Polynom;
221
+ let m2: Polynom;
222
+
223
+ let stack: Polynom[] = [],
224
+ previousToken: string = null,
225
+ tempPolynom
226
+
227
+ for (const element of rpn) {
228
+ if (element.tokenType === 'coefficient' || element.tokenType === 'variable') {
229
+ tempPolynom = new Polynom().zero();
230
+ tempPolynom.monoms = [new Monom(element.token)]
231
+ stack.push(tempPolynom.clone())
232
+ } else if (element.tokenType === 'operation') {
233
+ m2 = (stack.pop()) || new Polynom().zero();
234
+ m1 = (stack.pop()) || new Polynom().zero();
235
+ switch (element.token) {
236
+ case '+':
237
+ stack.push(m1.add(m2))
238
+ break;
239
+ case '-':
240
+ stack.push(m1.subtract(m2))
241
+ break;
242
+ case '*':
243
+ stack.push(m1.multiply(m2))
244
+ break;
245
+ case '^':
246
+ stack.push(m1.pow(+previousToken))
324
247
  }
325
248
  }
326
-
327
- // TODO: Build a more robust randomize function
328
- return P;
249
+ previousToken = element.token;
329
250
  }
330
251
 
331
- rndFactorable = (degree: number = 2, unit: boolean | number = false, letters: string = 'x'): Polynom => {
332
- // TODO: Make rndFactorable polynom generator more user friendly
333
- this._factors = [];
334
- for (let i = 0; i < degree; i++) {
335
- let factorUnit = unit === true || i >= unit,
336
- p = Random.polynom({
337
- degree: 1,
338
- unit: factorUnit,
339
- fraction: false,
340
- letters
341
- });
342
- this._factors.push(p);
343
- }
252
+ this._monoms = stack[0].monoms;
253
+ return this;
254
+ }
344
255
 
345
- this.empty().monoms = this._factors[0].monoms;
346
- for (let i = 1; i < this._factors.length; i++) {
347
- this.multiply(this._factors[i]);
348
- }
349
- return this;
350
- };
256
+ /**
257
+ * Clone the polynom
258
+ */
259
+ clone = (): Polynom => {
260
+ const P = new Polynom();
261
+ const M: Monom[] = [];
351
262
 
352
- // ------------------------------------------
353
- // Mathematical operations
354
- // ------------------------------------------
355
- opposed = (): Polynom => {
356
- this._monoms = this._monoms.map(m => m.opposed());
357
- return this;
358
- };
263
+ for (const m of this._monoms) {
264
+ M.push(m.clone());
265
+ }
359
266
 
360
- add = (...values: any[]): Polynom => {
267
+ P.monoms = M;
268
+ return P;
269
+ };
270
+
271
+ /**
272
+ * Set the polynom to zero.
273
+ * @returns {this}
274
+ */
275
+ zero = (): Polynom => {
276
+ this._monoms = [];
277
+ this._monoms.push(new Monom().zero());
278
+ this._rawString = '0';
279
+ return this;
280
+ };
281
+
282
+ one = (): Polynom => {
283
+ this._monoms = [];
284
+ this._monoms.push(new Monom().one());
285
+ this._rawString = '1';
286
+ return this;
287
+ }
361
288
 
362
- for (let value of values) {
363
- if (value.isPolynom) {
364
- this._monoms = this._monoms.concat(value.monoms);
365
- } else if (value.isMonom) {
366
- this._monoms.push(value.clone());
367
- } else if (Number.isSafeInteger(value)) {
368
- this._monoms.push(new Monom(value.toString()));
369
- } else {
370
- this._monoms.push(new Monom(value));
371
- }
289
+ empty = (): Polynom => {
290
+ this._monoms = [];
291
+ this._rawString = '';
292
+ return this;
293
+ };
294
+
295
+ // // -----------------------------------------------
296
+ // // Polynom generators and randomizers
297
+ // // -----------------------------------------------
298
+ // random(config?: randomPolynomConfig) {
299
+ // return Random.polynom(config);
300
+ // }
301
+ //
302
+ // private _randomizeDefaults: { [key: string]: number | string | boolean } = {
303
+ // degree: 2,
304
+ // unit: true,
305
+ // fractions: false,
306
+ // factorable: false,
307
+ // letters: 'x',
308
+ // allowNullMonom: false,
309
+ // numberOfMonoms: false
310
+ // };
311
+ // get randomizeDefaults(): { [key: string]: number | string | boolean } {
312
+ // return this._randomizeDefaults;
313
+ // }
314
+ //
315
+ // set randomizeDefaults(value) {
316
+ // this._randomizeDefaults = value;
317
+ // }
318
+ //
319
+ // randomize = (config: { [key: string]: number | string | boolean }): Polynom => {
320
+ // let P = new Polynom();
321
+ //
322
+ // // Check the config file and use the default values.
323
+ // if (config === undefined) {
324
+ // config = {};
325
+ // }
326
+ // for (let k in this._randomizeDefaults) {
327
+ // if (config[k] === undefined) {
328
+ // config[k] = this._randomizeDefaults[k];
329
+ // }
330
+ // }
331
+ //
332
+ // // TODO: Build a more robust randomize function
333
+ // return P;
334
+ // }
335
+ //
336
+ // rndFactorable = (degree: number = 2, unit: boolean | number = false, letters: string = 'x'): Polynom => {
337
+ // // TODO: Make rndFactorable polynom generator more user friendly
338
+ // this._factors = [];
339
+ // for (let i = 0; i < degree; i++) {
340
+ // let factorUnit = unit === true || i >= unit,
341
+ // p = Random.polynom({
342
+ // degree: 1,
343
+ // unit: factorUnit,
344
+ // fraction: false,
345
+ // letters
346
+ // });
347
+ // this._factors.push(p);
348
+ // }
349
+ //
350
+ // this.empty().monoms = this._factors[0].monoms;
351
+ // for (let i = 1; i < this._factors.length; i++) {
352
+ // this.multiply(this._factors[i]);
353
+ // }
354
+ // return this;
355
+ // };
356
+
357
+ // ------------------------------------------
358
+ // Mathematical operations
359
+ // ------------------------------------------
360
+ opposed = (): Polynom => {
361
+ this._monoms = this._monoms.map(m => m.opposed());
362
+ return this;
363
+ };
364
+
365
+ add = (...values: any[]): Polynom => {
366
+
367
+ for (let value of values) {
368
+ if (value.isPolynom) {
369
+ this._monoms = this._monoms.concat(value.monoms);
370
+ } else if (value.isMonom) {
371
+ this._monoms.push(value.clone());
372
+ } else if (Number.isSafeInteger(value)) {
373
+ this._monoms.push(new Monom(value.toString()));
374
+ } else {
375
+ this._monoms.push(new Monom(value));
372
376
  }
377
+ }
373
378
 
374
- return this.reduce();
375
- };
376
-
377
- subtract = (...values: any[]): Polynom => {
378
-
379
- for (let value of values) {
380
- if (value.isPolynom) {
381
- this._monoms = this._monoms.concat(value.clone().opposed().monoms);
382
- } else if (value.isMonom) {
383
- this._monoms.push(value.clone().opposed());
384
- } else if (Number.isSafeInteger(value)) {
385
- this._monoms.push(new Monom(value.toString()).opposed());
386
- } else {
387
- this._monoms.push(new Monom(value).opposed());
388
- }
389
- }
379
+ return this.reduce();
380
+ };
390
381
 
391
- return this.reduce();
392
- };
382
+ subtract = (...values: any[]): Polynom => {
393
383
 
394
- multiply = (value: any): Polynom => {
384
+ for (let value of values) {
395
385
  if (value.isPolynom) {
396
- return this.multiplyByPolynom(value);
397
- } else if (value.isFraction) {
398
- return this.multiplyByFraction(value);
386
+ this._monoms = this._monoms.concat(value.clone().opposed().monoms);
399
387
  } else if (value.isMonom) {
400
- return this.multiplyByMonom(value);
388
+ this._monoms.push(value.clone().opposed());
401
389
  } else if (Number.isSafeInteger(value)) {
402
- return this.multiplyByInteger(value);
390
+ this._monoms.push(new Monom(value.toString()).opposed());
391
+ } else {
392
+ this._monoms.push(new Monom(value).opposed());
403
393
  }
404
-
405
- // Something went wrong...
406
- return this;
407
394
  }
408
395
 
409
- private multiplyByPolynom = (P: Polynom): Polynom => {
410
- const M: Monom[] = [];
411
- for (const m1 of this._monoms) {
412
- for (const m2 of P.monoms) {
413
- M.push(Monom.xmultiply(m1, m2));
414
- }
415
- }
396
+ return this.reduce();
397
+ };
398
+
399
+ multiply = (value: any): Polynom => {
400
+ if (value instanceof Polynom) {
401
+ return this.multiplyByPolynom(value);
402
+ } else if (value instanceof Fraction) {
403
+ return this.multiplyByFraction(value);
404
+ } else if (value instanceof Monom) {
405
+ return this.multiplyByMonom(value);
406
+ } else if (Number.isSafeInteger(value)) {
407
+ return this.multiplyByInteger(value);
408
+ }
416
409
 
417
- this._monoms = M;
418
- return this.reduce();
419
- };
410
+ // Something went wrong...
411
+ return this;
412
+ }
420
413
 
421
- private multiplyByFraction = (F: Fraction): Polynom => {
422
- for (const m of this._monoms) {
423
- m.coefficient.multiply(F);
414
+ private multiplyByPolynom = (P: Polynom): Polynom => {
415
+ const M: Monom[] = [];
416
+ for (const m1 of this._monoms) {
417
+ for (const m2 of P.monoms) {
418
+ M.push(Monom.xmultiply(m1, m2));
424
419
  }
420
+ }
425
421
 
426
- return this.reduce();
427
- };
422
+ this._monoms = M;
423
+ return this.reduce();
424
+ };
428
425
 
429
- private multiplyByInteger = (nb: number): Polynom => {
430
- return this.multiplyByFraction(new Fraction(nb));
431
- };
426
+ private multiplyByFraction = (F: Fraction): Polynom => {
427
+ for (const m of this._monoms) {
428
+ m.coefficient.multiply(F);
429
+ }
432
430
 
433
- private multiplyByMonom = (M: Monom): Polynom => {
434
- for (const m of this._monoms) {
435
- m.multiply(M)
436
- }
437
- return this.reduce();
438
- };
439
-
440
- /**
441
- * Divide the current polynom by another polynom.
442
- * @param P
443
- * returns {quotient: Polynom, reminder: Polynom}
444
- */
445
- euclidian = (P: Polynom): { quotient: Polynom, reminder: Polynom } => {
446
- const letter: string = P.variables[0];
447
- const quotient: Polynom = new Polynom().zero();
448
- const reminder: Polynom = this.clone().reorder(letter);
449
-
450
- // There is no variable !
451
- if (P.variables.length === 0) {
452
- return {quotient, reminder}
453
- }
431
+ return this.reduce();
432
+ };
433
+
434
+ private multiplyByInteger = (nb: number): Polynom => {
435
+ return this.multiplyByFraction(new Fraction(nb));
436
+ };
454
437
 
455
- // Get at least a letter
438
+ private multiplyByMonom = (M: Monom): Polynom => {
439
+ for (const m of this._monoms) {
440
+ m.multiply(M)
441
+ }
442
+ return this.reduce();
443
+ };
444
+
445
+ /**
446
+ * Divide the current polynom by another polynom.
447
+ * @param P
448
+ * returns {quotient: Polynom, reminder: Polynom}
449
+ */
450
+ euclidian = (P: Polynom): { quotient: Polynom, reminder: Polynom } => {
451
+ const letter: string = P.variables[0];
452
+ const quotient: Polynom = new Polynom().zero();
453
+ const reminder: Polynom = this.clone().reorder(letter);
454
+
455
+ // There is no variable !
456
+ if (P.variables.length === 0) {
457
+ return {quotient, reminder}
458
+ }
456
459
 
457
- const maxMP: Monom = P.monomByDegree(undefined, letter);
458
- const degreeP: number = P.degree(letter);
460
+ // Get at least a letter
459
461
 
460
- let newM: Monom;
462
+ const maxMP: Monom = P.monomByDegree(undefined, letter);
463
+ const degreeP: Fraction = P.degree(letter);
461
464
 
462
- // Make the euclidian division of the two polynoms.
463
- let MaxIteration = this.degree(letter) * 2;
464
- while (reminder.degree(letter) >= degreeP && MaxIteration >= 0) {
465
- // console.log('EUCLIDE Q', quotient.degree(letter), quotient.tex)
466
- // console.log('EUCLIDE R', reminder.degree(letter), reminder.tex)
467
- // console.log('ITERATION', MaxIteration)
468
- MaxIteration--
465
+ let newM: Monom;
469
466
 
470
- // Get the greatest monom divided by the max monom of the divider
471
- newM = reminder.monomByDegree(undefined, letter).clone().divide(maxMP);
467
+ // Make the euclidian division of the two polynoms.
468
+ let MaxIteration = this.degree(letter).clone().multiply(2);
469
+ while (reminder.degree(letter) >= degreeP && MaxIteration.isPositive()) {
470
+ MaxIteration.subtract(1)
472
471
 
473
- if (newM.isZero()) {
474
- break;
475
- }
472
+ // Get the greatest monom divided by the max monom of the divider
473
+ newM = reminder.monomByDegree(undefined, letter).clone().divide(maxMP);
476
474
 
477
- // Get the new quotient and reminder.
478
- quotient.add(newM);
479
- reminder.subtract(P.clone().multiply(newM));
475
+ if (newM.isZero()) {
476
+ break;
480
477
  }
481
478
 
482
- return {quotient, reminder};
483
- };
479
+ // Get the new quotient and reminder.
480
+ quotient.add(newM);
481
+ reminder.subtract(P.clone().multiply(newM));
482
+ }
484
483
 
485
- divide = (value: any): Polynom => {
486
- if (value.isFraction) {
487
- this.divideByFraction(value);
488
- } else if (Number.isSafeInteger(value)) {
489
- return this.divideByInteger(value);
490
- }
484
+ return {quotient, reminder};
485
+ };
486
+
487
+ divide = (value: any): Polynom => {
488
+ if (value.isFraction) {
489
+ this.divideByFraction(value);
490
+ } else if (Number.isSafeInteger(value)) {
491
+ return this.divideByInteger(value);
491
492
  }
493
+ }
492
494
 
493
- private divideByInteger = (nb: number): Polynom => {
494
- const nbF = new Fraction(nb);
495
- for (const m of this._monoms) {
496
- m.coefficient.divide(nbF);
497
- }
498
- return this;
499
- };
495
+ private divideByInteger = (nb: number): Polynom => {
496
+ const nbF = new Fraction(nb);
497
+ for (const m of this._monoms) {
498
+ m.coefficient.divide(nbF);
499
+ }
500
+ return this;
501
+ };
500
502
 
501
- private divideByFraction = (F: Fraction): Polynom => {
502
- for (const m of this._monoms) {
503
- m.coefficient.divide(F);
504
- }
505
- return this;
506
- };
503
+ private divideByFraction = (F: Fraction): Polynom => {
504
+ for (const m of this._monoms) {
505
+ m.coefficient.divide(F);
506
+ }
507
+ return this;
508
+ };
507
509
 
508
- pow = (nb: number): Polynom => {
509
- if (!Number.isSafeInteger(nb)) {
510
- return this.zero();
511
- }
512
- if (nb < 0) {
513
- return this.zero();
514
- }
515
- if (nb === 0) {
516
- return new Polynom();
517
- }
510
+ pow = (nb: number): Polynom => {
511
+ if (!Number.isSafeInteger(nb)) {
512
+ return this.zero();
513
+ }
514
+ if (nb < 0) {
515
+ return this.zero();
516
+ }
517
+ if (nb === 0) {
518
+ return new Polynom();
519
+ }
518
520
 
519
- const P = this.clone();
520
- for (let i = 1; i < nb; i++) {
521
- this.multiply(P);
522
- }
523
- return this.reduce();
524
- };
525
-
526
-
527
- // ------------------------------------------
528
- // Compare functions
529
- // ------------------------------------------
530
- /**
531
- * Compare the current coefficient with another coefficient
532
- * @param P
533
- * @param sign (string| default is =): authorized values: =, <, <=, >, >= with some variations.
534
- */
535
- compare = (P: Polynom, sign?: string): boolean => {
536
- if (sign === undefined) {
537
- sign = '='
538
- }
521
+ const P = this.clone();
522
+ for (let i = 1; i < nb; i++) {
523
+ this.multiply(P);
524
+ }
525
+ return this.reduce();
526
+ };
527
+
528
+
529
+ // ------------------------------------------
530
+ // Compare functions
531
+ // ------------------------------------------
532
+ /**
533
+ * Compare the current coefficient with another coefficient
534
+ * @param P
535
+ * @param sign (string| default is =): authorized values: =, <, <=, >, >= with some variations.
536
+ */
537
+ compare = (P: Polynom, sign?: string): boolean => {
538
+ if (sign === undefined) {
539
+ sign = '='
540
+ }
539
541
 
540
- // Create clone version to reduce them without altering the original polynoms.
541
- const cP1 = this.clone().reduce().reorder();
542
- const cP2 = P.clone().reduce().reorder();
542
+ // Create clone version to reduce them without altering the original polynoms.
543
+ const cP1 = this.clone().reduce().reorder();
544
+ const cP2 = P.clone().reduce().reorder();
543
545
 
544
- switch (sign) {
545
- case '=':
546
- // They must have the isSame length and the isSame degree
547
- if (cP1.length !== cP2.length || cP1.degree() !== cP2.degree()) {
548
- return false;
549
- }
546
+ switch (sign) {
547
+ case '=':
548
+ // They must have the isSame length and the isSame degree
549
+ if (cP1.length !== cP2.length || cP1.degree().isNotEqual(cP2.degree())) {
550
+ return false;
551
+ }
550
552
 
551
- // Check if the coefficients are the isSame.
552
- for (const i in cP1.monoms) {
553
- if (!cP1.monoms[i].isEqual(cP2.monoms[i])) {
554
- return false;
555
- }
556
- }
557
- return true;
558
- case 'same':
559
- // They must have the isSame length and the isSame degree
560
- if (cP1.length !== cP2.length || cP1.degree() !== cP2.degree()) {
553
+ // Check if the coefficients are the isSame.
554
+ for (const i in cP1.monoms) {
555
+ if (!cP1.monoms[i].isEqual(cP2.monoms[i])) {
561
556
  return false;
562
557
  }
558
+ }
559
+ return true;
560
+ case 'same':
561
+ // They must have the isSame length and the isSame degree
562
+ if (cP1.length !== cP2.length || cP1.degree() !== cP2.degree()) {
563
+ return false;
564
+ }
563
565
 
564
- for (const i in cP1.monoms) {
565
- if (!cP1.monoms[i].isSameAs(cP2.monoms[i])) {
566
- return false;
567
- }
566
+ for (const i in cP1.monoms) {
567
+ if (!cP1.monoms[i].isSameAs(cP2.monoms[i])) {
568
+ return false;
568
569
  }
570
+ }
569
571
 
570
- return true;
571
- default:
572
- return false;
573
- }
574
- };
575
-
576
- isZero(): boolean {
577
- return (this._monoms.length === 1 && this._monoms[0].coefficient.isZero()) || this._monoms.length === 0;
572
+ return true;
573
+ default:
574
+ return false;
578
575
  }
576
+ };
579
577
 
580
- isOne(): boolean {
581
- return this._monoms.length === 1 && this._monoms[0].coefficient.isOne();
582
- }
578
+ isZero(): boolean {
579
+ return (this._monoms.length === 1 && this._monoms[0].coefficient.isZero()) || this._monoms.length === 0;
580
+ }
583
581
 
584
- isEqual = (P: Polynom): boolean => {
585
- return this.compare(P, '=');
586
- };
582
+ isOne(): boolean {
583
+ return this._monoms.length === 1 && this._monoms[0].coefficient.isOne();
584
+ }
587
585
 
588
- isSameAs = (P: Polynom): boolean => {
589
- return this.compare(P, 'same');
590
- };
586
+ isEqual = (P: Polynom): boolean => {
587
+ return this.compare(P, '=');
588
+ };
591
589
 
592
- isOpposedAt = (P: Polynom): boolean => {
593
- return this.compare(P.clone().opposed(), '=');
594
- };
590
+ isSameAs = (P: Polynom): boolean => {
591
+ return this.compare(P, 'same');
592
+ };
595
593
 
596
- isFactorized = (polynomString: string): boolean => {
597
- let P;
594
+ isOpposedAt = (P: Polynom): boolean => {
595
+ return this.compare(P.clone().opposed(), '=');
596
+ };
598
597
 
599
- // Check if polynom is complete...
600
- if (polynomString.match(/\(/g).length !== polynomString.match(/\)/g).length) {
601
- return false
602
- }
598
+ isFactorized = (polynomString: string): boolean => {
599
+ let P;
603
600
 
604
- // Try to build the polynom
605
- try {
606
- P = new Polynom(polynomString);
607
- } catch (e) {
608
- return false;
609
- }
601
+ // Check if polynom is complete...
602
+ if (polynomString.match(/\(/g).length !== polynomString.match(/\)/g).length) {
603
+ return false
604
+ }
610
605
 
611
- // Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
612
- if (!this.isEqual(P)) {
613
- return false;
614
- }
606
+ // Try to build the polynom
607
+ try {
608
+ P = new Polynom(polynomString);
609
+ } catch (e) {
610
+ return false;
611
+ }
615
612
 
616
- // Check if the provided (string) version is fully factorized.
617
- // Run a regex on the string.
618
- let polynomStringNormalized = polynomString.replaceAll('*', ''),
619
- polynomStringReduced = '' + polynomStringNormalized,
620
- factors: string[] = [];
613
+ // Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
614
+ if (!this.isEqual(P)) {
615
+ return false;
616
+ }
621
617
 
622
- for (let x of polynomStringNormalized.matchAll(/\(([a-z0-9+\-]+)\)(\^[0-9]*)?/g)) {
623
- if (x[2] !== undefined) {
624
- for (let i = 0; i < +x[2].substr(1); i++) {
625
- factors.push(x[1])
626
- }
627
- } else {
628
- factors.push(x[1]);
618
+ // Check if the provided (string) version is fully factorized.
619
+ // Run a regex on the string.
620
+ let polynomStringNormalized = polynomString.replaceAll('*', ''),
621
+ polynomStringReduced = '' + polynomStringNormalized,
622
+ factors: string[] = [];
623
+
624
+ for (let x of polynomStringNormalized.matchAll(/\(([a-z0-9+\-]+)\)(\^[0-9]*)?/g)) {
625
+ if (x[2] !== undefined) {
626
+ for (let i = 0; i < +x[2].substr(1); i++) {
627
+ factors.push(x[1])
629
628
  }
630
- polynomStringReduced = polynomStringReduced.replaceAll(x[0], '');
631
- }
632
- if (polynomStringReduced !== '') {
633
- factors.push(polynomStringReduced);
629
+ } else {
630
+ factors.push(x[1]);
634
631
  }
635
- let polyFactors = factors.map(x => new Polynom(x));
632
+ polynomStringReduced = polynomStringReduced.replaceAll(x[0], '');
633
+ }
634
+ if (polynomStringReduced !== '') {
635
+ factors.push(polynomStringReduced);
636
+ }
637
+ let polyFactors = factors.map(x => new Polynom(x));
636
638
 
637
- // Factorize the current polynom.
638
- this.factorize();
639
+ // Factorize the current polynom.
640
+ this.factorize();
639
641
 
640
- // Compare the given factors with the generated factors
641
- let sign = 1;
642
- for (let f of this.factors) {
643
- for (let i = 0; i < polyFactors.length; i++) {
644
- if (f.isEqual(polyFactors[i])) {
645
- polyFactors.splice(i, 1);
646
- break;
647
- } else if (f.isOpposedAt(polyFactors[i])) {
648
- polyFactors.splice(i, 1);
649
- sign = -sign;
650
- break;
651
- }
642
+ // Compare the given factors with the generated factors
643
+ let sign = 1;
644
+ for (let f of this.factors) {
645
+ for (let i = 0; i < polyFactors.length; i++) {
646
+ if (f.isEqual(polyFactors[i])) {
647
+ polyFactors.splice(i, 1);
648
+ break;
649
+ } else if (f.isOpposedAt(polyFactors[i])) {
650
+ polyFactors.splice(i, 1);
651
+ sign = -sign;
652
+ break;
652
653
  }
653
654
  }
654
-
655
- // The polyfactors must be empty and the cumulative opposite factors must be 1.
656
- return (polyFactors.length === 0 && sign === 1);
657
655
  }
658
656
 
659
- isDeveloped = (polynomString: string): Boolean => {
660
- let P: Polynom;
657
+ // The polyfactors must be empty and the cumulative opposite factors must be 1.
658
+ return (polyFactors.length === 0 && sign === 1);
659
+ }
661
660
 
662
- // There is at least one parenthese - it is not developed.
663
- if (polynomString.match(/\(/g).length + polynomString.match(/\)/g).length) {
664
- return false
665
- }
661
+ isDeveloped = (polynomString: string): Boolean => {
662
+ let P: Polynom;
666
663
 
667
- // Try to build the polynom
668
- try {
669
- // Build the polynom
670
- P = new Polynom(polynomString);
671
- } catch (e) {
672
- return false;
673
- }
664
+ // There is at least one parenthese - it is not developed.
665
+ if (polynomString.match(/\(/g).length + polynomString.match(/\)/g).length) {
666
+ return false
667
+ }
674
668
 
675
- // Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
676
- if (!this.isEqual(P)) {
677
- return false;
678
- }
669
+ // Try to build the polynom
670
+ try {
671
+ // Build the polynom
672
+ P = new Polynom(polynomString);
673
+ } catch (e) {
674
+ return false;
675
+ }
676
+
677
+ // Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
678
+ if (!this.isEqual(P)) {
679
+ return false;
680
+ }
679
681
 
680
- // Check that everything is completely developed. Actually, there are no parentheses... so it is fully developed
682
+ // Check that everything is completely developed. Actually, there are no parentheses... so it is fully developed
681
683
 
682
- // maybe it wasn't reduced and not ordered...
683
- // compare polynom string.
684
+ // maybe it wasn't reduced and not ordered...
685
+ // compare polynom string.
684
686
 
685
- // normalize the string
686
- let polynomStringNormalized = polynomString.replaceAll('[*\s]', '')
687
+ // normalize the string
688
+ let polynomStringNormalized = polynomString.replaceAll('[*\s]', '')
687
689
 
688
- // Determine if it's the exact same string.
689
- // TODO: Maybe it's enough to just make this test !
690
- return polynomStringNormalized === P.reduce().reorder().display
691
- }
692
- // ------------------------------------------
693
- // Misc polynoms functions
694
- // -------------------------------------
695
- reduce = (): Polynom => {
696
- for (let i = 0; i < this._monoms.length; i++) {
697
- for (let j = i + 1; j < this._monoms.length; j++) {
698
- if (this._monoms[i].isSameAs(this.monoms[j])) {
699
- this._monoms[i].add(this.monoms[j]);
700
- this._monoms.splice(j, 1);
701
- }
690
+ // Determine if it's the exact same string.
691
+ // TODO: Maybe it's enough to just make this test !
692
+ return polynomStringNormalized === P.reduce().reorder().display
693
+ }
694
+ // ------------------------------------------
695
+ // Misc polynoms functions
696
+ // -------------------------------------
697
+ reduce = (): Polynom => {
698
+ for (let i = 0; i < this._monoms.length; i++) {
699
+ for (let j = i + 1; j < this._monoms.length; j++) {
700
+ if (this._monoms[i].isSameAs(this.monoms[j])) {
701
+ this._monoms[i].add(this.monoms[j]);
702
+ this._monoms.splice(j, 1);
702
703
  }
703
704
  }
705
+ }
704
706
 
705
- // Remove all null monoms
706
- this._monoms = this._monoms.filter((m) => {
707
- return m.coefficient.value !== 0
708
- });
709
-
710
- // Reduce all monoms coefficient.
711
- for (const m of this._monoms) {
712
- m.coefficient.reduce();
713
- }
707
+ // Remove all null monoms
708
+ this._monoms = this._monoms.filter((m) => {
709
+ return m.coefficient.value !== 0
710
+ });
714
711
 
715
- if (this.length === 0) {
716
- return new Polynom().zero();
717
- }
718
- return this;
719
- };
720
-
721
- reorder = (letter: string = 'x'): Polynom => {
722
- // TODO: Must handle multiple setLetter reorder system
723
- this._monoms.sort(function (a, b) {
724
- return b.degree(letter) - a.degree(letter)
725
- });
726
- return this.reduce();
727
- };
728
-
729
- degree = (letter?: string): number => {
730
- let d: number = 0;
731
- for (const m of this._monoms) {
732
- d = Math.max(m.degree(letter), d);
733
- }
734
- return d;
735
- };
712
+ // Reduce all monoms coefficient.
713
+ for (const m of this._monoms) {
714
+ m.coefficient.reduce();
715
+ }
736
716
 
737
- letters = (): string[] => {
738
- let L: string[] = [], S = new Set();
717
+ if (this.length === 0) {
718
+ return new Polynom().zero();
719
+ }
720
+ return this;
721
+ };
722
+
723
+ reorder = (letter: string = 'x'): Polynom => {
724
+ // TODO: Must handle multiple setLetter reorder system
725
+ this._monoms.sort(function (a, b) {
726
+ return b.degree(letter).clone().subtract(a.degree(letter)).value
727
+ });
728
+ return this.reduce();
729
+ };
730
+
731
+ degree = (letter?: string): Fraction => {
732
+ let d: Fraction = new Fraction().zero();
733
+ for (const m of this._monoms) {
734
+ d = Fraction.max(m.degree(letter).value, d);
735
+ }
736
+ return d;
737
+ };
739
738
 
740
- for (let m of this._monoms) {
741
- S = new Set([...S, ...m.variables]);
742
- }
739
+ letters = (): string[] => {
740
+ let L: string[] = [], S = new Set();
743
741
 
744
- // @ts-ignore
745
- return [...S];
742
+ for (let m of this._monoms) {
743
+ S = new Set([...S, ...m.variables]);
746
744
  }
747
745
 
748
- /**
749
- * Replace a variable (letter) by a polynom.
750
- * @param letter
751
- * @param P
752
- */
753
- replaceBy = (letter: string, P: Polynom): Polynom => {
754
- let pow: number;
755
- const resultPolynom: Polynom = new Polynom().zero();
756
-
757
- for (const m of this.monoms) {
758
- if (m.literal[letter] === undefined || m.literal[letter] === 0) {
759
- resultPolynom.add(m.clone());
760
- } else {
761
- // We have found a setLetter.
762
- // Get the power and reset it.
763
- pow = +m.literal[letter];
764
- delete m.literal[letter];
746
+ // @ts-ignore
747
+ return [...S];
748
+ }
765
749
 
766
- resultPolynom.add(P.clone().pow(pow).multiply(m));
767
- }
768
- }
750
+ /**
751
+ * Replace a variable (letter) by a polynom.
752
+ * @param letter
753
+ * @param P
754
+ */
755
+ replaceBy = (letter: string, P: Polynom): Polynom => {
756
+ let pow: number;
757
+ const resultPolynom: Polynom = new Polynom().zero();
758
+
759
+ for (const m of this.monoms) {
760
+ if (m.literal[letter] === undefined || m.literal[letter].isZero()) {
761
+ resultPolynom.add(m.clone());
762
+ } else {
763
+ // We have found a setLetter.
764
+ // Get the power and reset it.
765
+ pow = +m.literal[letter];
766
+ delete m.literal[letter];
769
767
 
770
- this._monoms = resultPolynom.reduce().reorder().monoms;
771
- return this;
772
- };
768
+ resultPolynom.add(P.clone().pow(pow).multiply(m));
769
+ }
770
+ }
773
771
 
774
- // Evaluate a polynom.
775
- evaluate = (values: { [key: string]: Fraction | number } | Fraction | number): Fraction => {
776
- const r = new Fraction().zero();
772
+ this._monoms = resultPolynom.reduce().reorder().monoms;
773
+ return this;
774
+ };
777
775
 
778
- this._monoms.forEach(monom => {
779
- //console.log('Evaluate polynom: ', monom.display, values, monom.evaluate(values).display);
780
- r.add(monom.evaluate(values));
781
- });
782
- return r;
783
- };
776
+ // Evaluate a polynom.
777
+ evaluate = (values: literalType | Fraction | number): Fraction => {
778
+ const r = new Fraction().zero();
784
779
 
785
- derivative = (letter?: string): Polynom => {
786
- let dP = new Polynom();
780
+ this._monoms.forEach(monom => {
781
+ //console.log('Evaluate polynom: ', monom.display, values, monom.evaluate(values).display);
782
+ r.add(monom.evaluate(values));
783
+ });
784
+ return r;
785
+ };
787
786
 
788
- for (let m of this._monoms) {
789
- dP.add(m.derivative(letter));
790
- }
791
- return dP;
787
+ derivative = (letter?: string): Polynom => {
788
+ let dP = new Polynom();
792
789
 
790
+ for (let m of this._monoms) {
791
+ dP.add(m.derivative(letter));
793
792
  }
793
+ return dP;
794
794
 
795
- primitive = (letter?: string): Polynom => {
796
- let dP = new Polynom();
795
+ }
797
796
 
798
- for (let m of this._monoms) {
799
- dP.add(m.primitive(letter))
800
- }
801
- return dP
797
+ primitive = (letter?: string): Polynom => {
798
+ let dP = new Polynom();
799
+
800
+ for (let m of this._monoms) {
801
+ dP.add(m.primitive(letter))
802
802
  }
803
+ return dP
804
+ }
803
805
 
804
- integrate = (a: Fraction | number, b: Fraction | number, letter?: string): Fraction => {
805
- const primitive = this.primitive(letter)
806
+ integrate = (a: Fraction | number, b: Fraction | number, letter?: string): Fraction => {
807
+ const primitive = this.primitive(letter)
806
808
 
807
- if (letter === undefined) {
808
- letter = 'x'
809
- }
809
+ if (letter === undefined) {
810
+ letter = 'x'
811
+ }
810
812
 
811
- let valuesA: { [key: string]: Fraction | number } = {},
812
- valuesB: { [key: string]: Fraction | number } = {}
813
- valuesA[letter] = a;
814
- valuesB[letter] = b;
813
+ let valuesA: literalType = {},
814
+ valuesB: literalType = {}
815
+ valuesA[letter] = new Fraction(a);
816
+ valuesB[letter] = new Fraction(b);
815
817
 
816
- return primitive.evaluate(valuesB).subtract(primitive.evaluate(valuesA))
818
+ return primitive.evaluate(valuesB).subtract(primitive.evaluate(valuesA))
819
+ }
820
+ // ------------------------------------------
821
+ // Polynoms factorization functions
822
+ // -------------------------------------
823
+ /**
824
+ * Factorize a polynom and store the best results in factors.
825
+ * @param maxValue Defines the greatest value to search to (default is 20).
826
+ */
827
+ factorize = (letter?: string): Polynom[] => {
828
+ let factors: Polynom[] = [];
829
+
830
+ // Extract the common monom
831
+ let P = this.clone().reorder(),
832
+ M = P.commonMonom(),
833
+ tempPolynom: Polynom
834
+ // It has a common monom.
835
+ if (!M.isOne()) {
836
+ tempPolynom = new Polynom()
837
+ tempPolynom.monoms = [M]
838
+ factors = [tempPolynom.clone()]
839
+ P = P.euclidian(tempPolynom).quotient;
817
840
  }
818
- // ------------------------------------------
819
- // Polynoms factorization functions
820
- // -------------------------------------
821
- /**
822
- * Factorize a polynom and store the best results in factors.
823
- * @param maxValue Defines the greatest value to search to (default is 20).
824
- */
825
- factorize_OLD = (maxValue?: number): Polynom => {
826
- // TODO: Must handle other letters than 'x'
827
- this._factors = [];
828
-
829
- // Duplicate the polynom
830
- let P = this.clone(),
831
- nbFactorsFound = 0;
832
-
833
- // Determine if the polynom is "negative", eg has a max monom degree with a negative coefficient.
834
- if (P.monomByDegree().coefficient.numerator < 0) {
835
- this._factors.push(new Polynom('-1'));
836
- }
837
841
 
838
- // Determine if there is a 'common' monom
839
- let M = P.commonMonom();
840
- if (!M.isOne()) {
841
- let commonPolynom = new Polynom()
842
- commonPolynom.monoms = [M]
843
- if (this._factors.length === 0) {
844
- this._factors.push(commonPolynom);
845
- } else {
846
- this._factors = [];
847
- this._factors.push(commonPolynom.opposed());
848
- }
849
- P = P.euclidian(commonPolynom).quotient;
842
+ let securityLoop = P.degree().clone().multiply(2).value
843
+ // securityLoop = 0
844
+ while (securityLoop >= 0) {
845
+ securityLoop--
850
846
 
851
- nbFactorsFound = commonPolynom.degree();
852
- }
853
847
 
854
- // Main loop.
855
- //
856
- // Do it only if degree is equal or less than one.
857
- if (P.degree() <= 1) {
858
- this._factors.push(P.clone());
848
+ if (P.monoms.length < 2) {
849
+ if (!P.isOne()) {
850
+ factors.push(P.clone());
851
+ }
852
+ break;
859
853
  } else {
860
- // Force test.
861
- let Q = new Fraction(),
862
- F,
863
- degree = P.degree();
864
-
865
- maxValue = maxValue === undefined ? 20 : maxValue;
866
-
867
- // Test all polynom similar to ax+b
868
- for (let a = 1; a <= maxValue; a++) {
869
- // Skip a coefficient of 0
870
- for (let b = -maxValue; b <= maxValue; b++) {
871
-
872
- Q.parse(-b, a);
873
-
874
- if (P.evaluate({x: Q})) {
875
- F = new Polynom(`${a}x+${b}`);
876
- while (P.evaluate({x: Q}).value === 0) {
877
- this._factors.push(F.clone());
878
- nbFactorsFound++;
879
-
880
- // Means it can be divided without reminders.
881
- P = P.euclidian(F).quotient;
882
- }
854
+ // Get the first and last monom.
855
+ let m1 = P.monoms[0].dividers,
856
+ m2 = P.monoms[P.monoms.length - 1].dividers
857
+
858
+ // console.log('CURRENT VALUE')
859
+ // console.log(P.tex)
860
+ // console.log('---------------------')
861
+ for (let m1d of m1) {
862
+ for (let m2d of m2) {
863
+ // if(m1d.degree()===m2d.degree()){continue}
864
+ let dividerPolynom = new Polynom(),
865
+ result
866
+ dividerPolynom.monoms = [m1d.clone(), m2d.clone()]
867
+ result = P.euclidian(dividerPolynom)
868
+
869
+ // console.log(dividerPolynom.tex, '=>', result.reminder.tex, '|||||', result.quotient.tex)
870
+ if (result.reminder.isZero()) {
871
+ P = result.quotient.clone();
872
+ factors.push(dividerPolynom)
873
+ continue;
883
874
  }
884
875
 
885
- // Continue if the numbers of factors found equals the degree.
886
- if (nbFactorsFound > degree) {
887
- return this;
876
+ dividerPolynom.monoms = [m1d.clone(), m2d.clone().opposed()]
877
+ result = P.euclidian(dividerPolynom)
878
+ if (result.reminder.isZero()) {
879
+ P = result.quotient.clone();
880
+ factors.push(dividerPolynom)
888
881
  }
882
+ // console.log(dividerPolynom.tex, '=>', result.reminder.tex)
889
883
  }
890
884
  }
891
-
892
- if (P.degree() > 1) {
893
- this._factors.push(P.clone());
894
- return this;
895
- }
896
- }
897
-
898
- return this;
899
- };
900
-
901
- factorize = (letter?: string): Polynom[] => {
902
- let factors: Polynom[] = [];
903
-
904
- // Extract the common monom
905
- let P = this.clone().reorder(),
906
- M = P.commonMonom(),
907
- tempPolynom: Polynom
908
- // It has a common monom.
909
- if (!M.isOne()) {
910
- tempPolynom = new Polynom()
911
- tempPolynom.monoms = [M]
912
- factors = [tempPolynom.clone()]
913
- P = P.euclidian(tempPolynom).quotient;
914
885
  }
915
886
 
916
- let securityLoop = P.degree() * 2
917
- // securityLoop = 0
918
- while (securityLoop >= 0) {
919
- securityLoop--
887
+ }
920
888
 
889
+ this.factors = factors
890
+ return factors;
891
+ }
921
892
 
922
- if (P.monoms.length < 2) {
923
- if (!P.isOne()) {
924
- factors.push(P.clone());
925
- }
926
- break;
893
+ private _factorize2ndDegree = (letter: string): Polynom[] => {
894
+ let P1: Polynom, P2: Polynom,
895
+ a, b, c, delta, x1, x2, factor;
896
+
897
+ // One variable only
898
+ if (this.numberOfVars === 1) {
899
+ a = this.monomByDegree(2, letter).coefficient;
900
+ b = this.monomByDegree(1, letter).coefficient;
901
+ c = this.monomByDegree(0, letter).coefficient;
902
+ delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
903
+
904
+ if (delta.isZero()) {
905
+ x1 = b.clone().opposed().divide(a.clone().multiply(2))
906
+ P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
907
+ P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
908
+ factor = a.divide(x1.denominator).divide(x1.denominator);
909
+
910
+ if (!factor.isOne()) {
911
+ // TODO: Update new Polynom to accept anything...
912
+ return [new Polynom(factor.display), P1, P2]
927
913
  } else {
928
- // Get the first and last monom.
929
- let m1 = P.monoms[0].dividers,
930
- m2 = P.monoms[P.monoms.length - 1].dividers
931
-
932
- // console.log('CURRENT VALUE')
933
- // console.log(P.tex)
934
- // console.log('---------------------')
935
- for (let m1d of m1) {
936
- for (let m2d of m2) {
937
- // if(m1d.degree()===m2d.degree()){continue}
938
- let dividerPolynom = new Polynom(),
939
- result
940
- dividerPolynom.monoms = [m1d.clone(), m2d.clone()]
941
- result = P.euclidian(dividerPolynom)
942
-
943
- // console.log(dividerPolynom.tex, '=>', result.reminder.tex, '|||||', result.quotient.tex)
944
- if (result.reminder.isZero()) {
945
- P = result.quotient.clone();
946
- factors.push(dividerPolynom)
947
- continue;
948
- }
949
-
950
- dividerPolynom.monoms = [m1d.clone(), m2d.clone().opposed()]
951
- result = P.euclidian(dividerPolynom)
952
- if (result.reminder.isZero()) {
953
- P = result.quotient.clone();
954
- factors.push(dividerPolynom)
955
- }
956
- // console.log(dividerPolynom.tex, '=>', result.reminder.tex)
957
- }
958
- }
914
+ return [P1, P2]
959
915
  }
960
-
961
- }
962
-
963
- this.factors = factors
964
- return factors;
965
- }
966
-
967
- private _factorize2ndDegree = (letter: string): Polynom[] => {
968
- let P1: Polynom, P2: Polynom,
969
- a, b, c, delta, x1, x2, factor;
970
-
971
- // One variable only
972
- if (this.numberOfVars === 1) {
973
- a = this.monomByDegree(2, letter).coefficient;
974
- b = this.monomByDegree(1, letter).coefficient;
975
- c = this.monomByDegree(0, letter).coefficient;
976
- delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
977
-
978
- if (delta.isZero()) {
979
- x1 = b.clone().opposed().divide(a.clone().multiply(2))
980
- P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
981
- P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
982
- factor = a.divide(x1.denominator).divide(x1.denominator);
983
-
984
- if (!factor.isOne()) {
985
- // TODO: Update new Polynom to accept anything...
986
- return [new Polynom(factor.display), P1, P2]
987
- } else {
988
- return [P1, P2]
989
- }
990
- } else if (delta.isPositive() && delta.isSquare()) {
991
- x1 = b.clone().opposed()
992
- .add(delta.clone().sqrt())
993
- .divide(a.clone().multiply(2))
994
- x2 = b.clone().opposed()
995
- .subtract(delta.clone().sqrt())
996
- .divide(a.clone().multiply(2))
997
-
998
- // (2x+5)(3x-2)
999
- // 6x^2+11x-10
1000
- // a = 6, b = 11, c = -10
1001
- // delta = 121-4*6*(-10) = 361= 19^2
1002
- // x1 = (-11 + 19) / 12 = 8/12 = 2/3
1003
- // x2 = (-11 - 19) / 12 = -30/12 = -5/2
1004
- factor = a.divide(x1.denominator).divide(x2.denominator);
1005
- if (factor.isOne()) {
1006
- return [
1007
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1008
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1009
- ]
1010
- } else {
1011
- return [
1012
- new Polynom(factor.display),
1013
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1014
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1015
- ]
1016
-
1017
- }
916
+ } else if (delta.isPositive() && delta.isSquare()) {
917
+ x1 = b.clone().opposed()
918
+ .add(delta.clone().sqrt())
919
+ .divide(a.clone().multiply(2))
920
+ x2 = b.clone().opposed()
921
+ .subtract(delta.clone().sqrt())
922
+ .divide(a.clone().multiply(2))
923
+
924
+ // (2x+5)(3x-2)
925
+ // 6x^2+11x-10
926
+ // a = 6, b = 11, c = -10
927
+ // delta = 121-4*6*(-10) = 361= 19^2
928
+ // x1 = (-11 + 19) / 12 = 8/12 = 2/3
929
+ // x2 = (-11 - 19) / 12 = -30/12 = -5/2
930
+ factor = a.divide(x1.denominator).divide(x2.denominator);
931
+ if (factor.isOne()) {
932
+ return [
933
+ new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
934
+ new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
935
+ ]
1018
936
  } else {
1019
- // No solution possible - return the complete value.
1020
- return [this.clone()]
937
+ return [
938
+ new Polynom(factor.display),
939
+ new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
940
+ new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
941
+ ]
942
+
1021
943
  }
1022
944
  } else {
1023
- // If multiple variables, only handle perfect squares...
1024
- a = this.monomByDegree(2, letter);
1025
- b = this.monomByDegree(1, letter);
1026
- c = this.monomByDegree(0, letter);
1027
-
1028
-
1029
- if (a.isLitteralSquare() && c.isLitteralSquare()) {
1030
- // Check the middle item is same as...
1031
- if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
1032
- // Determine if the coefficient values matches.
1033
-
1034
- // Search 4 values (r, s, t, u) that matches:
1035
- // (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
1036
-
1037
- let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
1038
- let xFactors = xPolynom._factorize2ndDegree('x');
1039
-
1040
- let factors = [], xyzPolynom: Polynom;
1041
-
1042
- if (xFactors.length >= 2) {
1043
- for (let p of xFactors) {
1044
- if (p.degree() === 0) {
1045
- factors.push(p.clone())
1046
- } else {
1047
- xyzPolynom = p.clone();
1048
- xyzPolynom.monoms[0].literal = a.literalSqrt
1049
- xyzPolynom.monoms[1].literal = c.literalSqrt
1050
- factors.push(xyzPolynom.clone())
1051
- }
1052
- }
1053
- return factors
1054
- }
1055
- }
1056
- }
1057
-
945
+ // No solution possible - return the complete value.
1058
946
  return [this.clone()]
1059
- //
1060
- // console.log(a.tex, b.tex, c.tex)
1061
- // if (a.isSquare() && c.isSquare()) {
1062
- // console.log('A C squares')
1063
- // if (a.clone().sqrt().multiply(c.clone().sqrt()).multiplyByNumber(2).isSameAs(b)) {
1064
- // console.log('HERE')
1065
- // if (a.coefficient.sign() === b.coefficient.sign()) {
1066
- // return []
1067
- // }else{
1068
- // return []
1069
- // }
1070
- // }
1071
- // } else if(a.isLitteralSquare() && c.isLitteralSquare()) {
1072
- // console.log('A C litteral SQUARES')
1073
- // // Check that the middle element is the product of a and c.
1074
- //
1075
- // if(b.clone().pow(2).isSameAs(a.clone().multiply(c))){
1076
- // console.log('SAME')
1077
- //
1078
- // }else{
1079
- // console.log('NOT SAME')
1080
- // }
1081
- //
1082
- // return [this.clone()]
1083
- // } else {
1084
- // console.log('NOT SQUARES AT ALL !!!!')
1085
- // }
1086
-
1087
947
  }
1088
- }
948
+ } else {
949
+ // If multiple variables, only handle perfect squares...
950
+ a = this.monomByDegree(2, letter);
951
+ b = this.monomByDegree(1, letter);
952
+ c = this.monomByDegree(0, letter);
1089
953
 
1090
- private _factorizeByGroups = (): Polynom[] => {
1091
- // TODO: Factorize by groups.
1092
- return [];
1093
- }
1094
- // ------------------------------------------
1095
- // Polynoms helpers functions
1096
- // -------------------------------------
1097
- // TODO: get zeroes for more than first degree
1098
- getZeroes = (): (Fraction | boolean)[] => {
1099
- const Z: Fraction[] = [];
1100
-
1101
- switch (this.degree()) {
1102
- case 0:
1103
- if (this._monoms[0].coefficient.value === 0) {
1104
- return [true];
1105
- } else {
1106
- return [false];
1107
- }
1108
- case 1:
1109
- // There is only one monoms,
1110
- if (this._monoms.length === 1) {
1111
- return [new Fraction().zero()];
1112
- } else {
1113
- const P = this.clone().reduce().reorder();
1114
- return [P.monoms[1].coefficient.opposed().divide(P.monoms[0].coefficient)];
1115
- }
1116
- // TODO: Determine the zeros of an equation of second degree.
1117
- //case 2:
1118
- default:
1119
- // Make sure the polynom is factorized.
1120
- if (this._factors.length === 0) {
1121
- this.factorize()
1122
- }
1123
954
 
1124
- let zeroes = [], zeroesAsTex = [];
1125
- for (let P of this._factors) {
1126
- if (P.degree() > 2) {
1127
- // TODO: Handle other polynom.
955
+ if (a.isLiteralSquare() && c.isLiteralSquare()) {
956
+ // Check the middle item is same as...
957
+ if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
958
+ // Determine if the coefficient values matches.
1128
959
 
1129
- } else if (P.degree() === 2) {
1130
- let A = P.monomByDegree(2).coefficient,
1131
- B = P.monomByDegree(1).coefficient,
1132
- C = P.monomByDegree(0).coefficient,
1133
- D = B.clone().pow(2).subtract(A.clone().multiply(C).multiply(4));
960
+ // Search 4 values (r, s, t, u) that matches:
961
+ // (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
1134
962
 
1135
- if (D.value > 0) {
1136
- /*console.log('Two zeroes for ', P.tex); */
1137
- let x1 = (-(B.value) + Math.sqrt(D.value)) / (2 * A.value),
1138
- x2 = (-(B.value) - Math.sqrt(D.value)) / (2 * A.value);
963
+ let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
964
+ let xFactors = xPolynom._factorize2ndDegree('x');
1139
965
 
1140
- zeroes.push(new Fraction(x1.toFixed(3)).reduce());
1141
- zeroes.push(new Fraction(x2.toFixed(3)).reduce());
1142
- } else if (D.value === 0) {
1143
- /*console.log('One zero for ', P.tex); */
966
+ let factors = [], xyzPolynom: Polynom;
1144
967
 
968
+ if (xFactors.length >= 2) {
969
+ for (let p of xFactors) {
970
+ if (p.degree().isZero()) {
971
+ factors.push(p.clone())
1145
972
  } else {
1146
- console.log('No zero for ', P.tex);
1147
- }
1148
- } else {
1149
- for (let z of P.getZeroes()) {
1150
- // Check if the zero is already in the list.
1151
- if (z === false || z === true) {
1152
- continue;
1153
- }
1154
- if (zeroesAsTex.indexOf(z.frac) === -1) {
1155
- zeroes.push(z);
1156
- zeroesAsTex.push(z.frac);
1157
- }
973
+ xyzPolynom = p.clone();
974
+ xyzPolynom.monoms[0].literal = a.literalSqrt
975
+ xyzPolynom.monoms[1].literal = c.literalSqrt
976
+ factors.push(xyzPolynom.clone())
1158
977
  }
1159
978
  }
979
+ return factors
1160
980
  }
1161
- return zeroes;
981
+ }
1162
982
  }
1163
- return Z;
1164
- };
1165
983
 
984
+ return [this.clone()]
985
+ //
986
+ // console.log(a.tex, b.tex, c.tex)
987
+ // if (a.isSquare() && c.isSquare()) {
988
+ // console.log('A C squares')
989
+ // if (a.clone().sqrt().multiply(c.clone().sqrt()).multiplyByNumber(2).isSameAs(b)) {
990
+ // console.log('HERE')
991
+ // if (a.coefficient.sign() === b.coefficient.sign()) {
992
+ // return []
993
+ // }else{
994
+ // return []
995
+ // }
996
+ // }
997
+ // } else if(a.isLiteralSquare() && c.isLiteralSquare()) {
998
+ // console.log('A C litteral SQUARES')
999
+ // // Check that the middle element is the product of a and c.
1000
+ //
1001
+ // if(b.clone().pow(2).isSameAs(a.clone().multiply(c))){
1002
+ // console.log('SAME')
1003
+ //
1004
+ // }else{
1005
+ // console.log('NOT SAME')
1006
+ // }
1007
+ //
1008
+ // return [this.clone()]
1009
+ // } else {
1010
+ // console.log('NOT SQUARES AT ALL !!!!')
1011
+ // }
1166
1012
 
1167
- // TODO: analyse the next functions to determine if they are useful or not...
1168
- monomByDegree = (degree?: number, letter?: string): Monom => {
1169
- if (degree === undefined) {
1170
- // return the highest degree monom.
1171
- return this.monomByDegree(this.degree(letter), letter);
1172
- }
1013
+ }
1014
+ }
1173
1015
 
1174
- // Reduce the polynom.
1175
- const M = this.clone().reduce();
1176
- for (const m of M._monoms) {
1177
- if (m.degree(letter) === degree) {
1178
- return m.clone();
1016
+ private _factorizeByGroups = (): Polynom[] => {
1017
+ // TODO: Factorize by groups.
1018
+ return [];
1019
+ }
1020
+ // ------------------------------------------
1021
+ // Polynoms helpers functions
1022
+ // -------------------------------------
1023
+ // TODO: get zeroes for more than first degree and for more than natural degrees
1024
+ getZeroes = (): (Fraction | boolean)[] => {
1025
+ const Z: Fraction[] = [];
1026
+
1027
+ switch (this.degree().value) {
1028
+ case 0:
1029
+ if (this._monoms[0].coefficient.value === 0) {
1030
+ return [true];
1031
+ } else {
1032
+ return [false];
1033
+ }
1034
+ case 1:
1035
+ // There is only one monoms,
1036
+ if (this._monoms.length === 1) {
1037
+ return [new Fraction().zero()];
1038
+ } else {
1039
+ const P = this.clone().reduce().reorder();
1040
+ return [P.monoms[1].coefficient.opposed().divide(P.monoms[0].coefficient)];
1041
+ }
1042
+ // TODO: Determine the zeros of an equation of second degree.
1043
+ //case 2:
1044
+ default:
1045
+ // Make sure the polynom is factorized.
1046
+ if (this._factors.length === 0) {
1047
+ this.factorize()
1179
1048
  }
1180
- }
1181
1049
 
1182
- // Nothing was found - return the null monom.
1183
- return new Monom().zero();
1184
- };
1050
+ let zeroes = [], zeroesAsTex = [];
1051
+ for (let P of this._factors) {
1052
+ if (P.degree().greater(2)) {
1053
+ // TODO: Handle other polynom.
1185
1054
 
1186
- monomsByDegree = (degree?: number, letter?: string): Monom[] => {
1187
- if (degree === undefined) {
1188
- // return the highest degree monom.
1189
- return this.monomsByDegree(this.degree(letter));
1190
- }
1055
+ } else if (P.degree().value === 2) {
1056
+ let A = P.monomByDegree(2).coefficient,
1057
+ B = P.monomByDegree(1).coefficient,
1058
+ C = P.monomByDegree(0).coefficient,
1059
+ D = B.clone().pow(2).subtract(A.clone().multiply(C).multiply(4));
1060
+
1061
+ if (D.value > 0) {
1062
+ /*console.log('Two zeroes for ', P.tex); */
1063
+ let x1 = (-(B.value) + Math.sqrt(D.value)) / (2 * A.value),
1064
+ x2 = (-(B.value) - Math.sqrt(D.value)) / (2 * A.value);
1191
1065
 
1192
- // Reduce the polynom.
1193
- let Ms: Monom[] = [];
1066
+ zeroes.push(new Fraction(x1.toFixed(3)).reduce());
1067
+ zeroes.push(new Fraction(x2.toFixed(3)).reduce());
1068
+ } else if (D.value === 0) {
1069
+ /*console.log('One zero for ', P.tex); */
1194
1070
 
1195
- const M = this.clone().reduce();
1196
- for (const m of M._monoms) {
1197
- if (m.degree(letter) === degree) {
1198
- Ms.push(m.clone())
1071
+ } else {
1072
+ console.log('No zero for ', P.tex);
1073
+ }
1074
+ } else {
1075
+ for (let z of P.getZeroes()) {
1076
+ // Check if the zero is already in the list.
1077
+ if (z === false || z === true) {
1078
+ continue;
1079
+ }
1080
+ if (zeroesAsTex.indexOf(z.frac) === -1) {
1081
+ zeroes.push(z);
1082
+ zeroesAsTex.push(z.frac);
1083
+ }
1084
+ }
1085
+ }
1199
1086
  }
1200
- }
1087
+ return zeroes;
1088
+ }
1089
+ return Z;
1090
+ };
1091
+
1201
1092
 
1202
- return Ms
1203
- // Nothing was found - retur
1093
+ // TODO: analyse the next functions to determine if they are useful or not...
1094
+ monomByDegree = (degree?: Fraction|number, letter?: string): Monom => {
1095
+ if (degree === undefined) {
1096
+ // return the highest degree monom.
1097
+ return this.monomByDegree(this.degree(letter), letter);
1204
1098
  }
1205
1099
 
1206
- // Used in LinearSystem.tex
1207
- monomByLetter = (letter: string): Monom => {
1208
- const M = this.clone().reduce();
1209
- for (const m of M._monoms) {
1210
- if (m.hasLetter(letter)) {
1211
- return m.clone();
1212
- }
1100
+ // Reduce the polynom.
1101
+ const M = this.clone().reduce();
1102
+ for (const m of M._monoms) {
1103
+ if (m.degree(letter) === degree) {
1104
+ return m.clone();
1213
1105
  }
1106
+ }
1214
1107
 
1215
- return new Monom().zero();
1216
- };
1108
+ // Nothing was found - return the null monom.
1109
+ return new Monom().zero();
1110
+ };
1217
1111
 
1112
+ monomsByDegree = (degree?: number|Fraction, letter?: string): Monom[] => {
1113
+ if (degree === undefined) {
1114
+ // return the highest degree monom.
1115
+ return this.monomsByDegree(this.degree(letter));
1116
+ }
1218
1117
 
1219
- // Next functions are used for for commonMonom, which is used in the factorize method.
1220
- getDenominators = (): number[] => {
1221
- const denominators: number[] = [];
1222
- for (const m of this._monoms) {
1223
- denominators.push(m.coefficient.denominator);
1224
- }
1225
- return denominators;
1226
- };
1118
+ // Reduce the polynom.
1119
+ let Ms: Monom[] = [];
1227
1120
 
1228
- getNumerators = (): number[] => {
1229
- const numerators: number[] = [];
1230
- for (const m of this._monoms) {
1231
- numerators.push(m.coefficient.numerator);
1121
+ const M = this.clone().reduce();
1122
+ for (const m of M._monoms) {
1123
+ if (m.degree(letter) === degree) {
1124
+ Ms.push(m.clone())
1232
1125
  }
1233
- return numerators;
1234
- };
1235
-
1236
- lcmDenominator = (): number => {
1237
- return Numeric.lcm(...this.getDenominators());
1238
- };
1239
-
1240
- gcdDenominator = (): number => {
1241
- return Numeric.gcd(...this.getDenominators());
1242
- };
1243
-
1244
- lcmNumerator = (): number => {
1245
- return Numeric.lcm(...this.getNumerators());
1246
- };
1247
-
1248
- gcdNumerator = (): number => {
1249
- return Numeric.gcd(...this.getNumerators());
1250
- };
1251
-
1252
- commonMonom = (): Monom => {
1253
- let M = new Monom().one(), numerator: number, denominator: number, degree = this.degree();
1254
-
1255
- numerator = this.gcdNumerator();
1256
- denominator = this.gcdDenominator();
1257
-
1258
- M.coefficient = new Fraction(numerator, denominator);
1259
- for (let L of this.variables) {
1260
- // Initialize the setLetter with the max degree
1261
- M.setLetter(L, degree);
1262
- for (let m of this._monoms) {
1263
- M.setLetter(L, Math.min(m.degree(L), M.degree(L)));
1264
- if (M.degree(L) === 0) {
1265
- break;
1266
- }
1267
- }
1268
- }
1269
- return M;
1270
1126
  }
1271
1127
 
1128
+ return Ms
1129
+ // Nothing was found - retur
1130
+ }
1272
1131
 
1273
- // TODO: The rest of the functions are not used or unnecessary ?
1274
- /**
1275
- * This will generate a not reduced tex string of the polynom.
1276
- * @param complexity : Number of iteration to increase the complexity.
1277
- */
1278
- makeItComplicate = (complexity: number = 1): Polynom => {
1279
- this._texString = '';
1280
-
1281
- // The polynom must be at least of the first degree.
1282
- if (this.degree() < 1) {
1283
- return this;
1132
+ // Used in LinearSystem.tex
1133
+ monomByLetter = (letter: string): Monom => {
1134
+ const M = this.clone().reduce();
1135
+ for (const m of M._monoms) {
1136
+ if (m.hasLetter(letter)) {
1137
+ return m.clone();
1284
1138
  }
1139
+ }
1285
1140
 
1286
- // TODO: update this function !
1141
+ return new Monom().zero();
1142
+ };
1287
1143
 
1288
- const mDegree = Random.number(0, this.degree() - 1);
1289
- // const A = new Polynom().rndSimple(mDegree, false, complexity > 1, 'x', false, complexity > 1 ? -1 : 1);
1290
- // const B = new Polynom().rndSimple(1, false, complexity > 1);
1291
- // const C = this.clone().subtract(A.clone().multiply(B));
1292
1144
 
1293
- // Try to factorize a little bit the C polynom.
1294
- // C.factorizePartial(true);
1295
- // this._texString = `${A.genDisplay('tex', false, true)} \\cdot ${B.genDisplay('tex', false, true)} ${C.texString} `;
1296
- //
1297
- return this;
1298
- };
1299
- factorizePartial = (forceSign?: boolean): Polynom => {
1300
- this._texString = '';
1301
- // Try to find two monoms with a common coefficient.
1302
- if (this.length <= 1) {
1303
- return this;
1304
- }
1305
-
1306
- let mMain: Monom,
1307
- mCheck: Monom,
1308
- mFactor: Monom,
1309
- pFactor: Polynom,
1310
- // pRemain: Polynom,
1311
- g: number, sign: string;
1312
-
1313
- for (let i = 0; i < this.length; i++) {
1314
- mMain = this._monoms[i].clone();
1315
- // We factorize only if the main coefficient isn't a fraction
1316
- // if(mMain.coefficient.denominator!==1){continue;}
1317
- for (let j = i + 1; j < this.length; j++) {
1318
- mCheck = this._monoms[j].clone();
1319
- // if(mCheck.coefficient.denominator!==1){continue;}
1320
-
1321
- g = Numeric.gcd(mMain.coefficient.numerator, mCheck.coefficient.numerator);
1322
- if (g !== 1) {
1323
- // mFactor = mMain.clone().divide(mCheck); // This gets the literal part.
1324
- // mFactor.coefficient = new Fraction(g); // Set the coefficient to the gcd.
1325
- mFactor = Monom.lcm(mMain, mCheck);
1326
- sign = mMain.coefficient.sign() === 1 ? '+' : '-';
1327
- this._texString = `${forceSign === true ? sign : (sign === '+' ? '' : sign)}${mFactor.tex}`;
1328
-
1329
- pFactor = new Polynom().add(mMain.divide(mFactor)).add(mCheck.divide(mFactor));
1330
- this._texString += pFactor.genDisplay('tex', false, true);
1331
-
1332
- this._texString += this.clone().subtract(pFactor.clone().multiply(mFactor)).genDisplay('tex', true, false);
1333
- return this;
1334
- }
1335
- }
1336
- }
1145
+ // Next functions are used for for commonMonom, which is used in the factorize method.
1146
+ getDenominators = (): number[] => {
1147
+ const denominators: number[] = [];
1148
+ for (const m of this._monoms) {
1149
+ denominators.push(m.coefficient.denominator);
1150
+ }
1151
+ return denominators;
1152
+ };
1337
1153
 
1338
- this._texString = this.genDisplay('tex', forceSign);
1154
+ getNumerators = (): number[] => {
1155
+ const numerators: number[] = [];
1156
+ for (const m of this._monoms) {
1157
+ numerators.push(m.coefficient.numerator);
1158
+ }
1159
+ return numerators;
1160
+ };
1339
1161
 
1340
- return this;
1341
- };
1342
- /**
1343
- * reduce the coefficient value as if the polynom was equal to zero.
1344
- */
1345
- minify = (): Polynom => {
1346
- // First multiply by the common denominator.
1347
- this.multiply(this.lcmDenominator()).divide(this.gcdNumerator()).reduce();
1348
- return this.reduce();
1349
- };
1350
- /**
1351
- * Determine if the current polynom is divisible by P
1352
- * TODO: should work with any polynom, not only first degree polynoms and the setLetter should disappear
1353
- * @param P
1354
- * @param letter - default setLetter
1355
- */
1356
- canDivide = (P: Polynom, letter: string = 'x'): boolean => {
1357
- const d = P.degree();
1358
-
1359
- const evalValue: { [key: string]: Fraction } = {};
1360
- // A zero degree polynom can always divide, except if it's the zero polynom.
1361
- if (d === 0) {
1362
- return !P.isZero;
1363
- }
1162
+ lcmDenominator = (): number => {
1163
+ return Numeric.lcm(...this.getDenominators());
1164
+ };
1364
1165
 
1365
- // The polynom is of degree one.
1366
- if (d === 1) {
1367
- const z = P.getZeroes();
1368
- // The zero is an undefined zero.
1369
- if (z[0] === true || z[0] === false) {
1370
- return false;
1371
- }
1166
+ gcdDenominator = (): number => {
1167
+ return Numeric.gcd(...this.getDenominators());
1168
+ };
1372
1169
 
1373
- evalValue[letter] = z[0];
1374
- return this.evaluate(evalValue).value === 0;
1375
- }
1170
+ lcmNumerator = (): number => {
1171
+ return Numeric.lcm(...this.getNumerators());
1172
+ };
1376
1173
 
1377
- // The polynom is of degree 2 or more...
1378
- if (d > 1) {
1379
- console.log('Currently, only first degree polynom are supported');
1380
- return false;
1381
- }
1174
+ gcdNumerator = (): number => {
1175
+ return Numeric.gcd(...this.getNumerators());
1176
+ };
1382
1177
 
1383
- return false;
1384
- };
1178
+ commonMonom = (): Monom => {
1179
+ let M = new Monom().one(), numerator: number, denominator: number, degree = this.degree();
1385
1180
 
1181
+ numerator = this.gcdNumerator();
1182
+ denominator = this.gcdDenominator();
1386
1183
 
1184
+ M.coefficient = new Fraction(numerator, denominator);
1185
+ for (let L of this.variables) {
1186
+ // Initialize the setLetter with the max degree
1187
+ M.setLetter(L, degree);
1188
+ for (let m of this._monoms) {
1189
+ M.setLetter(L, Fraction.min(m.degree(L), M.degree(L)));
1190
+ if (M.degree(L).isZero()) {
1191
+ break;
1192
+ }
1193
+ }
1194
+ }
1195
+ return M;
1387
1196
  }
1197
+ }