pimath 0.0.14 → 0.0.18

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