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