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