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