pimath 0.0.16 → 0.0.20

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