pimath 0.0.13 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dev/index.html +9 -3
- package/dev/pi.js +364 -229
- package/dev/pi.js.map +1 -1
- package/dist/pi.js +1 -1
- package/dist/pi.js.map +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/algebra.Algebra.Equation.html +26 -0
- package/docs/classes/algebra.Algebra.LinearSystem.html +1 -0
- package/docs/classes/algebra.Algebra.LogicalSet.html +3 -0
- package/docs/classes/algebra.Algebra.Monom.html +36 -36
- package/docs/classes/algebra.Algebra.Polynom.html +11 -11
- package/docs/classes/algebra.Algebra.Rational.html +2 -0
- package/docs/classes/algebra.Equation.html +9 -9
- package/docs/classes/algebra.LinearSystem.html +1 -1
- package/docs/classes/algebra.Logicalset.html +2 -2
- package/docs/classes/algebra.Monom.html +36 -36
- package/docs/classes/algebra.Polynom.html +12 -12
- package/docs/classes/algebra.Rational.html +2 -2
- package/docs/classes/coefficients.Fraction.html +4 -4
- package/docs/classes/coefficients.Nthroot.html +1 -1
- package/docs/classes/geometry.Circle.html +1 -1
- package/docs/classes/geometry.Geometry.Circle.html +1 -0
- package/docs/classes/geometry.Geometry.Line.html +1 -0
- package/docs/classes/geometry.Geometry.Point.html +1 -0
- package/docs/classes/geometry.Geometry.Triangle.html +9 -0
- package/docs/classes/geometry.Geometry.Vector.html +1 -0
- package/docs/classes/geometry.Line.html +1 -1
- package/docs/classes/geometry.Point.html +1 -1
- package/docs/classes/geometry.Triangle.html +6 -6
- package/docs/classes/geometry.Vector.html +1 -1
- package/docs/classes/numeric.Numeric.html +5 -5
- package/docs/classes/shutingyard.Shutingyard.html +5 -5
- package/docs/interfaces/geometry.remarquableLines.html +1 -1
- package/docs/modules/algebra.Algebra.html +1 -1
- package/docs/modules/geometry.Geometry.html +1 -0
- package/docs/modules/geometry.html +1 -1
- package/docs/modules/random.Random.html +1 -1
- package/docs/modules/random.html +1 -1
- package/esm/main.js +24 -22
- package/esm/main.js.map +1 -1
- package/esm/maths/algebra/equation.d.ts +2 -1
- package/esm/maths/algebra/equation.js +29 -25
- package/esm/maths/algebra/equation.js.map +1 -1
- package/esm/maths/algebra/index.d.ts +0 -8
- package/esm/maths/algebra/index.js +18 -17
- package/esm/maths/algebra/index.js.map +1 -1
- package/esm/maths/algebra/linearSystem.d.ts +1 -1
- package/esm/maths/algebra/linearSystem.js +19 -15
- package/esm/maths/algebra/linearSystem.js.map +1 -1
- package/esm/maths/algebra/logicalset.js +7 -3
- package/esm/maths/algebra/logicalset.js.map +1 -1
- package/esm/maths/algebra/monom.d.ts +14 -17
- package/esm/maths/algebra/monom.js +164 -75
- package/esm/maths/algebra/monom.js.map +1 -1
- package/esm/maths/algebra/polynom.d.ts +6 -24
- package/esm/maths/algebra/polynom.js +57 -206
- package/esm/maths/algebra/polynom.js.map +1 -1
- package/esm/maths/algebra/rational.js +15 -10
- package/esm/maths/algebra/rational.js.map +1 -1
- package/esm/maths/coefficients/fraction.d.ts +20 -10
- package/esm/maths/coefficients/fraction.js +83 -15
- package/esm/maths/coefficients/fraction.js.map +1 -1
- package/esm/maths/coefficients/index.js +14 -2
- package/esm/maths/coefficients/index.js.map +1 -1
- package/esm/maths/coefficients/nthroot.js +5 -1
- package/esm/maths/coefficients/nthroot.js.map +1 -1
- package/esm/maths/geometry/circle.js +12 -8
- package/esm/maths/geometry/circle.js.map +1 -1
- package/esm/maths/geometry/index.js +17 -5
- package/esm/maths/geometry/index.js.map +1 -1
- package/esm/maths/geometry/line.js +26 -22
- package/esm/maths/geometry/line.js.map +1 -1
- package/esm/maths/geometry/point.js +16 -12
- package/esm/maths/geometry/point.js.map +1 -1
- package/esm/maths/geometry/triangle.js +31 -27
- package/esm/maths/geometry/triangle.js.map +1 -1
- package/esm/maths/geometry/vector.js +21 -17
- package/esm/maths/geometry/vector.js.map +1 -1
- package/esm/maths/numeric.js +5 -1
- package/esm/maths/numeric.js.map +1 -1
- package/esm/maths/random/index.d.ts +3 -1
- package/esm/maths/random/index.js +32 -14
- package/esm/maths/random/index.js.map +1 -1
- package/esm/maths/random/randomCore.js +5 -1
- package/esm/maths/random/randomCore.js.map +1 -1
- package/esm/maths/random/rndFraction.d.ts +9 -0
- package/esm/maths/random/rndFraction.js +30 -0
- package/esm/maths/random/rndFraction.js.map +1 -0
- package/esm/maths/random/rndHelpers.js +5 -1
- package/esm/maths/random/rndHelpers.js.map +1 -1
- package/esm/maths/random/rndMonom.d.ts +2 -2
- package/esm/maths/random/rndMonom.js +15 -8
- package/esm/maths/random/rndMonom.js.map +1 -1
- package/esm/maths/random/rndPolynom.d.ts +1 -1
- package/esm/maths/random/rndPolynom.js +22 -10
- package/esm/maths/random/rndPolynom.js.map +1 -1
- package/esm/maths/random/rndTypes.d.ts +5 -0
- package/esm/maths/random/rndTypes.js +2 -1
- package/esm/maths/shutingyard.js +5 -1
- package/esm/maths/shutingyard.js.map +1 -1
- package/package.json +5 -5
- package/src/maths/algebra/equation.ts +6 -5
- package/src/maths/algebra/index.ts +1 -9
- package/src/maths/algebra/linearSystem.ts +3 -3
- package/src/maths/algebra/monom.ts +759 -622
- package/src/maths/algebra/monom_bck.backup +746 -0
- package/src/maths/algebra/polynom.ts +980 -1170
- package/src/maths/algebra/rational.ts +6 -6
- package/src/maths/coefficients/fraction.ts +98 -27
- package/src/maths/geometry/index.ts +1 -1
- package/src/maths/geometry/line.ts +1 -1
- package/src/maths/random/index.ts +9 -3
- package/src/maths/random/rndFraction.ts +37 -0
- package/src/maths/random/rndMonom.ts +6 -3
- package/src/maths/random/rndPolynom.ts +15 -5
- package/src/maths/random/rndTypes.ts +5 -0
- package/src/maths/shutingyard.ts +2 -0
- package/tests/algebra/monom.test.ts +29 -8
- package/tests/algebra/polynom.test.ts +13 -22
- package/tests/coefficients/fraction.test.ts +35 -38
- package/tests/shutingyard.test.ts +0 -1
- package/tsconfig.json +1 -1
- package/tsconfig.testing.json +28 -0
|
@@ -3,744 +3,881 @@
|
|
|
3
3
|
* Defined as coefficient * literal
|
|
4
4
|
* Examples: 3x^2, 3/5x^2, ...
|
|
5
5
|
*/
|
|
6
|
-
import {Fraction} from "../coefficients
|
|
6
|
+
import {Fraction} from "../coefficients";
|
|
7
7
|
import {Numeric} from "../numeric";
|
|
8
|
+
import {Shutingyard} from "../shutingyard";
|
|
9
|
+
|
|
10
|
+
export type literalType = {
|
|
11
|
+
[Key: string]: Fraction
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Monom {
|
|
15
|
+
private _coefficient: Fraction;
|
|
16
|
+
private _literal: literalType;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create the monom object.
|
|
20
|
+
* @param value (optional) string
|
|
21
|
+
*/
|
|
22
|
+
constructor(value?: string) {
|
|
23
|
+
this.zero();
|
|
24
|
+
|
|
25
|
+
if (value !== undefined) {
|
|
26
|
+
// A string is given - try to parse the value.
|
|
27
|
+
this.parse(value);
|
|
28
|
+
}
|
|
8
29
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
private _literal: { [Key: string]: number };
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Create the monom object.
|
|
15
|
-
* @param value (optional) string
|
|
16
|
-
*/
|
|
17
|
-
constructor(value?: string) {
|
|
18
|
-
this.zero();
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
19
32
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
33
|
+
// ------------------------------------------
|
|
34
|
+
// Getter and setter
|
|
35
|
+
// ------------------------------------------
|
|
36
|
+
get isMonom() {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
24
39
|
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Get the coefficient as fraction
|
|
42
|
+
*/
|
|
43
|
+
get coefficient(): Fraction {
|
|
44
|
+
return this._coefficient;
|
|
45
|
+
}
|
|
27
46
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Set the coefficient value of the monom
|
|
49
|
+
* @param F Fraction
|
|
50
|
+
*/
|
|
51
|
+
set coefficient(F: Fraction) {
|
|
52
|
+
this._coefficient = F;
|
|
53
|
+
}
|
|
34
54
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Get the literal part, as dictionary
|
|
57
|
+
*/
|
|
58
|
+
get literal(): literalType {
|
|
59
|
+
return this._literal;
|
|
60
|
+
}
|
|
41
61
|
|
|
42
|
-
|
|
43
|
-
* Set the coefficient value of the monom
|
|
44
|
-
* @param F Fraction
|
|
45
|
-
*/
|
|
46
|
-
set coefficient(F: Fraction) {
|
|
47
|
-
this._coefficient = F;
|
|
48
|
-
}
|
|
62
|
+
get literalSqrt(): literalType {
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
if (this.isLiteralSquare()) {
|
|
65
|
+
let L: literalType = {}
|
|
66
|
+
for (let key in this._literal) {
|
|
67
|
+
L[key] = this._literal[key].clone().sqrt()
|
|
68
|
+
}
|
|
69
|
+
return L;
|
|
70
|
+
} else {
|
|
54
71
|
return this._literal;
|
|
55
72
|
}
|
|
73
|
+
}
|
|
56
74
|
|
|
57
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Set the literal part of the monom
|
|
77
|
+
* @param L Literal part as dictionary: <setLetter: exposant>
|
|
78
|
+
*/
|
|
79
|
+
set literal(L: literalType) {
|
|
80
|
+
this._literal = L;
|
|
81
|
+
}
|
|
58
82
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Set the literal part of the monom from a string
|
|
85
|
+
* @param inputStr String like x^2y^3
|
|
86
|
+
*/
|
|
87
|
+
set literalStr(inputStr: string) {
|
|
88
|
+
// TODO : parse using shutingyard tree !
|
|
89
|
+
|
|
90
|
+
// Match all x^n
|
|
91
|
+
for (const v of [...inputStr.matchAll(/([a-z])\^([+-]?[0-9]+)/g)]) {
|
|
92
|
+
// Create the default letter entry if necessary.
|
|
93
|
+
if (!(v[1] in this._literal)) {
|
|
94
|
+
this._literal[v[1]] = new Fraction().zero();
|
|
67
95
|
}
|
|
68
|
-
}
|
|
69
96
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
*/
|
|
74
|
-
set literal(L: { [Key: string]: number }) {
|
|
75
|
-
this._literal = L;
|
|
97
|
+
// Add the new value.
|
|
98
|
+
// TODO: actually, it adds only numeric value
|
|
99
|
+
this._literal[v[1]].add(+v[2]);
|
|
76
100
|
}
|
|
77
101
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Match all x^n
|
|
84
|
-
for (const v of [...inputStr.matchAll(/([a-z])\^([+-]?[0-9]+)/g)]) {
|
|
85
|
-
if (!(v[1] in this._literal)) {
|
|
86
|
-
this._literal[v[1]] = 0;
|
|
87
|
-
}
|
|
88
|
-
this._literal[v[1]] += +v[2];
|
|
89
|
-
}
|
|
90
|
-
for (const v of [...inputStr.matchAll(/([a-z](?!\^))/g)]) {
|
|
91
|
-
// Match all single letters
|
|
92
|
-
if (!(v[1] in this._literal)) {
|
|
93
|
-
this._literal[v[1]] = 0;
|
|
94
|
-
}
|
|
95
|
-
this._literal[v[1]] += 1;
|
|
102
|
+
// Match all x
|
|
103
|
+
for (const v of [...inputStr.matchAll(/([a-z](?!\^))/g)]) {
|
|
104
|
+
// Match all single letters
|
|
105
|
+
if (!(v[1] in this._literal)) {
|
|
106
|
+
this._literal[v[1]] = new Fraction().zero();
|
|
96
107
|
}
|
|
97
|
-
}
|
|
98
108
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
* Get the variables letters
|
|
102
|
-
*/
|
|
103
|
-
get variables(): string[] {
|
|
104
|
-
this.clone().clean();
|
|
105
|
-
return Object.keys(this._literal)
|
|
109
|
+
// Add one to the value.
|
|
110
|
+
this._literal[v[1]].add(1)
|
|
106
111
|
}
|
|
112
|
+
}
|
|
107
113
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
// Getter helpers.
|
|
115
|
+
/**
|
|
116
|
+
* Get the variables letters
|
|
117
|
+
*/
|
|
118
|
+
get variables(): string[] {
|
|
119
|
+
this.clone().clean();
|
|
120
|
+
return Object.keys(this._literal)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Display getter
|
|
124
|
+
/**
|
|
125
|
+
* This display getter is to be used in the polynom display getter
|
|
126
|
+
*/
|
|
127
|
+
get display(): string {
|
|
128
|
+
let L: string = '',
|
|
129
|
+
letters = Object.keys(this._literal).sort()
|
|
130
|
+
for (let letter of letters) {
|
|
131
|
+
if (this._literal[letter].isNotZero()) {
|
|
132
|
+
L += `${letter}`;
|
|
133
|
+
if (this._literal[letter].isNotEqual(1)) {
|
|
134
|
+
L += `^${this._literal[letter].display}`;
|
|
120
135
|
}
|
|
121
136
|
}
|
|
137
|
+
}
|
|
122
138
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
} else {
|
|
128
|
-
return '';
|
|
129
|
-
}
|
|
139
|
+
if (L === '') {
|
|
140
|
+
// No setLetter - means it's only a number !
|
|
141
|
+
if (this._coefficient.value != 0) {
|
|
142
|
+
return `${this._coefficient.display}`;
|
|
130
143
|
} else {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
return '';
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
if (this._coefficient.value === 1) {
|
|
148
|
+
return L;
|
|
149
|
+
} else if (this._coefficient.value === -1) {
|
|
150
|
+
return `-${L}`;
|
|
151
|
+
} else if (this._coefficient.value === 0) {
|
|
152
|
+
return '0';
|
|
153
|
+
} else {
|
|
154
|
+
return `${this._coefficient.display}${L}`;
|
|
140
155
|
}
|
|
141
156
|
}
|
|
157
|
+
}
|
|
142
158
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
get dividers(): Monom[] {
|
|
160
|
+
// Decompose only if the coefficient is a natural number
|
|
161
|
+
if (this.coefficient.denominator !== 1) {
|
|
162
|
+
return [this.clone()]
|
|
163
|
+
}
|
|
164
|
+
// Decompose only if the power values are natural numbers.
|
|
165
|
+
if (this.hasFractionCoefficient) {
|
|
166
|
+
return [this.clone()]
|
|
167
|
+
}
|
|
148
168
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
169
|
+
// Security : do not do this if greater than 10000
|
|
170
|
+
if (this.coefficient.numerator > 10000) {
|
|
171
|
+
return [this.clone()]
|
|
172
|
+
}
|
|
173
|
+
const dividers = Numeric.dividers(Math.abs(this.coefficient.numerator))
|
|
154
174
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
175
|
+
// Decompose the literals parts.
|
|
176
|
+
let literals: literalType[] = [];
|
|
177
|
+
for (let L in this.literal) {
|
|
178
|
+
// L is the letter.
|
|
179
|
+
literals = this._getLiteralDividers(literals, L)
|
|
180
|
+
}
|
|
161
181
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
let M = new Monom();
|
|
167
|
-
M.coefficient = new Fraction(N)
|
|
168
|
-
M.literal = L
|
|
169
|
-
monomDividers.push(M)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
} else if (dividers.length === 0) {
|
|
173
|
-
for (let L of litterals) {
|
|
174
|
-
let M = new Monom();
|
|
175
|
-
M.coefficient = new Fraction().one()
|
|
176
|
-
M.literal = L
|
|
177
|
-
monomDividers.push(M)
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
for (let N of dividers) {
|
|
182
|
+
const monomDividers: Monom[] = [];
|
|
183
|
+
if (literals.length > 0 && dividers.length > 0) {
|
|
184
|
+
for (let N of dividers) {
|
|
185
|
+
for (let L of literals) {
|
|
181
186
|
let M = new Monom();
|
|
182
187
|
M.coefficient = new Fraction(N)
|
|
188
|
+
M.literal = L
|
|
183
189
|
monomDividers.push(M)
|
|
184
190
|
}
|
|
185
191
|
}
|
|
186
|
-
|
|
187
|
-
|
|
192
|
+
} else if (dividers.length === 0) {
|
|
193
|
+
for (let L of literals) {
|
|
194
|
+
let M = new Monom();
|
|
195
|
+
M.coefficient = new Fraction().one()
|
|
196
|
+
M.literal = L
|
|
197
|
+
monomDividers.push(M)
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
for (let N of dividers) {
|
|
201
|
+
let M = new Monom();
|
|
202
|
+
M.coefficient = new Fraction(N)
|
|
203
|
+
monomDividers.push(M)
|
|
204
|
+
}
|
|
188
205
|
}
|
|
189
206
|
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
return monomDividers.length === 0 ? [new Monom().one()] : monomDividers;
|
|
208
|
+
}
|
|
192
209
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
210
|
+
private _getLiteralDividers(arr: literalType[], letter: string): literalType[] {
|
|
211
|
+
let tmpList: { [key: string]: Fraction }[] = [];
|
|
212
|
+
|
|
213
|
+
// Be default, this.literal[letter] should be a rational number.
|
|
214
|
+
for (let d = 0; d <= this.literal[letter].value; d++) {
|
|
215
|
+
if (arr.length === 0) {
|
|
216
|
+
let litt: literalType = {}
|
|
217
|
+
litt[letter] = new Fraction(d)
|
|
218
|
+
tmpList.push(litt)
|
|
219
|
+
} else {
|
|
220
|
+
for (let item of arr) {
|
|
221
|
+
let litt: literalType = {}
|
|
222
|
+
for (let currentLetter in item) {
|
|
223
|
+
litt[currentLetter] = item[currentLetter]
|
|
206
224
|
}
|
|
225
|
+
litt[letter] = new Fraction(d)
|
|
226
|
+
tmpList.push(litt)
|
|
207
227
|
}
|
|
208
228
|
}
|
|
209
|
-
return tmpList;
|
|
210
229
|
}
|
|
230
|
+
return tmpList;
|
|
231
|
+
}
|
|
211
232
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
233
|
+
/**
|
|
234
|
+
* Display the monom, forcing the '+' sign to appear
|
|
235
|
+
*/
|
|
236
|
+
get displayWithSign(): string {
|
|
237
|
+
// TODO: Rename or remove this getter ?
|
|
238
|
+
let d: String = this.display;
|
|
239
|
+
return (d[0] !== '-' ? '+' : '') + d;
|
|
240
|
+
}
|
|
220
241
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Get the tex output of the monom
|
|
244
|
+
*/
|
|
245
|
+
get tex(): string {
|
|
246
|
+
// TODO: display with square root !
|
|
247
|
+
let L: string = '',
|
|
248
|
+
letters = Object.keys(this._literal).sort()
|
|
249
|
+
|
|
250
|
+
for (let letter of letters) {
|
|
251
|
+
if (this._literal[letter].isNotZero()) {
|
|
252
|
+
L += `${letter}`;
|
|
253
|
+
if (this._literal[letter].isNotEqual(1)) {
|
|
254
|
+
L += `^{${this._literal[letter].display}}`;
|
|
232
255
|
}
|
|
233
256
|
}
|
|
257
|
+
}
|
|
234
258
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
} else {
|
|
240
|
-
return '0';
|
|
241
|
-
}
|
|
259
|
+
if (L === '') {
|
|
260
|
+
// No setLetter - means it's only a number !
|
|
261
|
+
if (this._coefficient.value != 0) {
|
|
262
|
+
return `${this._coefficient.dfrac}`;
|
|
242
263
|
} else {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
264
|
+
return '0';
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
if (this._coefficient.value === 1) {
|
|
268
|
+
return L;
|
|
269
|
+
} else if (this._coefficient.value === -1) {
|
|
270
|
+
return `-${L}`;
|
|
271
|
+
} else if (this._coefficient.value === 0) {
|
|
272
|
+
return '0';
|
|
273
|
+
} else {
|
|
274
|
+
return `${this._coefficient.dfrac}${L}`;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ------------------------------------------
|
|
280
|
+
// Creation / parsing functions
|
|
281
|
+
// -----------------------------------------
|
|
282
|
+
/**
|
|
283
|
+
* Parse a string to a monom. The string may include fraction.
|
|
284
|
+
* @param inputStr
|
|
285
|
+
*/
|
|
286
|
+
parse = (inputStr: string): Monom => {
|
|
287
|
+
this._shutingYardToReducedMonom(inputStr)
|
|
288
|
+
//
|
|
289
|
+
// // Set the literal part.
|
|
290
|
+
// this.literalStr = inputStr;
|
|
291
|
+
//
|
|
292
|
+
// // Get the coefficient
|
|
293
|
+
// this._coefficient = new Fraction();
|
|
294
|
+
// for (const v of [...inputStr.replace(/([a-z])|(\^[+-]?[0-9]+)/g, ',').split(',')]) {
|
|
295
|
+
// // The value is empty.
|
|
296
|
+
// if (v.trim() === '') {
|
|
297
|
+
// continue;
|
|
298
|
+
// }
|
|
299
|
+
//
|
|
300
|
+
// // Multiply the current coefficient by the new found value.
|
|
301
|
+
// this._coefficient.multiply(new Fraction(v.trim()));
|
|
302
|
+
// }
|
|
303
|
+
|
|
304
|
+
return this;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
private _shutingYardToReducedMonom = (inputStr: string): Monom => {
|
|
308
|
+
// Get the RPN array of the current expression
|
|
309
|
+
const SY: Shutingyard = new Shutingyard().parse(inputStr);
|
|
310
|
+
const rpn: { token: string, tokenType: string }[] = SY.rpn;
|
|
311
|
+
|
|
312
|
+
let stack: Monom[] = [], m, pow, letter, q1, q2
|
|
313
|
+
|
|
314
|
+
if(rpn.length===0){
|
|
315
|
+
this.zero()
|
|
316
|
+
return this
|
|
317
|
+
}else if(rpn.length===1){
|
|
318
|
+
const element = rpn[0]
|
|
319
|
+
|
|
320
|
+
this.one()
|
|
321
|
+
if (element.tokenType === 'coefficient') {
|
|
322
|
+
this.coefficient = new Fraction(element.token)
|
|
323
|
+
} else if (element.tokenType === 'variable') {
|
|
324
|
+
this.setLetter(element.token, 1)
|
|
325
|
+
}
|
|
326
|
+
return this
|
|
327
|
+
}else{
|
|
328
|
+
// Reset the monom
|
|
329
|
+
this.one()
|
|
330
|
+
for (const element of rpn) {
|
|
331
|
+
if (element.tokenType === 'coefficient') {
|
|
332
|
+
let M = new Monom().one()
|
|
333
|
+
M.coefficient = new Fraction(element.token)
|
|
334
|
+
stack.push(M.clone())
|
|
335
|
+
} else if (element.tokenType === 'variable') {
|
|
336
|
+
let M = new Monom().one()
|
|
337
|
+
M.setLetter(element.token, 1)
|
|
338
|
+
stack.push(M.clone())
|
|
339
|
+
} else if (element.tokenType === 'operation') {
|
|
340
|
+
switch (element.token) {
|
|
341
|
+
case '-':
|
|
342
|
+
// this should only happen for negative powers or for negative coefficient.
|
|
343
|
+
q2 = (stack.pop()) || new Monom().zero()
|
|
344
|
+
q1 = (stack.pop()) || new Monom().zero()
|
|
345
|
+
|
|
346
|
+
if(q1.isZero() && q2.isZero()){
|
|
347
|
+
this.opposed()
|
|
348
|
+
break
|
|
349
|
+
}
|
|
350
|
+
stack.push(q1.subtract(q2))
|
|
351
|
+
break;
|
|
352
|
+
case '*':
|
|
353
|
+
// Get the last element in the stack
|
|
354
|
+
m = (stack.pop()) || new Monom().one()
|
|
355
|
+
this.multiply(m)
|
|
356
|
+
break
|
|
357
|
+
case '^':
|
|
358
|
+
// get the two last elements in the stack
|
|
359
|
+
pow = (stack.pop().coefficient) || new Fraction().one()
|
|
360
|
+
m = (stack.pop()) || new Monom().one()
|
|
361
|
+
|
|
362
|
+
letter = m.variables[0]
|
|
363
|
+
|
|
364
|
+
if(letter!==undefined) {
|
|
365
|
+
m.setLetter(letter, pow)
|
|
366
|
+
}
|
|
367
|
+
this.multiply(m.clone())
|
|
368
|
+
break
|
|
369
|
+
}
|
|
251
370
|
}
|
|
252
371
|
}
|
|
253
372
|
}
|
|
254
373
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
parse = (inputStr: string): Monom => {
|
|
263
|
-
// Set the literal part.
|
|
264
|
-
this.literalStr = inputStr;
|
|
374
|
+
return this
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Clone the current Monom.
|
|
378
|
+
*/
|
|
379
|
+
clone = (): Monom => {
|
|
380
|
+
let F: Monom = new Monom();
|
|
265
381
|
|
|
266
|
-
|
|
267
|
-
this._coefficient = new Fraction();
|
|
382
|
+
F.coefficient = this._coefficient.clone();
|
|
268
383
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
this._coefficient = new Fraction().zero();
|
|
302
|
-
this._literal = {};
|
|
303
|
-
return this;
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Create a one value monom
|
|
308
|
-
*/
|
|
309
|
-
one = (): Monom => {
|
|
310
|
-
this._coefficient = new Fraction().one();
|
|
311
|
-
this._literal = {};
|
|
312
|
-
return this;
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Clean the monom by removing each letters with a power of zero.
|
|
317
|
-
*/
|
|
318
|
-
clean = (): Monom => {
|
|
319
|
-
for (let letter in this._literal) {
|
|
320
|
-
if (this._literal[letter] === 0) {
|
|
321
|
-
delete this._literal[letter];
|
|
322
|
-
}
|
|
384
|
+
// Copy the literal parts.
|
|
385
|
+
for (let k in this._literal) {
|
|
386
|
+
F.setLetter(k, this._literal[k].clone());
|
|
387
|
+
}
|
|
388
|
+
return F;
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Create a zero value monom
|
|
393
|
+
*/
|
|
394
|
+
zero = (): Monom => {
|
|
395
|
+
this._coefficient = new Fraction().zero();
|
|
396
|
+
this._literal = {};
|
|
397
|
+
return this;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Create a one value monom
|
|
402
|
+
*/
|
|
403
|
+
one = (): Monom => {
|
|
404
|
+
this._coefficient = new Fraction().one();
|
|
405
|
+
this._literal = {};
|
|
406
|
+
return this;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Clean the monom by removing each letters with a power of zero.
|
|
411
|
+
*/
|
|
412
|
+
clean = (): Monom => {
|
|
413
|
+
for (let letter in this._literal) {
|
|
414
|
+
if (this._literal[letter].isZero()) {
|
|
415
|
+
delete this._literal[letter];
|
|
323
416
|
}
|
|
417
|
+
}
|
|
324
418
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
419
|
+
return this;
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
// ------------------------------------------
|
|
423
|
+
// Mathematical operations
|
|
424
|
+
// ------------------------------------------
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Get the opposed
|
|
428
|
+
* Returns a monom.
|
|
429
|
+
*/
|
|
430
|
+
opposed = (): Monom => {
|
|
431
|
+
this._coefficient.opposed();
|
|
432
|
+
return this;
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Add all similar monoms. If they aren't similar, they are simply skipped.
|
|
437
|
+
* @param M (Monom[]) The monoms to add.
|
|
438
|
+
*/
|
|
439
|
+
add = (...M: Monom[]): Monom => {
|
|
440
|
+
for (let m of M) {
|
|
441
|
+
if (this.isSameAs(m)) {
|
|
442
|
+
this._coefficient.add(m.coefficient);
|
|
443
|
+
} else {
|
|
444
|
+
console.log('Add: Is not similar: ', m.display);
|
|
352
445
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
446
|
+
}
|
|
447
|
+
return this;
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Subtract multiple monoms
|
|
452
|
+
* @param M (Monom[]) The monoms to subtract
|
|
453
|
+
*/
|
|
454
|
+
subtract = (...M: Monom[]): Monom => {
|
|
455
|
+
for (let m of M) {
|
|
456
|
+
if (this.isSameAs(m)) {
|
|
457
|
+
this._coefficient.add(m.coefficient.clone().opposed());
|
|
458
|
+
} else {
|
|
459
|
+
console.log('Subtract: Is not similar: ', m.display);
|
|
367
460
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
461
|
+
}
|
|
462
|
+
return this;
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Multiple multiple monoms to the current monom
|
|
467
|
+
* @param M (Monom[]) The monoms to multiply to.
|
|
468
|
+
*/
|
|
469
|
+
multiply = (...M: Monom[]): Monom => {
|
|
470
|
+
for (let m of M) {
|
|
471
|
+
// Multiply the coefficient.
|
|
472
|
+
this._coefficient.multiply(m.coefficient);
|
|
473
|
+
|
|
474
|
+
// Multiply the literal parts.
|
|
475
|
+
for (let letter in m.literal) {
|
|
476
|
+
if (this._literal[letter] === undefined) {
|
|
477
|
+
this._literal[letter] = m.literal[letter].clone()
|
|
478
|
+
} else {
|
|
479
|
+
this._literal[letter].add(m.literal[letter])
|
|
382
480
|
}
|
|
383
|
-
}
|
|
384
|
-
return this;
|
|
385
|
-
};
|
|
386
481
|
|
|
387
|
-
|
|
388
|
-
this._coefficient.multiply(F);
|
|
389
|
-
return this;
|
|
482
|
+
}
|
|
390
483
|
}
|
|
484
|
+
return this;
|
|
485
|
+
};
|
|
391
486
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
divide = (...M: Monom[]): Monom => {
|
|
397
|
-
// Depending on the given value, choose the current item
|
|
398
|
-
for (let v of M) {
|
|
399
|
-
// Divide the coefficient
|
|
400
|
-
this._coefficient.divide(v.coefficient);
|
|
401
|
-
|
|
402
|
-
// Subtract the power values
|
|
403
|
-
for (let letter in v.literal) {
|
|
404
|
-
this._literal[letter] = (this._literal[letter] === undefined) ? -v.literal[letter] : this._literal[letter] - v.literal[letter];
|
|
487
|
+
multiplyByNumber = (F: Fraction | number): Monom => {
|
|
488
|
+
this._coefficient.multiply(F);
|
|
489
|
+
return this;
|
|
490
|
+
}
|
|
405
491
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
492
|
+
/**
|
|
493
|
+
* Divide the current monoms by multiple monoms
|
|
494
|
+
* @param M (Monom[])
|
|
495
|
+
*/
|
|
496
|
+
divide = (...M: Monom[]): Monom => {
|
|
497
|
+
// Depending on the given value, choose the current item
|
|
498
|
+
for (let v of M) {
|
|
499
|
+
// Divide the coefficient
|
|
500
|
+
this._coefficient.divide(v.coefficient);
|
|
501
|
+
|
|
502
|
+
// Subtract the power values
|
|
503
|
+
for (let letter in v.literal) {
|
|
504
|
+
this._literal[letter] = (this._literal[letter] === undefined) ? v.literal[letter].clone().opposed() : this._literal[letter].subtract(v.literal[letter])
|
|
505
|
+
|
|
506
|
+
// If the power of a particular setLetter is zero, delete it from the literal part..
|
|
507
|
+
if (this._literal[letter].isZero()) {
|
|
508
|
+
delete this._literal[letter];
|
|
410
509
|
}
|
|
411
510
|
}
|
|
412
|
-
|
|
413
|
-
|
|
511
|
+
}
|
|
512
|
+
return this;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Get the pow of a monom.
|
|
517
|
+
* @param nb (number) : Mathematical pow
|
|
518
|
+
*/
|
|
519
|
+
pow = (nb: number): Monom => {
|
|
520
|
+
this._coefficient.pow(nb);
|
|
521
|
+
for (let letter in this._literal) {
|
|
522
|
+
this._literal[letter].pow(nb)
|
|
523
|
+
}
|
|
524
|
+
return this;
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Get the nth-root of the monom
|
|
529
|
+
* @param p
|
|
530
|
+
*/
|
|
531
|
+
root = (p: number): Monom => {
|
|
532
|
+
// TODO: determiner the nth root of a monom
|
|
533
|
+
return this;
|
|
534
|
+
}
|
|
414
535
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
this._coefficient.
|
|
536
|
+
/**
|
|
537
|
+
* Return the square root of a monom
|
|
538
|
+
*/
|
|
539
|
+
sqrt = (): Monom => {
|
|
540
|
+
if (this.isSquare()) {
|
|
541
|
+
this._coefficient.sqrt();
|
|
421
542
|
for (let letter in this._literal) {
|
|
422
|
-
this._literal[letter]
|
|
423
|
-
}
|
|
424
|
-
return this;
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* Get the nth-root of the monom
|
|
429
|
-
* @param p
|
|
430
|
-
*/
|
|
431
|
-
root = (p: number): Monom => {
|
|
432
|
-
// TODO: determiner the nth root of a monom
|
|
433
|
-
return this;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Return the square root of a monom
|
|
438
|
-
*/
|
|
439
|
-
sqrt = (): Monom => {
|
|
440
|
-
if (this.isSquare()) {
|
|
441
|
-
this._coefficient.sqrt();
|
|
442
|
-
for (let letter in this._literal) {
|
|
443
|
-
this._literal[letter] /= 2;
|
|
444
|
-
}
|
|
543
|
+
this._literal[letter].clone().divide(2)
|
|
445
544
|
}
|
|
446
|
-
return this.root(2);
|
|
447
545
|
}
|
|
546
|
+
return this.root(2);
|
|
547
|
+
}
|
|
448
548
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
549
|
+
// ------------------------------------------
|
|
550
|
+
// Compare functions
|
|
551
|
+
// ------------------------------------------
|
|
552
|
+
compare = (M: Monom, sign?: string): boolean => {
|
|
553
|
+
// TODO: Build the compare systems.
|
|
554
|
+
if (sign === undefined) {
|
|
555
|
+
sign = '=';
|
|
556
|
+
}
|
|
457
557
|
|
|
458
558
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
559
|
+
switch (sign) {
|
|
560
|
+
case '=':
|
|
561
|
+
// To be equal, they must be the isSame
|
|
562
|
+
if (!this.compare(M, 'same')) {
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// The literal parts are the isSame. The coefficient must be equal
|
|
567
|
+
return this._coefficient.isEqual(M.coefficient);
|
|
568
|
+
case 'same':
|
|
569
|
+
// Get the list of all variables from both monoms.
|
|
570
|
+
let M1: string[] = this.variables,
|
|
571
|
+
M2: string[] = M.variables,
|
|
572
|
+
K: string[] = M1.concat(M2.filter((item) => M1.indexOf(item) < 0));
|
|
573
|
+
|
|
574
|
+
for (let key of K) {
|
|
575
|
+
// The setLetter is not available in one of the monom
|
|
576
|
+
if (this._literal[key] === undefined || M.literal[key] === undefined) {
|
|
463
577
|
return false;
|
|
464
578
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
case 'same':
|
|
469
|
-
// Get the list of all variables from both monoms.
|
|
470
|
-
let M1: string[] = this.variables,
|
|
471
|
-
M2: string[] = M.variables,
|
|
472
|
-
K: string[] = M1.concat(M2.filter((item) => M1.indexOf(item) < 0));
|
|
473
|
-
|
|
474
|
-
for (let key of K) {
|
|
475
|
-
// The setLetter is not available in one of the monom
|
|
476
|
-
if (this._literal[key] === undefined || M.literal[key] === undefined) {
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
// The setLetter does not have the isSame power in each monoms.
|
|
480
|
-
if (this._literal[key] !== M.literal[key]) {
|
|
481
|
-
return false;
|
|
482
|
-
}
|
|
579
|
+
// The setLetter does not have the isSame power in each monoms.
|
|
580
|
+
if (!this._literal[key].isEqual(M.literal[key])) {
|
|
581
|
+
return false;
|
|
483
582
|
}
|
|
583
|
+
}
|
|
484
584
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
585
|
+
// All are positive check - the monoms are the sames.
|
|
586
|
+
return true;
|
|
587
|
+
default:
|
|
588
|
+
return false;
|
|
490
589
|
}
|
|
590
|
+
}
|
|
491
591
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
592
|
+
/**
|
|
593
|
+
* Determine if the monom is null
|
|
594
|
+
*/
|
|
595
|
+
isZero(): boolean {
|
|
596
|
+
return this._coefficient.value === 0;
|
|
597
|
+
}
|
|
498
598
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
599
|
+
/**
|
|
600
|
+
* Determine if the monom is one
|
|
601
|
+
*/
|
|
602
|
+
isOne(): boolean {
|
|
603
|
+
return this._coefficient.value === 1 && this.variables.length === 0;
|
|
604
|
+
}
|
|
505
605
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
606
|
+
/**
|
|
607
|
+
* Determine if two monoms are equals
|
|
608
|
+
* @param M
|
|
609
|
+
*/
|
|
610
|
+
isEqual = (M: Monom): boolean => {
|
|
611
|
+
return this.compare(M, '=');
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Determine if two monoms are similar
|
|
616
|
+
* @param M
|
|
617
|
+
*/
|
|
618
|
+
isSameAs = (M: Monom): boolean => {
|
|
619
|
+
return this.compare(M, 'same');
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
isSquare = (): boolean => {
|
|
623
|
+
if (!this.coefficient.isSquare()) {
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
return this.isLiteralSquare();
|
|
627
|
+
}
|
|
513
628
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
};
|
|
629
|
+
isLiteralSquare = (): boolean => {
|
|
630
|
+
for (let letter in this.literal) {
|
|
631
|
+
// A literal square must have a natural power
|
|
632
|
+
if (this.literal[letter].isRational()) {
|
|
633
|
+
return false
|
|
634
|
+
}
|
|
521
635
|
|
|
522
|
-
|
|
523
|
-
if (
|
|
636
|
+
// The natural power must be be even
|
|
637
|
+
if (this.literal[letter].isEven()) {
|
|
524
638
|
return false;
|
|
525
639
|
}
|
|
526
|
-
return this.isLitteralSquare();
|
|
527
640
|
}
|
|
528
641
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
if (this.literal[letter] % 2 !== 0) {
|
|
532
|
-
return false;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
return true;
|
|
536
|
-
}
|
|
537
|
-
// ------------------------------------------
|
|
538
|
-
// Misc monoms functions
|
|
539
|
-
// -------------------------------------
|
|
540
|
-
/**
|
|
541
|
-
* Determine if a monom contains a setLetter in it's literal part
|
|
542
|
-
* @param letter
|
|
543
|
-
*/
|
|
544
|
-
hasLetter = (letter?: string): boolean => {
|
|
545
|
-
return this._literal[letter === undefined ? 'x' : letter] > 0;
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
/**
|
|
549
|
-
* Set the power of a particular setLetter
|
|
550
|
-
* @param letter (string) Letter to change
|
|
551
|
-
* @param pow (number) Power of the setLetter (must be positive integer.
|
|
552
|
-
*/
|
|
553
|
-
setLetter = (letter: string, pow: number): void => {
|
|
554
|
-
// If the power is not legal or is zero, remove the setLetter from the dict
|
|
555
|
-
if (pow <= 0 || !Number.isSafeInteger(pow)) {
|
|
556
|
-
if (this._literal[letter] !== undefined) {
|
|
557
|
-
delete this._literal[letter];
|
|
558
|
-
}
|
|
559
|
-
} else {
|
|
560
|
-
this._literal[letter] = pow;
|
|
561
|
-
}
|
|
562
|
-
};
|
|
642
|
+
return true;
|
|
643
|
+
}
|
|
563
644
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
degree = (letter?: string): number => {
|
|
569
|
-
if (this.variables.length === 0) {
|
|
570
|
-
return 0;
|
|
571
|
-
}
|
|
572
|
-
if (letter === undefined) {
|
|
573
|
-
// Not setLetter given -> we get the global monom degree (sum of all the letters).
|
|
574
|
-
return Object.values(this._literal).reduce((t, n) => t + n);
|
|
575
|
-
} else {
|
|
576
|
-
// A setLetter is given -> get the corresponding power.
|
|
577
|
-
return this._literal[letter] === undefined ? 0 : this._literal[letter];
|
|
645
|
+
hasFractionCoefficient = (): boolean => {
|
|
646
|
+
for (let letter in this._literal) {
|
|
647
|
+
if (this._literal[letter].isRational()) {
|
|
648
|
+
return true
|
|
578
649
|
}
|
|
579
|
-
}
|
|
650
|
+
}
|
|
580
651
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
652
|
+
return false
|
|
653
|
+
}
|
|
654
|
+
// ------------------------------------------
|
|
655
|
+
// Misc monoms functions
|
|
656
|
+
// -------------------------------------
|
|
657
|
+
/**
|
|
658
|
+
* Determine if a monom contains a setLetter in it's literal part
|
|
659
|
+
* @param letter
|
|
660
|
+
*/
|
|
661
|
+
hasLetter = (letter?: string): boolean => {
|
|
662
|
+
// The letter was not found
|
|
663
|
+
if (this._literal[letter === undefined ? 'x' : letter] === undefined) {
|
|
664
|
+
return false
|
|
665
|
+
}
|
|
587
666
|
|
|
588
|
-
|
|
589
|
-
|
|
667
|
+
// The letter is found and is not zero !
|
|
668
|
+
return this._literal[letter === undefined ? 'x' : letter].isNotZero();
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Set the power of a particular setLetter
|
|
673
|
+
* @param letter (string) Letter to change
|
|
674
|
+
* @param pow (number) Power of the setLetter (must be positive integer.
|
|
675
|
+
*/
|
|
676
|
+
setLetter = (letter: string, pow: Fraction | number): void => {
|
|
677
|
+
if (pow instanceof Fraction) {
|
|
678
|
+
// Set the power of the letter to zero => remove it
|
|
679
|
+
if (this.hasLetter(letter) && pow.isZero()) {
|
|
680
|
+
delete this._literal[letter]
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
this._literal[letter] = pow.clone()
|
|
684
|
+
} else {
|
|
685
|
+
this.setLetter(letter, new Fraction(pow))
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Get the degree of a monom. If no setLetter is given, the result will be the global degree.
|
|
691
|
+
* @param letter (string) Letter to get to degree (power)
|
|
692
|
+
*/
|
|
693
|
+
degree = (letter?: string): Fraction => {
|
|
694
|
+
if (this.variables.length === 0) {
|
|
695
|
+
return new Fraction().zero();
|
|
696
|
+
}
|
|
697
|
+
if (letter === undefined) {
|
|
698
|
+
// Not setLetter given -> we get the global monom degree (sum of all the letters).
|
|
699
|
+
return Object.values(this._literal).reduce((t, n) => t.clone().add(n));
|
|
700
|
+
} else {
|
|
701
|
+
// A setLetter is given -> get the corresponding power.
|
|
702
|
+
return this._literal[letter] === undefined ? new Fraction().zero() : this._literal[letter].clone();
|
|
703
|
+
}
|
|
704
|
+
};
|
|
590
705
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
706
|
+
/**
|
|
707
|
+
* Evaluate a monom. Each setLetter must be assigned to a Fraction.
|
|
708
|
+
* @param values Dictionary of <setLetter: Fraction>
|
|
709
|
+
*/
|
|
710
|
+
evaluate = (values: literalType | Fraction | number): Fraction => {
|
|
711
|
+
let r = this.coefficient.clone();
|
|
594
712
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
713
|
+
if (typeof values === 'number' || values instanceof Fraction) {
|
|
714
|
+
let tmpValues: literalType = {}
|
|
715
|
+
|
|
716
|
+
tmpValues[this.variables[0]] = new Fraction(values)
|
|
717
|
+
return this.evaluate(tmpValues);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (typeof values === 'object') {
|
|
721
|
+
for (let L in this._literal) {
|
|
722
|
+
if (values[L] === undefined) {
|
|
723
|
+
return new Fraction().zero();
|
|
602
724
|
}
|
|
603
|
-
}
|
|
604
|
-
return r;
|
|
605
|
-
};
|
|
606
725
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
* @param letter
|
|
610
|
-
*/
|
|
611
|
-
derivative = (letter?: string): Monom => {
|
|
612
|
-
// No setLetter given - assume it's the setLetter 'x'
|
|
613
|
-
if (letter === undefined) {
|
|
614
|
-
letter = 'x';
|
|
726
|
+
let value = new Fraction(values[L])
|
|
727
|
+
r.multiply(value.pow(this._literal[L]))
|
|
615
728
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
729
|
+
}
|
|
730
|
+
return r;
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Derivative the monom
|
|
735
|
+
* @param letter
|
|
736
|
+
*/
|
|
737
|
+
derivative = (letter?: string): Monom => {
|
|
738
|
+
// No setLetter given - assume it's the setLetter 'x'
|
|
739
|
+
if (letter === undefined) {
|
|
740
|
+
letter = 'x';
|
|
741
|
+
}
|
|
619
742
|
|
|
620
|
-
|
|
621
|
-
|
|
743
|
+
if (this.hasLetter(letter)) {
|
|
744
|
+
let d = this._literal[letter].clone(),
|
|
745
|
+
dM = this.clone();
|
|
622
746
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
}
|
|
747
|
+
// Subtract one to the degree.
|
|
748
|
+
dM._literal[letter].subtract(1)
|
|
749
|
+
|
|
750
|
+
// Multiply the coefficient by the previous degree
|
|
751
|
+
dM._coefficient.multiply(new Fraction(d.clone()));
|
|
752
|
+
return dM;
|
|
753
|
+
} else {
|
|
754
|
+
return new Monom().zero();
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
primitive = (letter?: string): Monom => {
|
|
759
|
+
// TODO: derivative including the ln value => implies creating different monom system ?
|
|
760
|
+
if (letter === undefined) {
|
|
761
|
+
letter = 'x'
|
|
762
|
+
}
|
|
630
763
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
764
|
+
// Zero monom
|
|
765
|
+
let M = this.clone(), degree
|
|
766
|
+
|
|
767
|
+
if (M.hasLetter(letter)) {
|
|
768
|
+
degree = M.degree(letter).clone().add(1)
|
|
769
|
+
M.coefficient = M.coefficient.clone().divide(degree)
|
|
770
|
+
M.setLetter(letter, degree)
|
|
771
|
+
} else {
|
|
772
|
+
// There is no letter.
|
|
773
|
+
|
|
774
|
+
// The coefficient might be zero (=> x) or a number a (=> ax)
|
|
775
|
+
if (M.coefficient.isZero()) {
|
|
776
|
+
M.coefficient = new Fraction().one()
|
|
777
|
+
}
|
|
778
|
+
M.setLetter(letter, 1)
|
|
779
|
+
}
|
|
780
|
+
return M
|
|
781
|
+
}
|
|
782
|
+
// ----------------------------------------
|
|
783
|
+
// Static functions
|
|
784
|
+
// ----------------------------------------
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Get the least common multiple of monoms
|
|
788
|
+
* @param monoms Array of monoms
|
|
789
|
+
*/
|
|
790
|
+
static lcm = (...monoms: Monom[]): Monom => {
|
|
791
|
+
// All the monoms must be with natural powers...
|
|
792
|
+
for (let m of monoms) {
|
|
793
|
+
if (m.hasFractionCoefficient()) {
|
|
794
|
+
return new Monom().zero()
|
|
634
795
|
}
|
|
796
|
+
}
|
|
635
797
|
|
|
636
|
-
// Zero monom
|
|
637
|
-
let M = this.clone()
|
|
638
798
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
799
|
+
let M = new Monom(),
|
|
800
|
+
coeffN: number[] = monoms.map(value => value.coefficient.numerator),
|
|
801
|
+
coeffD: number[] = monoms.map(value => value.coefficient.denominator),
|
|
802
|
+
n = Numeric.gcd(...coeffN),
|
|
803
|
+
d = Numeric.lcm(...coeffD);
|
|
644
804
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
// Static functions
|
|
655
|
-
// ----------------------------------------
|
|
656
|
-
|
|
657
|
-
/**
|
|
658
|
-
* Get the least common multiple of monoms
|
|
659
|
-
* @param monoms Array of monoms
|
|
660
|
-
*/
|
|
661
|
-
static lcm = (...monoms: Monom[]): Monom => {
|
|
662
|
-
let M = new Monom(),
|
|
663
|
-
coeffN: number[] = monoms.map(value => value.coefficient.numerator),
|
|
664
|
-
coeffD: number[] = monoms.map(value => value.coefficient.denominator),
|
|
665
|
-
n = Numeric.gcd(...coeffN),
|
|
666
|
-
d = Numeric.lcm(...coeffD);
|
|
667
|
-
|
|
668
|
-
// Get the coefficient.
|
|
669
|
-
M.coefficient = new Fraction(n, d).reduce();
|
|
670
|
-
|
|
671
|
-
// Set the literal parts - go through each monoms literal parts and get only the lowest degree of each letters.
|
|
672
|
-
for (let m of monoms) {
|
|
673
|
-
// Remove the inexistant letters from the resulting monom
|
|
674
|
-
for (let letter in M.literal) {
|
|
675
|
-
if (!(letter in m.literal)) {
|
|
676
|
-
M.literal[letter] = 0;
|
|
677
|
-
}
|
|
805
|
+
// Get the coefficient.
|
|
806
|
+
M.coefficient = new Fraction(n, d).reduce();
|
|
807
|
+
|
|
808
|
+
// Set the literal parts - go through each monoms literal parts and get only the lowest degree of each letters.
|
|
809
|
+
for (let m of monoms) {
|
|
810
|
+
// Remove the inexistant letters from the resulting monom
|
|
811
|
+
for (let letter in M.literal) {
|
|
812
|
+
if (!(letter in m.literal)) {
|
|
813
|
+
M.literal[letter].zero();
|
|
678
814
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
815
|
+
}
|
|
816
|
+
for (let letter in m.literal) {
|
|
817
|
+
if (M.literal[letter] === undefined && m.literal[letter].isStrictlyPositive()) {
|
|
818
|
+
M.literal[letter] = m.literal[letter].clone();
|
|
819
|
+
} else {
|
|
820
|
+
M.literal[letter] = new Fraction(Math.min(m.literal[letter].value, M.literal[letter].value))
|
|
685
821
|
}
|
|
686
822
|
}
|
|
823
|
+
}
|
|
687
824
|
|
|
688
|
-
|
|
689
|
-
|
|
825
|
+
return M;
|
|
826
|
+
};
|
|
690
827
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
828
|
+
/**
|
|
829
|
+
* Multiply two monoms and return a NEW monom.
|
|
830
|
+
* @param monoms
|
|
831
|
+
*/
|
|
832
|
+
static xmultiply = (...monoms: Monom[]): Monom => {
|
|
833
|
+
let M = new Monom().one();
|
|
697
834
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
835
|
+
for (let m of monoms) {
|
|
836
|
+
M.multiply(m);
|
|
837
|
+
}
|
|
701
838
|
|
|
702
|
-
|
|
703
|
-
|
|
839
|
+
return M;
|
|
840
|
+
};
|
|
704
841
|
|
|
705
842
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
843
|
+
// TODO: The rest of the functions are not used or unnecessary ?
|
|
844
|
+
/**
|
|
845
|
+
* Determine if multiple monoms are similar
|
|
846
|
+
* @param M
|
|
847
|
+
*/
|
|
848
|
+
areSameAs = (...M: Monom[]): boolean => {
|
|
849
|
+
let result: boolean = true;
|
|
713
850
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
}
|
|
851
|
+
// Check all monoms if they are the isSame as the "this" one.
|
|
852
|
+
for (let i = 0; i < M.length; i++) {
|
|
853
|
+
if (!this.isSameAs(M[i])) {
|
|
854
|
+
return false;
|
|
719
855
|
}
|
|
856
|
+
}
|
|
720
857
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
858
|
+
// All check passed -> all the monoms are similar.
|
|
859
|
+
return result;
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Determine if multiple monoms are equals
|
|
864
|
+
* @param M
|
|
865
|
+
*/
|
|
866
|
+
areEquals = (...M: Monom[]): boolean => {
|
|
867
|
+
// They are not similar.
|
|
868
|
+
if (!this.areSameAs(...M)) {
|
|
869
|
+
return false;
|
|
870
|
+
}
|
|
724
871
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
*/
|
|
729
|
-
areEquals = (...M: Monom[]): boolean => {
|
|
730
|
-
// They are not similar.
|
|
731
|
-
if (!this.areSameAs(...M)) {
|
|
872
|
+
// Check all coefficient. They must be equals.
|
|
873
|
+
for (let m of M) {
|
|
874
|
+
if (!this._coefficient.isEqual(m.coefficient)) {
|
|
732
875
|
return false;
|
|
733
876
|
}
|
|
877
|
+
}
|
|
734
878
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
return false;
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
// All checks passed.
|
|
743
|
-
return true;
|
|
744
|
-
};
|
|
879
|
+
// All checks passed.
|
|
880
|
+
return true;
|
|
881
|
+
};
|
|
745
882
|
|
|
746
|
-
|
|
883
|
+
}
|