pimath 0.0.127 → 0.0.129
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/dist/main.d.ts +39 -0
- package/{esm → dist}/maths/algebra/equation.d.ts +11 -10
- package/{esm → dist}/maths/algebra/linearSystem.d.ts +5 -4
- package/{esm → dist}/maths/algebra/monom.d.ts +5 -4
- package/{esm → dist}/maths/algebra/polynom.d.ts +11 -13
- package/{esm → dist}/maths/algebra/rational.d.ts +7 -9
- package/dist/maths/algebra/study/rationalStudy.d.ts +14 -0
- package/{esm → dist}/maths/algebra/study.d.ts +4 -7
- package/{esm → dist}/maths/geometry/circle.d.ts +9 -8
- package/{esm → dist}/maths/geometry/line.d.ts +17 -14
- package/{esm → dist}/maths/geometry/point.d.ts +11 -9
- package/{esm → dist}/maths/geometry/triangle.d.ts +4 -3
- package/{esm → dist}/maths/geometry/vector.d.ts +7 -10
- package/{esm → dist}/maths/randomization/random.d.ts +10 -7
- package/{esm → dist}/maths/randomization/rndFraction.d.ts +4 -3
- package/dist/maths/randomization/rndGeometryCircle.d.ts +13 -0
- package/{esm → dist}/maths/randomization/rndGeometryLine.d.ts +4 -3
- package/{esm → dist}/maths/randomization/rndGeometryPoint.d.ts +4 -3
- package/{esm → dist}/maths/randomization/rndMonom.d.ts +5 -4
- package/{esm → dist}/maths/randomization/rndPolynom.d.ts +5 -4
- package/{esm → dist}/maths/randomization/rndTypes.d.ts +7 -1
- package/dist/pimath.js +4239 -7819
- package/package.json +13 -7
- package/.eslintrc.js +0 -24
- package/.idea/$CACHE_FILE$ +0 -6
- package/.idea/PI.iml +0 -14
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/php.xml +0 -19
- package/.idea/shelf/Uncommitted_changes_before_Checkout_at_07_11_2023_08_30_[Default_Changelist]/shelved.patch +0 -192
- package/.idea/shelf/Uncommitted_changes_before_Checkout_at_07_11_2023_08_30_[Default_Changelist]1/shelved.patch +0 -0
- package/.idea/shelf/Uncommitted_changes_before_Checkout_at_07_11_2023_08_30__Default_Changelist_.xml +0 -4
- package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_10_43_[Default_Changelist]/shelved.patch +0 -2404
- package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_10_43__Default_Changelist_.xml +0 -4
- package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_11_01_[Default_Changelist]/shelved.patch +0 -1362
- package/.idea/shelf/Uncommitted_changes_before_Checkout_at_09_11_2023_11_01__Default_Changelist_.xml +0 -4
- package/.idea/shelf/Uncommitted_changes_before_Update_at_24_07_2023_15_31_[Default_Changelist]/shelved.patch +0 -90
- package/.idea/shelf/Uncommitted_changes_before_Update_at_24_07_2023_15_31__Default_Changelist_.xml +0 -4
- package/.idea/vcs.xml +0 -6
- package/dev/pimath.js +0 -7945
- package/dev/pimath.js.map +0 -1
- package/dist/pimath.js.map +0 -1
- package/dist/pimath.min.js +0 -2
- package/dist/pimath.min.js.map +0 -1
- package/docs/.nojekyll +0 -1
- package/docs/assets/highlight.css +0 -78
- package/docs/assets/main.js +0 -59
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1383
- package/docs/classes/Logicalset.Logicalset.html +0 -217
- package/docs/classes/Polynom.Rational.html +0 -397
- package/docs/classes/Vector-1.Vector.html +0 -490
- package/docs/classes/Vector.Point.html +0 -337
- package/docs/classes/algebra_equation.Equation.html +0 -790
- package/docs/classes/algebra_linearSystem.LinearSystem.html +0 -404
- package/docs/classes/algebra_monom.Monom.html +0 -962
- package/docs/classes/algebra_polynom.Polynom.html +0 -1275
- package/docs/classes/coefficients_fraction.Fraction.html +0 -934
- package/docs/classes/geometry_circle.Circle.html +0 -472
- package/docs/classes/geometry_line.Line.html +0 -774
- package/docs/classes/geometry_triangle.Triangle.html +0 -429
- package/docs/classes/numeric.Numeric.html +0 -265
- package/docs/classes/shutingyard.Shutingyard.html +0 -250
- package/docs/enums/algebra_equation.PARTICULAR_SOLUTION.html +0 -83
- package/docs/enums/geometry_line.LinePropriety.html +0 -97
- package/docs/enums/shutingyard.ShutingyardMode.html +0 -97
- package/docs/enums/shutingyard.ShutingyardType.html +0 -111
- package/docs/index.html +0 -63
- package/docs/interfaces/algebra_equation.ISolution.html +0 -105
- package/docs/interfaces/algebra_polynom.IEuclidian.html +0 -87
- package/docs/interfaces/geometry_triangle.remarquableLines.html +0 -163
- package/docs/modules/Logicalset.html +0 -65
- package/docs/modules/Polynom.html +0 -65
- package/docs/modules/Vector-1.html +0 -65
- package/docs/modules/Vector.html +0 -65
- package/docs/modules/algebra_equation.html +0 -69
- package/docs/modules/algebra_linearSystem.html +0 -61
- package/docs/modules/algebra_monom.html +0 -65
- package/docs/modules/algebra_polynom.html +0 -69
- package/docs/modules/coefficients_fraction.html +0 -65
- package/docs/modules/geometry_circle.html +0 -61
- package/docs/modules/geometry_line.html +0 -65
- package/docs/modules/geometry_triangle.html +0 -65
- package/docs/modules/numeric.html +0 -61
- package/docs/modules/shutingyard.html +0 -75
- package/docs/types/algebra_monom.literalType.html +0 -61
- package/docs/types/algebra_polynom.PolynomParsingType.html +0 -56
- package/docs/types/coefficients_fraction.FractionParsingType.html +0 -56
- package/docs/types/shutingyard.Token.html +0 -63
- package/docs/types/shutingyard.tokenType.html +0 -68
- package/docs/variables/shutingyard.tokenConstant.html +0 -61
- package/esm/index.d.ts +0 -38
- package/esm/index.js +0 -44
- package/esm/index.js.map +0 -1
- package/esm/maths/algebra/equation.js +0 -797
- package/esm/maths/algebra/equation.js.map +0 -1
- package/esm/maths/algebra/linearSystem.js +0 -279
- package/esm/maths/algebra/linearSystem.js.map +0 -1
- package/esm/maths/algebra/logicalset.js +0 -158
- package/esm/maths/algebra/logicalset.js.map +0 -1
- package/esm/maths/algebra/monom.js +0 -909
- package/esm/maths/algebra/monom.js.map +0 -1
- package/esm/maths/algebra/polynom.js +0 -1305
- package/esm/maths/algebra/polynom.js.map +0 -1
- package/esm/maths/algebra/rational.js +0 -195
- package/esm/maths/algebra/rational.js.map +0 -1
- package/esm/maths/algebra/study/rationalStudy.d.ts +0 -28
- package/esm/maths/algebra/study/rationalStudy.js +0 -244
- package/esm/maths/algebra/study/rationalStudy.js.map +0 -1
- package/esm/maths/algebra/study.js +0 -380
- package/esm/maths/algebra/study.js.map +0 -1
- package/esm/maths/coefficients/fraction.js +0 -517
- package/esm/maths/coefficients/fraction.js.map +0 -1
- package/esm/maths/coefficients/nthRoot.js +0 -137
- package/esm/maths/coefficients/nthRoot.js.map +0 -1
- package/esm/maths/geometry/circle.js +0 -324
- package/esm/maths/geometry/circle.js.map +0 -1
- package/esm/maths/geometry/line.js +0 -485
- package/esm/maths/geometry/line.js.map +0 -1
- package/esm/maths/geometry/point.js +0 -167
- package/esm/maths/geometry/point.js.map +0 -1
- package/esm/maths/geometry/triangle.js +0 -276
- package/esm/maths/geometry/triangle.js.map +0 -1
- package/esm/maths/geometry/vector.js +0 -198
- package/esm/maths/geometry/vector.js.map +0 -1
- package/esm/maths/numeric.js +0 -136
- package/esm/maths/numeric.js.map +0 -1
- package/esm/maths/numexp.js +0 -186
- package/esm/maths/numexp.js.map +0 -1
- package/esm/maths/randomization/random.js +0 -79
- package/esm/maths/randomization/random.js.map +0 -1
- package/esm/maths/randomization/randomCore.js +0 -22
- package/esm/maths/randomization/randomCore.js.map +0 -1
- package/esm/maths/randomization/rndFraction.js +0 -44
- package/esm/maths/randomization/rndFraction.js.map +0 -1
- package/esm/maths/randomization/rndGeometryLine.js +0 -46
- package/esm/maths/randomization/rndGeometryLine.js.map +0 -1
- package/esm/maths/randomization/rndGeometryPoint.js +0 -61
- package/esm/maths/randomization/rndGeometryPoint.js.map +0 -1
- package/esm/maths/randomization/rndHelpers.js +0 -98
- package/esm/maths/randomization/rndHelpers.js.map +0 -1
- package/esm/maths/randomization/rndMonom.js +0 -53
- package/esm/maths/randomization/rndMonom.js.map +0 -1
- package/esm/maths/randomization/rndPolynom.js +0 -75
- package/esm/maths/randomization/rndPolynom.js.map +0 -1
- package/esm/maths/randomization/rndTypes.js +0 -3
- package/esm/maths/randomization/rndTypes.js.map +0 -1
- package/esm/maths/shutingyard.js +0 -443
- package/esm/maths/shutingyard.js.map +0 -1
- package/public/demo.css +0 -3
- package/public/index.html +0 -283
- package/public/matrices.html +0 -100
- package/public/playground.html +0 -168
- package/src/index.ts +0 -42
- package/src/maths/algebra/equation.ts +0 -897
- package/src/maths/algebra/linearSystem.ts +0 -370
- package/src/maths/algebra/logicalset.ts +0 -183
- package/src/maths/algebra/monom.ts +0 -1028
- package/src/maths/algebra/polynom.ts +0 -1537
- package/src/maths/algebra/rational.ts +0 -240
- package/src/maths/algebra/study/rationalStudy.ts +0 -287
- package/src/maths/algebra/study.ts +0 -506
- package/src/maths/coefficients/fraction.ts +0 -593
- package/src/maths/coefficients/nthRoot.ts +0 -148
- package/src/maths/geometry/circle.ts +0 -382
- package/src/maths/geometry/line.ts +0 -604
- package/src/maths/geometry/point.ts +0 -215
- package/src/maths/geometry/triangle.ts +0 -368
- package/src/maths/geometry/vector.ts +0 -242
- package/src/maths/numeric.ts +0 -162
- package/src/maths/numexp.ts +0 -184
- package/src/maths/randomization/random.ts +0 -80
- package/src/maths/randomization/randomCore.ts +0 -19
- package/src/maths/randomization/rndFraction.ts +0 -47
- package/src/maths/randomization/rndGeometryCircle.ts +0 -50
- package/src/maths/randomization/rndGeometryLine.ts +0 -53
- package/src/maths/randomization/rndGeometryPoint.ts +0 -69
- package/src/maths/randomization/rndHelpers.ts +0 -107
- package/src/maths/randomization/rndMonom.ts +0 -57
- package/src/maths/randomization/rndPolynom.ts +0 -90
- package/src/maths/randomization/rndTypes.ts +0 -43
- package/src/maths/shutingyard.ts +0 -496
- package/tests/algebra/equation.test.ts +0 -64
- package/tests/algebra/linear.test.ts +0 -58
- package/tests/algebra/monom.test.ts +0 -78
- package/tests/algebra/polynom.test.ts +0 -343
- package/tests/algebra/rationnal.test.ts +0 -64
- package/tests/algebra/study.test.ts +0 -48
- package/tests/coefficients/fraction.test.ts +0 -131
- package/tests/custom.test.ts +0 -33
- package/tests/geometry/circle.test.ts +0 -404
- package/tests/geometry/line.test.ts +0 -36
- package/tests/numeric.test.ts +0 -43
- package/tests/numexp.test.ts +0 -89
- package/tests/shutingyard.test.ts +0 -58
- package/tsconfig.json +0 -41
- package/tsconfig.testing.json +0 -28
- package/typedoc.katex.js +0 -11
- package/webpack-production-min.config.js +0 -26
- package/webpack-production.config.js +0 -26
- package/webpack.config.js +0 -26
- package/{esm → dist}/maths/algebra/logicalset.d.ts +6 -6
- package/{esm → dist}/maths/coefficients/fraction.d.ts +0 -0
- package/{esm → dist}/maths/coefficients/nthRoot.d.ts +0 -0
- package/{esm → dist}/maths/numeric.d.ts +0 -0
- package/{esm → dist}/maths/numexp.d.ts +3 -3
- /package/{esm → dist}/maths/randomization/randomCore.d.ts +0 -0
- /package/{esm → dist}/maths/randomization/rndHelpers.d.ts +0 -0
- /package/{esm → dist}/maths/shutingyard.d.ts +0 -0
|
@@ -1,1537 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Polynom module contains everything necessary to handle polynoms.*
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {literalType, Monom} from './monom';
|
|
6
|
-
import {Shutingyard, ShutingyardType, Token} from '../shutingyard';
|
|
7
|
-
import {Numeric} from '../numeric';
|
|
8
|
-
import {Fraction} from "../coefficients/fraction";
|
|
9
|
-
import {Equation, ISolution} from "./equation";
|
|
10
|
-
|
|
11
|
-
export type PolynomParsingType = string | Polynom | number | Fraction | Monom
|
|
12
|
-
|
|
13
|
-
export interface IEuclidian {
|
|
14
|
-
quotient: Polynom,
|
|
15
|
-
reminder: Polynom
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Polynom class can handle polynoms, reorder, resolve, ...
|
|
20
|
-
* ```
|
|
21
|
-
* let P = new Polynom('3x-4')
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export class Polynom {
|
|
25
|
-
private _rawString: string;
|
|
26
|
-
private _dirty_factors: boolean
|
|
27
|
-
private _dirty_zeroes: boolean
|
|
28
|
-
private _euclidianCache: { [Key: string]: IEuclidian }
|
|
29
|
-
private _factors: Polynom[];
|
|
30
|
-
private _monoms: Monom[];
|
|
31
|
-
private _texString: string;
|
|
32
|
-
private _zeroes: ISolution[]
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* @param {string} polynomString (optional) Default polynom to parse on class creation
|
|
37
|
-
* @param values
|
|
38
|
-
*/
|
|
39
|
-
constructor(polynomString?: PolynomParsingType, ...values: unknown[]) {
|
|
40
|
-
this._monoms = [];
|
|
41
|
-
this._factors = [];
|
|
42
|
-
this.mark_as_dirty()
|
|
43
|
-
|
|
44
|
-
if (polynomString !== undefined) {
|
|
45
|
-
this.parse(polynomString, ...values);
|
|
46
|
-
}
|
|
47
|
-
return this;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ------------------------------------------
|
|
51
|
-
get dirty_factors(): boolean {
|
|
52
|
-
return this._dirty_factors;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
set dirty_factors(value: boolean) {
|
|
56
|
-
this._dirty_factors = value;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
get dirty_zeroes(): boolean {
|
|
60
|
-
return this._dirty_zeroes;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
set dirty_zeroes(value: boolean) {
|
|
64
|
-
this._dirty_zeroes = value;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
get euclidianCache(): { [p: string]: IEuclidian } {
|
|
68
|
-
return this._euclidianCache;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
set euclidianCache(value: { [p: string]: IEuclidian }) {
|
|
72
|
-
this._euclidianCache = value;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get factors(): Polynom[] {
|
|
76
|
-
return this.factorize()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
set factors(value: Polynom[]) {
|
|
80
|
-
this.mark_as_dirty()
|
|
81
|
-
this._factors = value;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ------------------------------------------
|
|
85
|
-
get monoms() {
|
|
86
|
-
return this._monoms;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
set monoms(M: Monom[]) {
|
|
90
|
-
this._monoms = M;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
get texString(): string {
|
|
94
|
-
return this._texString;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
get zeroes(): ISolution[] {
|
|
98
|
-
return this.getZeroes()
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
get texFactors(): string {
|
|
102
|
-
this.factorize()
|
|
103
|
-
|
|
104
|
-
if (this.factors.length <= 1) {
|
|
105
|
-
return this.tex
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Build an array of texFactors with the number of similar items.
|
|
109
|
-
let factorsCount: { [Key: string]: { degree: number, factor: Polynom } } = {}
|
|
110
|
-
for (let f of this.factors) {
|
|
111
|
-
if (factorsCount[f.tex] !== undefined) {
|
|
112
|
-
factorsCount[f.tex].degree++
|
|
113
|
-
} else {
|
|
114
|
-
factorsCount[f.tex] = {
|
|
115
|
-
degree: 1,
|
|
116
|
-
factor: f
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// First round to put the 'monom' first
|
|
122
|
-
let simpleFactor = new Polynom().one()
|
|
123
|
-
|
|
124
|
-
for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length === 1)) {
|
|
125
|
-
simpleFactor.multiply(item.factor)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let tex = simpleFactor.isOne() ? '' : simpleFactor.tex
|
|
129
|
-
|
|
130
|
-
// Loop through all factors that contains at least 2 monoms.
|
|
131
|
-
for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length > 1)) {
|
|
132
|
-
if (item.factor.length > 1) {
|
|
133
|
-
tex += `\\left( ${item.factor.tex} \\right)${item.degree > 1 ? '^{ ' + item.degree + ' }' : ''}`
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return tex;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
get displayFactors() {
|
|
141
|
-
this.factorize()
|
|
142
|
-
|
|
143
|
-
if (this.factors.length <= 1) {
|
|
144
|
-
return this.display
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Build an array of texFactors with the number of similar items.
|
|
148
|
-
let factorsCount: { [Key: string]: { degree: number, factor: Polynom } } = {}
|
|
149
|
-
for (let f of this.factors) {
|
|
150
|
-
if (factorsCount[f.display] !== undefined) {
|
|
151
|
-
factorsCount[f.display].degree++
|
|
152
|
-
} else {
|
|
153
|
-
factorsCount[f.display] = {
|
|
154
|
-
degree: 1,
|
|
155
|
-
factor: f
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// First round to put the 'monom' first
|
|
161
|
-
let simpleFactor = new Polynom().one()
|
|
162
|
-
|
|
163
|
-
for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length === 1)) {
|
|
164
|
-
simpleFactor.multiply(item.factor)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
let display = simpleFactor.isOne() ? '' : simpleFactor.display
|
|
168
|
-
|
|
169
|
-
// Loop through all factors that contains at least 2 monoms.
|
|
170
|
-
for (let item of Object.values(factorsCount).filter(item => item.factor.monoms.length > 1)) {
|
|
171
|
-
if (item.factor.length > 1) {
|
|
172
|
-
display += `(${item.factor.display})${item.degree > 1 ? '^(' + item.degree + ')' : ''}`
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return display;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
get length() {
|
|
180
|
-
// TODO: Must reduce the monoms list to remove the zero coefficient.
|
|
181
|
-
return this._monoms.length;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
get display(): string {
|
|
185
|
-
return this.genDisplay();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
get raw(): string {
|
|
189
|
-
return this._rawString
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
get tex(): string {
|
|
193
|
-
return this.genDisplay('tex');
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
get isMultiVariable(): boolean {
|
|
197
|
-
const B = false;
|
|
198
|
-
for (const m of this._monoms) {
|
|
199
|
-
if (m.variables.length > 1) {
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return B;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
get variables(): string[] {
|
|
207
|
-
let V: string[] = [];
|
|
208
|
-
|
|
209
|
-
for (const m of this._monoms) {
|
|
210
|
-
V = V.concat(m.variables);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Remove duplicates.
|
|
214
|
-
V = [...new Set(V)];
|
|
215
|
-
V.sort()
|
|
216
|
-
return V;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
get numberOfVars(): number {
|
|
220
|
-
return this.variables.length;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
get plotFunction(): string {
|
|
224
|
-
return this.genDisplay('tex', false, false, true)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
mark_as_dirty = (): void => {
|
|
228
|
-
this.dirty_factors = true
|
|
229
|
-
this.dirty_zeroes = true
|
|
230
|
-
this.euclidianCache = {}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
addToken = (stack: Polynom[], element: Token): void => {
|
|
234
|
-
switch (element.tokenType) {
|
|
235
|
-
case ShutingyardType.COEFFICIENT:
|
|
236
|
-
stack.push(new Polynom(element.token))
|
|
237
|
-
break
|
|
238
|
-
|
|
239
|
-
case ShutingyardType.VARIABLE:
|
|
240
|
-
stack.push(new Polynom().add(new Monom(element.token)))
|
|
241
|
-
break
|
|
242
|
-
|
|
243
|
-
case ShutingyardType.CONSTANT:
|
|
244
|
-
// TODO: add constant support to Polynom parsing.
|
|
245
|
-
console.log('Actually, not supported - will be added later !')
|
|
246
|
-
break
|
|
247
|
-
|
|
248
|
-
case ShutingyardType.OPERATION:
|
|
249
|
-
if (stack.length >= 2) {
|
|
250
|
-
const b = stack.pop(),
|
|
251
|
-
a = stack.pop()
|
|
252
|
-
|
|
253
|
-
if (element.token === '+') {
|
|
254
|
-
stack.push(a.add(b))
|
|
255
|
-
} else if (element.token === '-') {
|
|
256
|
-
stack.push(a.subtract(b))
|
|
257
|
-
} else if (element.token === '*') {
|
|
258
|
-
stack.push(a.multiply(b))
|
|
259
|
-
} else if (element.token === '/') {
|
|
260
|
-
if (b.degree().isStrictlyPositive()) {
|
|
261
|
-
console.log('divide by a polynom -> should create a rational polynom !')
|
|
262
|
-
} else {
|
|
263
|
-
stack.push(a.divide(b.monoms[0].coefficient))
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
} else if (element.token === '^') {
|
|
267
|
-
if (b.degree().isStrictlyPositive()) {
|
|
268
|
-
console.error('Cannot elevate a polynom with another polynom !', a.tex, b.tex)
|
|
269
|
-
} else {
|
|
270
|
-
if (b.monoms[0].coefficient.isRelative()) {
|
|
271
|
-
// Integer power
|
|
272
|
-
stack.push(a.pow(b.monoms[0].coefficient.value))
|
|
273
|
-
} else {
|
|
274
|
-
// Only allow power if the previous polynom is only a monom, without coefficient.
|
|
275
|
-
if (a.monoms.length === 1 && a.monoms[0].coefficient.isOne()) {
|
|
276
|
-
for (let letter in a.monoms[0].literal) {
|
|
277
|
-
a.monoms[0].literal[letter].multiply(b.monoms[0].coefficient)
|
|
278
|
-
}
|
|
279
|
-
stack.push(a)
|
|
280
|
-
} else {
|
|
281
|
-
console.error('Cannot have power with fraction')
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
if (element.token === '-') {
|
|
288
|
-
stack.push(stack.pop().opposed())
|
|
289
|
-
} else {
|
|
290
|
-
throw "Error parsing the polynom " + this._rawString
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
break
|
|
294
|
-
|
|
295
|
-
case ShutingyardType.MONOM:
|
|
296
|
-
// Should never appear.
|
|
297
|
-
console.error('The monom token should not appear here')
|
|
298
|
-
break;
|
|
299
|
-
|
|
300
|
-
case ShutingyardType.FUNCTION:
|
|
301
|
-
// Should never appear.
|
|
302
|
-
console.error('The function token should not appear here - might be introduced later.')
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
// ------------------------------------------
|
|
309
|
-
// Creation / parsing functions
|
|
310
|
-
|
|
311
|
-
// ------------------------------------------
|
|
312
|
-
/**
|
|
313
|
-
* Parse a string to a polynom.
|
|
314
|
-
* @param inputStr
|
|
315
|
-
* @param values: as string, numbers or fractions
|
|
316
|
-
*/
|
|
317
|
-
parse = (inputStr: PolynomParsingType, ...values: unknown[]): Polynom => {
|
|
318
|
-
// Reset the main variables.
|
|
319
|
-
this._monoms = []
|
|
320
|
-
this._factors = []
|
|
321
|
-
this.mark_as_dirty()
|
|
322
|
-
|
|
323
|
-
// TODO: allow to enter a liste of Fraction (a, b, c, ...) to make a polynom ax^n + bx^(n-1) + cx^(n-2) + ...
|
|
324
|
-
if (typeof inputStr === 'string') {
|
|
325
|
-
return this._parseString(inputStr, ...values)
|
|
326
|
-
} else if (
|
|
327
|
-
(typeof inputStr === 'number' || inputStr instanceof Fraction || inputStr instanceof Monom)
|
|
328
|
-
&& (values === undefined || values.length === 0)
|
|
329
|
-
) {
|
|
330
|
-
this._monoms.push(new Monom(inputStr))
|
|
331
|
-
} else if (inputStr instanceof Monom && values.length > 0) {
|
|
332
|
-
this._monoms.push(new Monom(inputStr))
|
|
333
|
-
values.forEach(m => {
|
|
334
|
-
this._monoms.push(new Monom(m))
|
|
335
|
-
})
|
|
336
|
-
} else if (inputStr instanceof Polynom) {
|
|
337
|
-
for (const m of inputStr.monoms) {
|
|
338
|
-
this._monoms.push(m.clone())
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
return this
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Clone the polynom
|
|
347
|
-
*/
|
|
348
|
-
clone = (): Polynom => {
|
|
349
|
-
const P = new Polynom();
|
|
350
|
-
const M: Monom[] = [];
|
|
351
|
-
|
|
352
|
-
for (const m of this._monoms) {
|
|
353
|
-
M.push(m.clone());
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
P.monoms = M;
|
|
357
|
-
|
|
358
|
-
return P;
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Set the polynom to zero.
|
|
363
|
-
* @returns {this}
|
|
364
|
-
*/
|
|
365
|
-
zero = (): Polynom => {
|
|
366
|
-
this._monoms = [];
|
|
367
|
-
this._monoms.push(new Monom().zero());
|
|
368
|
-
this._rawString = '0';
|
|
369
|
-
this.mark_as_dirty()
|
|
370
|
-
return this;
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
one = (): Polynom => {
|
|
374
|
-
this._monoms = [];
|
|
375
|
-
this._monoms.push(new Monom().one());
|
|
376
|
-
this._rawString = '1';
|
|
377
|
-
this.mark_as_dirty()
|
|
378
|
-
return this;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
empty = (): Polynom => {
|
|
382
|
-
this._monoms = [];
|
|
383
|
-
this._rawString = '';
|
|
384
|
-
this.mark_as_dirty()
|
|
385
|
-
return this;
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
// ------------------------------------------
|
|
389
|
-
opposed = (): Polynom => {
|
|
390
|
-
this._monoms = this._monoms.map(m => m.opposed());
|
|
391
|
-
this.mark_as_dirty()
|
|
392
|
-
return this;
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
// ------------------------------------------
|
|
397
|
-
// Mathematical operations
|
|
398
|
-
|
|
399
|
-
add = (...values: unknown[]): Polynom => {
|
|
400
|
-
this.mark_as_dirty()
|
|
401
|
-
|
|
402
|
-
// @ts-ignore
|
|
403
|
-
for (let value of values) {
|
|
404
|
-
if (value instanceof Polynom) {
|
|
405
|
-
this._monoms = this._monoms.concat(value.monoms);
|
|
406
|
-
} else if (value instanceof Monom) {
|
|
407
|
-
this._monoms.push(value.clone());
|
|
408
|
-
} else if (Number.isSafeInteger(value)) {
|
|
409
|
-
this._monoms.push(new Monom(value.toString()));
|
|
410
|
-
} else {
|
|
411
|
-
this._monoms.push(new Monom(value));
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
return this.reduce();
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
subtract = (...values: unknown[]): Polynom => {
|
|
419
|
-
this.mark_as_dirty()
|
|
420
|
-
|
|
421
|
-
for (let value of values) {
|
|
422
|
-
if (value instanceof Polynom) {
|
|
423
|
-
this._monoms = this._monoms.concat(value.clone().opposed().monoms);
|
|
424
|
-
} else if (value instanceof Monom) {
|
|
425
|
-
this._monoms.push(value.clone().opposed());
|
|
426
|
-
} else if (Number.isSafeInteger(value)) {
|
|
427
|
-
this._monoms.push(new Monom(value.toString()).opposed());
|
|
428
|
-
} else {
|
|
429
|
-
this._monoms.push(new Monom(value).opposed());
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
return this.reduce();
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
multiply = (value: unknown): Polynom => {
|
|
437
|
-
this.mark_as_dirty()
|
|
438
|
-
|
|
439
|
-
if (value instanceof Polynom) {
|
|
440
|
-
return this.multiplyByPolynom(value)
|
|
441
|
-
} else if (value instanceof Fraction) {
|
|
442
|
-
return this.multiplyByFraction(value);
|
|
443
|
-
} else if (value instanceof Monom) {
|
|
444
|
-
return this.multiplyByMonom(value);
|
|
445
|
-
} else if (Number.isSafeInteger(value) && typeof value === 'number') {
|
|
446
|
-
return this.multiplyByInteger(value);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// Something went wrong...
|
|
450
|
-
return this;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Divide the current polynom by another polynom.
|
|
455
|
-
* @param P
|
|
456
|
-
* returns {quotient: Polynom, reminder: Polynom}
|
|
457
|
-
*/
|
|
458
|
-
euclidian = (P: Polynom): IEuclidian => {
|
|
459
|
-
|
|
460
|
-
if (this.euclidianCache[P.tex] !== undefined) {
|
|
461
|
-
return this.euclidianCache[P.tex]
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
const letter: string = P.variables[0];
|
|
465
|
-
const quotient: Polynom = new Polynom().zero();
|
|
466
|
-
const reminder: Polynom = this.clone().reorder(letter);
|
|
467
|
-
|
|
468
|
-
// There is no variable - means it's a number
|
|
469
|
-
if (P.variables.length === 0) {
|
|
470
|
-
let q = this.clone().divide(P)
|
|
471
|
-
return {
|
|
472
|
-
quotient: this.clone().divide(P).reduce(),
|
|
473
|
-
reminder: new Polynom().zero()
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// Get at least a letter
|
|
478
|
-
const maxMP: Monom = P.monomByDegree(undefined, letter);
|
|
479
|
-
const degreeP: Fraction = P.degree(letter);
|
|
480
|
-
|
|
481
|
-
let newM: Monom;
|
|
482
|
-
|
|
483
|
-
// Make the euclidian division of the two polynoms.
|
|
484
|
-
let MaxIteration = this.degree(letter).value * 2;
|
|
485
|
-
while (reminder.degree(letter).geq(degreeP) && MaxIteration > 0) {
|
|
486
|
-
MaxIteration--
|
|
487
|
-
|
|
488
|
-
// Get the greatest monom divided by the max monom of the divider
|
|
489
|
-
newM = reminder.monomByDegree(undefined, letter).clone().divide(maxMP);
|
|
490
|
-
|
|
491
|
-
if (newM.isZero()) continue;
|
|
492
|
-
|
|
493
|
-
// Get the new quotient and reminder.
|
|
494
|
-
quotient.add(newM);
|
|
495
|
-
reminder.subtract(P.clone().multiply(newM)).reduce();
|
|
496
|
-
|
|
497
|
-
// Check if the reminder is zero.
|
|
498
|
-
if (newM.degree(letter).isZero()) break
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
quotient.reduce()
|
|
502
|
-
reminder.reduce()
|
|
503
|
-
return {quotient, reminder};
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
divide = (value: unknown): Polynom => {
|
|
507
|
-
this.mark_as_dirty()
|
|
508
|
-
|
|
509
|
-
if (value instanceof Fraction) {
|
|
510
|
-
return this.divideByFraction(value);
|
|
511
|
-
} else if (typeof value === 'number' && Number.isSafeInteger(value)) {
|
|
512
|
-
return this.divideByInteger(value);
|
|
513
|
-
} else if (value instanceof Monom) {
|
|
514
|
-
return this.divide(new Polynom(value))
|
|
515
|
-
} else if (value instanceof Polynom) {
|
|
516
|
-
if (value.monoms.length === 1 && value.variables.length === 0) {
|
|
517
|
-
return this.divideByFraction(value.monoms[0].coefficient)
|
|
518
|
-
} else {
|
|
519
|
-
let {quotient, reminder} = this.euclidian(value)
|
|
520
|
-
if (reminder.isZero()) {
|
|
521
|
-
return quotient
|
|
522
|
-
} else {
|
|
523
|
-
console.log(`${this.tex} is not divideable by ${value.tex}`)
|
|
524
|
-
return new Polynom().zero()
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
pow = (nb: number): Polynom => {
|
|
531
|
-
this.mark_as_dirty()
|
|
532
|
-
|
|
533
|
-
if (!Number.isSafeInteger(nb)) {
|
|
534
|
-
return this.zero();
|
|
535
|
-
}
|
|
536
|
-
if (nb < 0) {
|
|
537
|
-
return this.zero();
|
|
538
|
-
}
|
|
539
|
-
if (nb === 0) {
|
|
540
|
-
return new Polynom();
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
const P = this.clone();
|
|
544
|
-
for (let i = 1; i < nb; i++) {
|
|
545
|
-
this.multiply(P);
|
|
546
|
-
}
|
|
547
|
-
return this.reduce();
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
// ------------------------------------------
|
|
551
|
-
/**
|
|
552
|
-
* Compare the current coefficient with another coefficient
|
|
553
|
-
* @param P
|
|
554
|
-
* @param sign (string| default is =): authorized values: =, <, <=, >, >= with some variations.
|
|
555
|
-
*/
|
|
556
|
-
compare = (P: Polynom, sign?: string): boolean => {
|
|
557
|
-
if (sign === undefined) {
|
|
558
|
-
sign = '='
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Create clone version to reduce them without altering the original polynoms.
|
|
562
|
-
const cP1 = this.clone().reduce().reorder();
|
|
563
|
-
const cP2 = P.clone().reduce().reorder();
|
|
564
|
-
|
|
565
|
-
switch (sign) {
|
|
566
|
-
case '=':
|
|
567
|
-
// They must have the isSame length and the isSame degree
|
|
568
|
-
if (cP1.length !== cP2.length || cP1.degree().isNotEqual(cP2.degree())) {
|
|
569
|
-
return false;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
// Check if the coefficients are the isSame.
|
|
573
|
-
for (const i in cP1.monoms) {
|
|
574
|
-
if (!cP1.monoms[i].isEqual(cP2.monoms[i])) {
|
|
575
|
-
return false;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
return true;
|
|
579
|
-
case 'same':
|
|
580
|
-
// They must have the isSame length and the isSame degree
|
|
581
|
-
if (cP1.length !== cP2.length || cP1.degree() !== cP2.degree()) {
|
|
582
|
-
return false;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
for (const i in cP1.monoms) {
|
|
586
|
-
if (!cP1.monoms[i].isSameAs(cP2.monoms[i])) {
|
|
587
|
-
return false;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
return true;
|
|
592
|
-
default:
|
|
593
|
-
return false;
|
|
594
|
-
}
|
|
595
|
-
};
|
|
596
|
-
|
|
597
|
-
isZero(): boolean {
|
|
598
|
-
return (this._monoms.length === 1 && this._monoms[0].coefficient.isZero()) || this._monoms.length === 0;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
isOne(): boolean {
|
|
602
|
-
return this._monoms.length === 1 && this._monoms[0].coefficient.isOne();
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
isEqual = (P: Polynom): boolean => {
|
|
606
|
-
return this.compare(P, '=');
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
isSameAs = (P: Polynom): boolean => {
|
|
610
|
-
return this.compare(P, 'same');
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
isOpposedAt = (P: Polynom): boolean => {
|
|
614
|
-
return this.compare(P.clone().opposed(), '=');
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
isFactorized = (polynomString: string, soft?: boolean): boolean => {
|
|
618
|
-
let P;
|
|
619
|
-
|
|
620
|
-
// Check if polynom is complete...
|
|
621
|
-
if (polynomString.split('(').length !== polynomString.split(')').length) {
|
|
622
|
-
return false
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
// Try to build the polynom
|
|
626
|
-
try {
|
|
627
|
-
P = new Polynom(polynomString);
|
|
628
|
-
} catch (e) {
|
|
629
|
-
return false;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
// Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
|
|
633
|
-
if (!this.isEqual(P)) {
|
|
634
|
-
return false;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// Check if the provided (string) version is fully factorized.
|
|
638
|
-
// Run a regex on the string.
|
|
639
|
-
let polynomStringNormalized = polynomString.replaceAll('*', ''),
|
|
640
|
-
polynomStringReduced = '' + polynomStringNormalized,
|
|
641
|
-
factors: string[] = [];
|
|
642
|
-
|
|
643
|
-
for (let x of polynomStringNormalized.matchAll(/\(([a-z0-9+\-]+)\)(\^[0-9]*)?/g)) {
|
|
644
|
-
|
|
645
|
-
if (x[2] !== undefined) {
|
|
646
|
-
// if there is an exponential value, add it multiple times
|
|
647
|
-
for (let i = 0; i < +x[2].substring(1); i++) {
|
|
648
|
-
factors.push(x[1])
|
|
649
|
-
}
|
|
650
|
-
} else {
|
|
651
|
-
// no power - add it once.
|
|
652
|
-
factors.push(x[1]);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
// Remove the current polynom
|
|
656
|
-
polynomStringReduced = polynomStringReduced.replaceAll(x[0], '');
|
|
657
|
-
}
|
|
658
|
-
if (polynomStringReduced !== '') {
|
|
659
|
-
factors.push(polynomStringReduced);
|
|
660
|
-
}
|
|
661
|
-
let polyFactors = factors.map(x => new Polynom(x));
|
|
662
|
-
|
|
663
|
-
// polyFactors contain all polynoms.
|
|
664
|
-
let checkPolyFactors = polyFactors.filter(x => x.degree().geq(1) && !x.commonMonom().isOne())
|
|
665
|
-
|
|
666
|
-
// Some polynoms are not completely factorized.
|
|
667
|
-
if (checkPolyFactors.length > 0 && !soft) {
|
|
668
|
-
return false
|
|
669
|
-
}
|
|
670
|
-
if (checkPolyFactors.length > 0 && soft) {
|
|
671
|
-
polyFactors = polyFactors.filter(x => x.commonMonom().isOne())
|
|
672
|
-
|
|
673
|
-
let FactorizedConstant = new Fraction().one()
|
|
674
|
-
for (let p of checkPolyFactors) {
|
|
675
|
-
let k = p.commonMonom(),
|
|
676
|
-
pFactor = p.clone().divide(k)
|
|
677
|
-
|
|
678
|
-
if (k.degree().isZero()) {
|
|
679
|
-
FactorizedConstant.multiply(k.coefficient)
|
|
680
|
-
polyFactors.push(pFactor.clone())
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
// Factorize the current polynom.
|
|
687
|
-
this.factorize();
|
|
688
|
-
|
|
689
|
-
// Compare the given factors with the generated factors
|
|
690
|
-
let sign = 1,
|
|
691
|
-
notFoundedFactors = []
|
|
692
|
-
for (let f of this.factors) {
|
|
693
|
-
// The factor is just a coefficient. Might be opposed
|
|
694
|
-
if (f.degree().isZero()) {
|
|
695
|
-
if (f.monoms[0].coefficient.isNegativeOne()) {
|
|
696
|
-
sign = -sign
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
let factorFound = false
|
|
701
|
-
for (let i = 0; i < polyFactors.length; i++) {
|
|
702
|
-
if (f.isEqual(polyFactors[i])) {
|
|
703
|
-
polyFactors.splice(i, 1);
|
|
704
|
-
factorFound = true
|
|
705
|
-
break;
|
|
706
|
-
} else if (f.isOpposedAt(polyFactors[i])) {
|
|
707
|
-
polyFactors.splice(i, 1);
|
|
708
|
-
sign = -sign;
|
|
709
|
-
factorFound = true
|
|
710
|
-
break;
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
if (!factorFound) {
|
|
715
|
-
notFoundedFactors.push(f.clone())
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
// The polyfactors must be empty and the cumulative opposite factors must be 1.
|
|
720
|
-
return (polyFactors.length === 0 && sign === 1);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
// ------------------------------------------
|
|
725
|
-
// Compare functions
|
|
726
|
-
|
|
727
|
-
isReduced = (polynomString: string): Boolean => {
|
|
728
|
-
// The polynom must be developed to be reduced.
|
|
729
|
-
if (!this.isDeveloped(polynomString)) {
|
|
730
|
-
return false
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
let P = new Polynom(polynomString)
|
|
734
|
-
if (P.monoms.length > this.monoms.length) {
|
|
735
|
-
return false
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// TODO: Not ur the reduced systme checking is working properly !
|
|
739
|
-
for (let m of P.monoms) {
|
|
740
|
-
if (!m.coefficient.isReduced()) {
|
|
741
|
-
return false
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
return false
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
isDeveloped = (polynomString: string): Boolean => {
|
|
749
|
-
let P: Polynom;
|
|
750
|
-
|
|
751
|
-
// Start by removing the parenthis after a "power"
|
|
752
|
-
let pString = polynomString.replaceAll(/\^\(([-0-9/]+)\)/g, '$1')
|
|
753
|
-
|
|
754
|
-
// There is at least one parenthese - it is not developed.
|
|
755
|
-
if (pString.includes('(') || pString.includes(')')) {
|
|
756
|
-
return false
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
// Try to build the polynom
|
|
760
|
-
try {
|
|
761
|
-
// Build the polynom
|
|
762
|
-
P = new Polynom(polynomString);
|
|
763
|
-
} catch (e) {
|
|
764
|
-
return false;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
// Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
|
|
768
|
-
if (!this.isEqual(P)) {
|
|
769
|
-
return false;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// Check that everything is completely developed. Actually, there are no parentheses... so it is fully developed
|
|
773
|
-
return true
|
|
774
|
-
|
|
775
|
-
// // maybe it wasn't reduced and not ordered...
|
|
776
|
-
// // compare polynom string.
|
|
777
|
-
//
|
|
778
|
-
// // normalize the string
|
|
779
|
-
// let polynomStringNormalized = polynomString.replaceAll('[*\s]', '')
|
|
780
|
-
//
|
|
781
|
-
// // Determine if it's the exact same string.
|
|
782
|
-
// // TODO: Maybe it's enough to just make this test !a
|
|
783
|
-
// return polynomStringNormalized === P.reduce().reorder().display
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
// -------------------------------------
|
|
787
|
-
reduce = (): Polynom => {
|
|
788
|
-
// Reduce the polynom
|
|
789
|
-
let values = this._monoms.map(x => x.clone()),
|
|
790
|
-
vars = [...this.variables]
|
|
791
|
-
|
|
792
|
-
// Group the monoms by similarity
|
|
793
|
-
let i = 0
|
|
794
|
-
while (i < this._monoms.length) {
|
|
795
|
-
for (let j = i + 1; j < this._monoms.length; j++) {
|
|
796
|
-
if (this._monoms[i].isSameAs(this._monoms[j])) {
|
|
797
|
-
this._monoms[i].add(this._monoms[j])
|
|
798
|
-
this._monoms.splice(j, 1)
|
|
799
|
-
if (this._monoms[i].isZero()) {
|
|
800
|
-
this._monoms[i] = new Monom().zero()
|
|
801
|
-
}
|
|
802
|
-
j--
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
i++
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
//
|
|
809
|
-
//
|
|
810
|
-
//
|
|
811
|
-
// let coeffs = values.filter(x => x.variables.length === 0)
|
|
812
|
-
//
|
|
813
|
-
// if (coeffs.length > 0) {
|
|
814
|
-
// this._monoms.push(coeffs.reduce((a, b) => a.add(b)))
|
|
815
|
-
// }
|
|
816
|
-
//
|
|
817
|
-
// // Build the new monoms
|
|
818
|
-
// for (let letter of vars) {
|
|
819
|
-
// // Monom with same letters, but might be of different degrees
|
|
820
|
-
// let M = values.filter(x => x.hasLetter(letter))
|
|
821
|
-
//
|
|
822
|
-
// while (M.length > 0) {
|
|
823
|
-
// // Take the first element
|
|
824
|
-
// const m = M.shift(), degree = m.degree(letter)
|
|
825
|
-
//
|
|
826
|
-
// for (let a of M.filter(x => x.degree(letter).isEqual(degree))) {
|
|
827
|
-
// m.add(a)
|
|
828
|
-
// }
|
|
829
|
-
//
|
|
830
|
-
// this._monoms.push(m)
|
|
831
|
-
//
|
|
832
|
-
// // Make the new array.
|
|
833
|
-
// M = M.filter(x => x.degree(letter).isNotEqual(degree))
|
|
834
|
-
// }
|
|
835
|
-
// // reduce the monom
|
|
836
|
-
//
|
|
837
|
-
// }
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
// Remove all null monoms
|
|
841
|
-
this._monoms = this._monoms.filter((m) => {
|
|
842
|
-
return m.coefficient.value !== 0
|
|
843
|
-
});
|
|
844
|
-
|
|
845
|
-
// Reduce all monoms coefficient.
|
|
846
|
-
for (const m of this._monoms) {
|
|
847
|
-
m.coefficient.reduce();
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
if (this.length === 0) {
|
|
851
|
-
return new Polynom().zero();
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
return this.reorder();
|
|
855
|
-
};
|
|
856
|
-
|
|
857
|
-
reorder = (letter: string = 'x', revert?: boolean): Polynom => {
|
|
858
|
-
if (revert === undefined) {
|
|
859
|
-
revert = false
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
// TODO: Must handle multiple setLetter reorder system
|
|
863
|
-
let otherLetters = this.variables.filter(x => x !== letter)
|
|
864
|
-
this._monoms.sort(function (a, b) {
|
|
865
|
-
let da = a.degree(letter).value,
|
|
866
|
-
db = b.degree(letter).value
|
|
867
|
-
|
|
868
|
-
// Values are different
|
|
869
|
-
if (da !== db) return revert ? da - db : db - da
|
|
870
|
-
|
|
871
|
-
// if values are equals, check other letters - it must be revert in that case !
|
|
872
|
-
if (otherLetters.length > 0) {
|
|
873
|
-
for (let L of otherLetters) {
|
|
874
|
-
let da = a.degree(L).value,
|
|
875
|
-
db = b.degree(L).value
|
|
876
|
-
|
|
877
|
-
// Values are different
|
|
878
|
-
if (da !== db) return revert ? da - db : db - da
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
return 0
|
|
883
|
-
// return b.degree(letter).clone().subtract(a.degree(letter)).value
|
|
884
|
-
});
|
|
885
|
-
|
|
886
|
-
return this;
|
|
887
|
-
};
|
|
888
|
-
|
|
889
|
-
degree = (letter?: string): Fraction => {
|
|
890
|
-
let d: Fraction = new Fraction().zero();
|
|
891
|
-
for (const m of this._monoms) {
|
|
892
|
-
d = Fraction.max(m.degree(letter).value, d);
|
|
893
|
-
}
|
|
894
|
-
return d;
|
|
895
|
-
};
|
|
896
|
-
|
|
897
|
-
letters = (): string[] => {
|
|
898
|
-
let L: string[] = [], S = new Set();
|
|
899
|
-
|
|
900
|
-
for (let m of this._monoms) {
|
|
901
|
-
S = new Set([...S, ...m.variables]);
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
// @ts-ignore
|
|
905
|
-
return [...S];
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
/**
|
|
909
|
-
* Replace a variable (letter) by a polynom.
|
|
910
|
-
* @param letter
|
|
911
|
-
* @param P
|
|
912
|
-
*/
|
|
913
|
-
replaceBy = (letter: string, P: Polynom): Polynom => {
|
|
914
|
-
this.mark_as_dirty()
|
|
915
|
-
|
|
916
|
-
let pow: Fraction;
|
|
917
|
-
const resultPolynom: Polynom = new Polynom().zero();
|
|
918
|
-
|
|
919
|
-
for (const m of this.monoms) {
|
|
920
|
-
if (m.literal[letter] === undefined || m.literal[letter].isZero()) {
|
|
921
|
-
resultPolynom.add(m.clone());
|
|
922
|
-
} else {
|
|
923
|
-
// We have found a setLetter.
|
|
924
|
-
// Get the power and reset it.
|
|
925
|
-
pow = m.literal[letter].clone();
|
|
926
|
-
delete m.literal[letter];
|
|
927
|
-
|
|
928
|
-
// TODO: replaceBy works only with positive and natural pow
|
|
929
|
-
resultPolynom.add(P.clone().pow(Math.abs(pow.numerator)).multiply(m));
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
this._monoms = resultPolynom.reduce().reorder().monoms;
|
|
934
|
-
return this;
|
|
935
|
-
};
|
|
936
|
-
|
|
937
|
-
// Evaluate a polynom.
|
|
938
|
-
evaluate = (values: literalType | Fraction | number): Fraction => {
|
|
939
|
-
const r = new Fraction().zero();
|
|
940
|
-
|
|
941
|
-
this._monoms.forEach(monom => {
|
|
942
|
-
//console.log('Evaluate polynom: ', monom.display, values, monom.evaluate(values).display);
|
|
943
|
-
r.add(monom.evaluate(values));
|
|
944
|
-
});
|
|
945
|
-
|
|
946
|
-
return r;
|
|
947
|
-
};
|
|
948
|
-
|
|
949
|
-
evaluateAsNumeric = (values: { [Key: string]: number } | number): number => {
|
|
950
|
-
let r = 0
|
|
951
|
-
this._monoms.forEach(monom => {
|
|
952
|
-
r += monom.evaluateAsNumeric(values)
|
|
953
|
-
})
|
|
954
|
-
|
|
955
|
-
return r
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
derivative = (letter?: string): Polynom => {
|
|
959
|
-
let dP = new Polynom();
|
|
960
|
-
|
|
961
|
-
for (let m of this._monoms) {
|
|
962
|
-
dP.add(m.derivative(letter));
|
|
963
|
-
}
|
|
964
|
-
return dP;
|
|
965
|
-
}
|
|
966
|
-
// ------------------------------------------
|
|
967
|
-
// Misc polynoms functions
|
|
968
|
-
|
|
969
|
-
primitive = (letter?: string): Polynom => {
|
|
970
|
-
let dP = new Polynom();
|
|
971
|
-
|
|
972
|
-
for (let m of this._monoms) {
|
|
973
|
-
dP.add(m.primitive(letter))
|
|
974
|
-
}
|
|
975
|
-
return dP
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
integrate = (a: Fraction | number, b: Fraction | number, letter?: string): Fraction => {
|
|
979
|
-
const primitive = this.primitive(letter)
|
|
980
|
-
|
|
981
|
-
if (letter === undefined) {
|
|
982
|
-
letter = 'x'
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
let valuesA: literalType = {},
|
|
986
|
-
valuesB: literalType = {}
|
|
987
|
-
valuesA[letter] = new Fraction(a);
|
|
988
|
-
valuesB[letter] = new Fraction(b);
|
|
989
|
-
|
|
990
|
-
return primitive.evaluate(valuesB).subtract(primitive.evaluate(valuesA))
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
// -------------------------------------
|
|
994
|
-
/**
|
|
995
|
-
* Factorize a polynom and store the best results in factors.
|
|
996
|
-
* @param maxValue Defines the greatest value to search to (default is 20).
|
|
997
|
-
*/
|
|
998
|
-
factorize = (letter?: string): Polynom[] => {
|
|
999
|
-
if (!this.dirty_factors) {
|
|
1000
|
-
return this._factors
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
let factors: Polynom[] = [];
|
|
1004
|
-
let P = this.clone().reorder()
|
|
1005
|
-
|
|
1006
|
-
// Extract the common monom
|
|
1007
|
-
// 2x^3+6x^2 => 2x^2
|
|
1008
|
-
let M = P.commonMonom()
|
|
1009
|
-
// If the polynom starts with a negative monom, factorize it.
|
|
1010
|
-
if (P.monomByDegree().coefficient.isStrictlyNegative() && M.coefficient.isStrictlyPositive() && !M.isOne()) {
|
|
1011
|
-
M.opposed()
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
if (!M.isOne()) {
|
|
1015
|
-
let tempPolynom: Polynom = new Polynom(M)
|
|
1016
|
-
factors = [tempPolynom.clone()]
|
|
1017
|
-
P = P.euclidian(tempPolynom).quotient;
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
// Main loop
|
|
1021
|
-
let securityLoop = P.degree().clone().multiply(2).value,
|
|
1022
|
-
maxDegree = 1
|
|
1023
|
-
while (securityLoop >= 0) {
|
|
1024
|
-
securityLoop--
|
|
1025
|
-
if (P.monoms.length < 2) {
|
|
1026
|
-
// The polynom has only one monom => 7x^2
|
|
1027
|
-
// No need to continue.
|
|
1028
|
-
if (!P.isOne()) {
|
|
1029
|
-
factors.push(P.clone())
|
|
1030
|
-
P.one()
|
|
1031
|
-
}
|
|
1032
|
-
break
|
|
1033
|
-
} else if (P.degree(letter).isOne()) {
|
|
1034
|
-
// The polynom is a first degree polynom => 3x-5
|
|
1035
|
-
// No need to continue
|
|
1036
|
-
factors.push(P.clone())
|
|
1037
|
-
P.one()
|
|
1038
|
-
break
|
|
1039
|
-
} else {
|
|
1040
|
-
// Create the list of all "potential" polynom dividers.
|
|
1041
|
-
let allDividers: Polynom[] = this._getAllPotentialFactors(P, maxDegree, letter)
|
|
1042
|
-
maxDegree = P.degree(letter).value
|
|
1043
|
-
|
|
1044
|
-
// Actually: 100ms
|
|
1045
|
-
while (allDividers.length > 0) {
|
|
1046
|
-
let div = allDividers[0]
|
|
1047
|
-
|
|
1048
|
-
if (!P.isDividableBy(div)) {
|
|
1049
|
-
// Not dividable. Remove it from the list
|
|
1050
|
-
allDividers.shift()
|
|
1051
|
-
} else {
|
|
1052
|
-
// It's dividable - so make the division
|
|
1053
|
-
let result = P.euclidian(div)
|
|
1054
|
-
|
|
1055
|
-
// Add the factor
|
|
1056
|
-
factors.push(div)
|
|
1057
|
-
|
|
1058
|
-
// As it's dividable, get the quotient.
|
|
1059
|
-
P = result.quotient.clone()
|
|
1060
|
-
|
|
1061
|
-
// filter all dividers that are no more suitable.
|
|
1062
|
-
allDividers = allDividers.filter(x => {
|
|
1063
|
-
let pX = P.monoms[0],
|
|
1064
|
-
pC = P.monoms[P.monoms.length - 1],
|
|
1065
|
-
dX = x.monoms[0],
|
|
1066
|
-
dC = x.monoms[x.monoms.length - 1]
|
|
1067
|
-
|
|
1068
|
-
// Check last item (degree zero)
|
|
1069
|
-
if (!pC.isDivisible(dC)) return false
|
|
1070
|
-
|
|
1071
|
-
// Check the first item (degree max)
|
|
1072
|
-
return pX.isDivisible(dX);
|
|
1073
|
-
})
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
// Maybe there is still something in the Polynom (not everything was possible to factorize)
|
|
1080
|
-
if (!P.isOne()) {
|
|
1081
|
-
factors.push(P.clone())
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
// Save the factors
|
|
1085
|
-
this._factors = factors
|
|
1086
|
-
|
|
1087
|
-
// The factors list is no more dirty
|
|
1088
|
-
this.dirty_factors = false
|
|
1089
|
-
|
|
1090
|
-
return this._factors;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
isDividableBy = (div: Polynom): boolean => {
|
|
1094
|
-
// Quick evaluation.
|
|
1095
|
-
if (div.degree().isOne()) {
|
|
1096
|
-
let zero = div.getZeroes()[0]
|
|
1097
|
-
|
|
1098
|
-
if (zero.exact instanceof Fraction) {
|
|
1099
|
-
return this.evaluate(zero.exact).isZero()
|
|
1100
|
-
} else {
|
|
1101
|
-
return false
|
|
1102
|
-
}
|
|
1103
|
-
} else {
|
|
1104
|
-
this.euclidianCache[div.tex] = this.euclidian(div)
|
|
1105
|
-
return this.euclidianCache[div.tex].reminder.isZero()
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
// TODO: get zeroes for more than first degree and for more than natural degrees
|
|
1109
|
-
getZeroes = (): ISolution[] => {
|
|
1110
|
-
if (this.dirty_zeroes) {
|
|
1111
|
-
let equ = new Equation(this.clone(), 0)
|
|
1112
|
-
equ.solve()
|
|
1113
|
-
this._zeroes = equ.solutions
|
|
1114
|
-
this.dirty_zeroes = false
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
return this._zeroes
|
|
1118
|
-
};
|
|
1119
|
-
|
|
1120
|
-
// TODO: analyse the next functions to determine if they are useful or not...
|
|
1121
|
-
monomByDegree = (degree?: Fraction | number, letter?: string): Monom => {
|
|
1122
|
-
if (degree === undefined) {
|
|
1123
|
-
// return the highest degree monom.
|
|
1124
|
-
return this.monomByDegree(this.degree(letter), letter);
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
// Reduce the polynom.
|
|
1128
|
-
const M = this.clone().reduce();
|
|
1129
|
-
for (const m of M._monoms) {
|
|
1130
|
-
if (m.degree(letter).isEqual(degree)) {
|
|
1131
|
-
return m.clone();
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
// Nothing was found - return the null monom.
|
|
1136
|
-
return new Monom().zero();
|
|
1137
|
-
};
|
|
1138
|
-
|
|
1139
|
-
monomsByDegree = (degree?: number | Fraction, letter?: string): Monom[] => {
|
|
1140
|
-
if (degree === undefined) {
|
|
1141
|
-
// return the highest degree monom.
|
|
1142
|
-
return this.monomsByDegree(this.degree(letter));
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
// Reduce the polynom.
|
|
1146
|
-
let Ms: Monom[] = [];
|
|
1147
|
-
|
|
1148
|
-
const M = this.clone().reduce();
|
|
1149
|
-
for (const m of M._monoms) {
|
|
1150
|
-
if (m.degree(letter) === degree) {
|
|
1151
|
-
Ms.push(m.clone())
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
return Ms
|
|
1156
|
-
// Nothing was found - retur
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
// Used in LinearSystem.tex
|
|
1160
|
-
monomByLetter = (letter: string): Monom => {
|
|
1161
|
-
const M = this.clone().reduce();
|
|
1162
|
-
for (const m of M._monoms) {
|
|
1163
|
-
if (m.hasLetter(letter)) {
|
|
1164
|
-
return m.clone();
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
return new Monom().zero();
|
|
1169
|
-
};
|
|
1170
|
-
|
|
1171
|
-
// Next functions are used for for commonMonom, which is used in the factorize method.
|
|
1172
|
-
getDenominators = (): number[] => {
|
|
1173
|
-
const denominators: number[] = [];
|
|
1174
|
-
for (const m of this._monoms) {
|
|
1175
|
-
denominators.push(m.coefficient.denominator);
|
|
1176
|
-
}
|
|
1177
|
-
return denominators;
|
|
1178
|
-
};
|
|
1179
|
-
|
|
1180
|
-
getNumerators = (): number[] => {
|
|
1181
|
-
const numerators: number[] = [];
|
|
1182
|
-
for (const m of this._monoms) {
|
|
1183
|
-
numerators.push(m.coefficient.numerator);
|
|
1184
|
-
}
|
|
1185
|
-
return numerators;
|
|
1186
|
-
};
|
|
1187
|
-
|
|
1188
|
-
lcmDenominator = (): number => {
|
|
1189
|
-
return Numeric.lcm(...this.getDenominators());
|
|
1190
|
-
};
|
|
1191
|
-
// ------------------------------------------
|
|
1192
|
-
// Polynoms factorization functions
|
|
1193
|
-
|
|
1194
|
-
gcdDenominator = (): number => {
|
|
1195
|
-
return Numeric.gcd(...this.getDenominators());
|
|
1196
|
-
};
|
|
1197
|
-
|
|
1198
|
-
lcmNumerator = (): number => {
|
|
1199
|
-
return Numeric.lcm(...this.getNumerators());
|
|
1200
|
-
};
|
|
1201
|
-
|
|
1202
|
-
gcdNumerator = (): number => {
|
|
1203
|
-
return Numeric.gcd(...this.getNumerators());
|
|
1204
|
-
};
|
|
1205
|
-
// ------------------------------------------
|
|
1206
|
-
// Polynoms helpers functions
|
|
1207
|
-
// -------------------------------------
|
|
1208
|
-
|
|
1209
|
-
commonMonom = (): Monom => {
|
|
1210
|
-
let M = new Monom().one(), numerator: number, denominator: number, degree = this.degree();
|
|
1211
|
-
|
|
1212
|
-
numerator = this.gcdNumerator();
|
|
1213
|
-
denominator = this.gcdDenominator();
|
|
1214
|
-
|
|
1215
|
-
M.coefficient = new Fraction(numerator, denominator);
|
|
1216
|
-
for (let L of this.variables) {
|
|
1217
|
-
// Initialize the setLetter with the max degree
|
|
1218
|
-
M.setLetter(L, degree);
|
|
1219
|
-
for (let m of this._monoms) {
|
|
1220
|
-
M.setLetter(L, Fraction.min(m.degree(L), M.degree(L)));
|
|
1221
|
-
if (M.degree(L).isZero()) {
|
|
1222
|
-
break;
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
return M;
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
limitToInfinity = (letter?: string): Fraction => {
|
|
1230
|
-
const M = this.monomByDegree(undefined, letter),
|
|
1231
|
-
sign = M.coefficient.sign(),
|
|
1232
|
-
degree = M.degree(letter)
|
|
1233
|
-
|
|
1234
|
-
if (degree.isStrictlyPositive()) {
|
|
1235
|
-
return sign === 1 ? (new Fraction()).infinite() : (new Fraction()).infinite().opposed()
|
|
1236
|
-
} else if (degree.isZero()) {
|
|
1237
|
-
return M.coefficient
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
// Any other cases
|
|
1241
|
-
return (new Fraction()).zero()
|
|
1242
|
-
}
|
|
1243
|
-
limitToNegativeInfinity = (letter?: string): Fraction => {
|
|
1244
|
-
const M = this.monomByDegree(undefined, letter),
|
|
1245
|
-
sign = M.coefficient.sign(),
|
|
1246
|
-
degree = M.degree(letter)
|
|
1247
|
-
|
|
1248
|
-
if (degree.isStrictlyPositive()) {
|
|
1249
|
-
return sign === -1 ? (new Fraction()).infinite() : (new Fraction()).infinite().opposed()
|
|
1250
|
-
} else if (degree.isZero()) {
|
|
1251
|
-
return M.coefficient
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
// Any other cases
|
|
1255
|
-
return (new Fraction()).zero()
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
private _getAllPotentialFactors = (P: Polynom, maxDegree: number, letter: string): Polynom[] => {
|
|
1259
|
-
let m1 = P.monoms[0].dividers,
|
|
1260
|
-
m2 = P.monoms[P.monoms.length - 1].dividers
|
|
1261
|
-
|
|
1262
|
-
let allDividers: Polynom[] = []
|
|
1263
|
-
m1.forEach(m1d => {
|
|
1264
|
-
// Get only polynom that has a degree less than a specific value
|
|
1265
|
-
if (m1d.degree(letter).leq(maxDegree)) {
|
|
1266
|
-
m2.forEach(m2d => {
|
|
1267
|
-
if (m1d.degree(letter).isNotEqual(m2d.degree(letter))) {
|
|
1268
|
-
allDividers.push(new Polynom(m1d, m2d))
|
|
1269
|
-
allDividers.push(new Polynom(m1d, m2d.clone().opposed()))
|
|
1270
|
-
}
|
|
1271
|
-
})
|
|
1272
|
-
}
|
|
1273
|
-
})
|
|
1274
|
-
|
|
1275
|
-
return allDividers
|
|
1276
|
-
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
private _parseString(inputStr: string, ...values: unknown[]): Polynom {
|
|
1280
|
-
if (values === undefined || values.length === 0) {
|
|
1281
|
-
inputStr = '' + inputStr;
|
|
1282
|
-
this._rawString = inputStr.trim().replaceAll(' ', '');
|
|
1283
|
-
|
|
1284
|
-
// Parse the polynom using the shutting yard algorithm
|
|
1285
|
-
if (inputStr !== '' && !isNaN(Number(inputStr))) {
|
|
1286
|
-
this.empty();
|
|
1287
|
-
// It's a simple number.
|
|
1288
|
-
let m = new Monom(inputStr);
|
|
1289
|
-
// m.coefficient = new Fraction(inputStr);
|
|
1290
|
-
// m.literalStr = '';
|
|
1291
|
-
this.add(m);
|
|
1292
|
-
return this;
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
// Parse the string.
|
|
1296
|
-
return this.shutingYardToReducedPolynom(inputStr);
|
|
1297
|
-
} else if (/^[a-z]/.test(inputStr)) {
|
|
1298
|
-
// We assume the inputStr contains only letters.
|
|
1299
|
-
this.empty();
|
|
1300
|
-
|
|
1301
|
-
let fractions = values.map(x => new Fraction(x));
|
|
1302
|
-
// Multiple setLetter version
|
|
1303
|
-
if (inputStr.length > 1) {
|
|
1304
|
-
// TODO: check that the number of values given correspond to the letters (+1 eventually)
|
|
1305
|
-
let letters = inputStr.split(''),
|
|
1306
|
-
i = 0;
|
|
1307
|
-
for (let F of fractions) {
|
|
1308
|
-
let m = new Monom();
|
|
1309
|
-
m.coefficient = F.clone();
|
|
1310
|
-
m.literalStr = letters[i] || '';
|
|
1311
|
-
this.add(m);
|
|
1312
|
-
i++;
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
// Single setLetter version
|
|
1316
|
-
else {
|
|
1317
|
-
let n = fractions.length - 1;
|
|
1318
|
-
for (let F of fractions) {
|
|
1319
|
-
let m = new Monom()
|
|
1320
|
-
m.coefficient = F.clone();
|
|
1321
|
-
m.literalStr = `${inputStr}^${n}`
|
|
1322
|
-
this.add(m);
|
|
1323
|
-
n--;
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
return this;
|
|
1327
|
-
} else {
|
|
1328
|
-
return this.zero();
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean, withAllMultSign?: boolean): string => {
|
|
1333
|
-
let P: string = '';
|
|
1334
|
-
|
|
1335
|
-
for (const k of this._monoms) {
|
|
1336
|
-
if (k.coefficient.value === 0) {
|
|
1337
|
-
continue;
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
// The monom to be displayed
|
|
1341
|
-
let m
|
|
1342
|
-
if (withAllMultSign) {
|
|
1343
|
-
m = k.plotFunction
|
|
1344
|
-
} else {
|
|
1345
|
-
m = (output === 'tex') ? k.tex : k.display
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${m}`;
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
if (wrapParentheses === true && this.length > 1) {
|
|
1352
|
-
if (output === 'tex') {
|
|
1353
|
-
P = `\\left( ${P} \\right)`;
|
|
1354
|
-
} else {
|
|
1355
|
-
P = `(${P})`;
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
if (P === '') {
|
|
1360
|
-
P = '0';
|
|
1361
|
-
}
|
|
1362
|
-
return P;
|
|
1363
|
-
};
|
|
1364
|
-
|
|
1365
|
-
/**
|
|
1366
|
-
* Main parse using a shutting yard class
|
|
1367
|
-
* @param inputStr
|
|
1368
|
-
*/
|
|
1369
|
-
private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
|
|
1370
|
-
// Get the RPN array of the current expression
|
|
1371
|
-
const SY: Shutingyard = new Shutingyard().parse(inputStr);
|
|
1372
|
-
const rpn: { token: string, tokenType: string }[] = SY.rpn;
|
|
1373
|
-
|
|
1374
|
-
// New version for reducing shuting yard.
|
|
1375
|
-
this.zero()
|
|
1376
|
-
|
|
1377
|
-
let stack: Polynom[] = [],
|
|
1378
|
-
monom: Monom = new Monom()
|
|
1379
|
-
|
|
1380
|
-
// Loop through the
|
|
1381
|
-
for (const element of rpn) {
|
|
1382
|
-
this.addToken(stack, element);
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
if (stack.length === 1) {
|
|
1386
|
-
this.add(stack[0])
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
return this.reorder()
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
private multiplyByPolynom = (P: Polynom): Polynom => {
|
|
1393
|
-
const M: Monom[] = [];
|
|
1394
|
-
for (const m1 of this._monoms) {
|
|
1395
|
-
for (const m2 of P.monoms) {
|
|
1396
|
-
M.push(Monom.xmultiply(m1, m2));
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
this._monoms = M;
|
|
1401
|
-
return this.reduce();
|
|
1402
|
-
};
|
|
1403
|
-
|
|
1404
|
-
private multiplyByFraction = (F: Fraction): Polynom => {
|
|
1405
|
-
for (const m of this._monoms) {
|
|
1406
|
-
m.coefficient.multiply(F);
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
return this.reduce();
|
|
1410
|
-
};
|
|
1411
|
-
|
|
1412
|
-
private multiplyByInteger = (nb: number): Polynom => {
|
|
1413
|
-
return this.multiplyByFraction(new Fraction(nb));
|
|
1414
|
-
};
|
|
1415
|
-
|
|
1416
|
-
private multiplyByMonom = (M: Monom): Polynom => {
|
|
1417
|
-
for (const m of this._monoms) {
|
|
1418
|
-
m.multiply(M)
|
|
1419
|
-
}
|
|
1420
|
-
return this.reduce();
|
|
1421
|
-
};
|
|
1422
|
-
|
|
1423
|
-
private divideByInteger = (nb: number): Polynom => {
|
|
1424
|
-
const nbF = new Fraction(nb);
|
|
1425
|
-
for (const m of this._monoms) {
|
|
1426
|
-
m.coefficient.divide(nbF);
|
|
1427
|
-
}
|
|
1428
|
-
return this;
|
|
1429
|
-
};
|
|
1430
|
-
|
|
1431
|
-
private divideByFraction = (F: Fraction): Polynom => {
|
|
1432
|
-
for (const m of this._monoms) {
|
|
1433
|
-
m.coefficient.divide(F);
|
|
1434
|
-
}
|
|
1435
|
-
return this;
|
|
1436
|
-
};
|
|
1437
|
-
|
|
1438
|
-
private _factorize2ndDegree = (letter: string): Polynom[] => {
|
|
1439
|
-
let P1: Polynom, P2: Polynom,
|
|
1440
|
-
a, b, c, delta, x1, x2, factor;
|
|
1441
|
-
|
|
1442
|
-
// One variable only
|
|
1443
|
-
if (this.numberOfVars === 1) {
|
|
1444
|
-
a = this.monomByDegree(2, letter).coefficient;
|
|
1445
|
-
b = this.monomByDegree(1, letter).coefficient;
|
|
1446
|
-
c = this.monomByDegree(0, letter).coefficient;
|
|
1447
|
-
delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
|
|
1448
|
-
|
|
1449
|
-
if (delta.isZero()) {
|
|
1450
|
-
x1 = b.clone().opposed().divide(a.clone().multiply(2))
|
|
1451
|
-
P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
|
|
1452
|
-
P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
|
|
1453
|
-
factor = a.divide(x1.denominator).divide(x1.denominator);
|
|
1454
|
-
|
|
1455
|
-
if (!factor.isOne()) {
|
|
1456
|
-
// TODO: Update new Polynom to accept anything...
|
|
1457
|
-
return [new Polynom(factor.display), P1, P2]
|
|
1458
|
-
} else {
|
|
1459
|
-
return [P1, P2]
|
|
1460
|
-
}
|
|
1461
|
-
} else if (delta.isPositive() && delta.isSquare()) {
|
|
1462
|
-
x1 = b.clone().opposed()
|
|
1463
|
-
.add(delta.clone().sqrt())
|
|
1464
|
-
.divide(a.clone().multiply(2))
|
|
1465
|
-
x2 = b.clone().opposed()
|
|
1466
|
-
.subtract(delta.clone().sqrt())
|
|
1467
|
-
.divide(a.clone().multiply(2))
|
|
1468
|
-
|
|
1469
|
-
// (2x+5)(3x-2)
|
|
1470
|
-
// 6x^2+11x-10
|
|
1471
|
-
// a = 6, b = 11, c = -10
|
|
1472
|
-
// delta = 121-4*6*(-10) = 361= 19^2
|
|
1473
|
-
// x1 = (-11 + 19) / 12 = 8/12 = 2/3
|
|
1474
|
-
// x2 = (-11 - 19) / 12 = -30/12 = -5/2
|
|
1475
|
-
factor = a.divide(x1.denominator).divide(x2.denominator);
|
|
1476
|
-
if (factor.isOne()) {
|
|
1477
|
-
return [
|
|
1478
|
-
new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
|
|
1479
|
-
new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
|
|
1480
|
-
]
|
|
1481
|
-
} else {
|
|
1482
|
-
return [
|
|
1483
|
-
new Polynom(factor.display),
|
|
1484
|
-
new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
|
|
1485
|
-
new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
|
|
1486
|
-
]
|
|
1487
|
-
|
|
1488
|
-
}
|
|
1489
|
-
} else {
|
|
1490
|
-
// No solution possible - return the complete value.
|
|
1491
|
-
return [this.clone()]
|
|
1492
|
-
}
|
|
1493
|
-
} else {
|
|
1494
|
-
// If multiple variables, only handle perfect squares...
|
|
1495
|
-
a = this.monomByDegree(2, letter);
|
|
1496
|
-
b = this.monomByDegree(1, letter);
|
|
1497
|
-
c = this.monomByDegree(0, letter);
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
if (a.isLiteralSquare() && c.isLiteralSquare()) {
|
|
1501
|
-
// Check the middle item is same as...
|
|
1502
|
-
if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
|
|
1503
|
-
// Determine if the coefficient values matches.
|
|
1504
|
-
|
|
1505
|
-
// Search 4 values (r, s, t, u) that matches:
|
|
1506
|
-
// (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
|
|
1507
|
-
|
|
1508
|
-
let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
|
|
1509
|
-
let xFactors = xPolynom._factorize2ndDegree('x');
|
|
1510
|
-
|
|
1511
|
-
let factors = [], xyzPolynom: Polynom;
|
|
1512
|
-
|
|
1513
|
-
if (xFactors.length >= 2) {
|
|
1514
|
-
for (let p of xFactors) {
|
|
1515
|
-
if (p.degree().isZero()) {
|
|
1516
|
-
factors.push(p.clone())
|
|
1517
|
-
} else {
|
|
1518
|
-
xyzPolynom = p.clone();
|
|
1519
|
-
xyzPolynom.monoms[0].literal = a.literalSqrt
|
|
1520
|
-
xyzPolynom.monoms[1].literal = c.literalSqrt
|
|
1521
|
-
factors.push(xyzPolynom.clone())
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
return factors
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
return [this.clone()]
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
private _factorizeByGroups = (): Polynom[] => {
|
|
1534
|
-
// TODO: Factorize by groups.
|
|
1535
|
-
return [];
|
|
1536
|
-
}
|
|
1537
|
-
}
|