pimath 0.1.39 → 0.2.0
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/pimath.js +3127 -2865
- package/dist/pimath.js.map +1 -1
- package/package.json +16 -12
- package/src/algebra/equation.ts +558 -0
- package/src/algebra/equationSolver.ts +488 -0
- package/src/algebra/factor.ts +338 -0
- package/src/algebra/index.ts +11 -0
- package/src/algebra/linearSystem.ts +439 -0
- package/src/algebra/logicalset.ts +255 -0
- package/src/algebra/matrix.ts +474 -0
- package/src/algebra/monom.ts +977 -0
- package/src/algebra/operations.ts +23 -0
- package/src/algebra/polyFactor.ts +668 -0
- package/src/algebra/polynom.ts +1247 -0
- package/src/analyze/index.ts +4 -0
- package/src/analyze/solution.ts +178 -0
- package/src/analyze/tableOfSigns.ts +30 -0
- package/src/coefficients/fraction.ts +718 -0
- package/src/coefficients/index.ts +4 -0
- package/src/coefficients/root.ts +346 -0
- package/src/geometry/TupleN.ts +128 -0
- package/src/geometry/circle.ts +456 -0
- package/src/geometry/geomMath.ts +71 -0
- package/src/geometry/index.ts +11 -0
- package/src/geometry/line.ts +653 -0
- package/src/geometry/line3.ts +211 -0
- package/src/geometry/plane3.ts +179 -0
- package/src/geometry/point.ts +104 -0
- package/src/geometry/sphere3.ts +214 -0
- package/src/geometry/triangle.ts +482 -0
- package/src/geometry/vector.ts +225 -0
- package/src/helpers.ts +35 -0
- package/src/index.ts +61 -0
- package/src/numeric.ts +196 -0
- package/src/pimath.interface.ts +162 -0
- package/src/randomization/algebra/rndEquation.ts +41 -0
- package/src/randomization/algebra/rndMonom.ts +39 -0
- package/src/randomization/algebra/rndPolynom.ts +100 -0
- package/src/randomization/coefficient/rndFraction.ts +38 -0
- package/src/randomization/geometry/rndCircle.ts +27 -0
- package/src/randomization/geometry/rndLine.ts +35 -0
- package/src/randomization/geometry/rndLine3.ts +27 -0
- package/src/randomization/geometry/rndVector.ts +63 -0
- package/src/randomization/random.ts +89 -0
- package/src/randomization/rndHelpers.ts +102 -0
- package/src/randomization/rndTypes.ts +67 -0
- package/types/algebra/equation.d.ts +18 -17
- package/types/algebra/equation.d.ts.map +1 -1
- package/types/algebra/equationSolver.d.ts +7 -3
- package/types/algebra/equationSolver.d.ts.map +1 -1
- package/types/algebra/factor.d.ts +1 -1
- package/types/algebra/factor.d.ts.map +1 -1
- package/types/algebra/linearSystem.d.ts +23 -6
- package/types/algebra/linearSystem.d.ts.map +1 -1
- package/types/algebra/logicalset.d.ts +1 -1
- package/types/algebra/logicalset.d.ts.map +1 -1
- package/types/algebra/monom.d.ts +1 -6
- package/types/algebra/monom.d.ts.map +1 -1
- package/types/algebra/operations.d.ts.map +1 -1
- package/types/algebra/polyFactor.d.ts +9 -4
- package/types/algebra/polyFactor.d.ts.map +1 -1
- package/types/algebra/polynom.d.ts +10 -7
- package/types/algebra/polynom.d.ts.map +1 -1
- package/types/analyze/index.d.ts +2 -0
- package/types/analyze/index.d.ts.map +1 -0
- package/types/analyze/solution.d.ts +27 -0
- package/types/analyze/solution.d.ts.map +1 -0
- package/types/analyze/tableOfSigns.d.ts +9 -0
- package/types/analyze/tableOfSigns.d.ts.map +1 -0
- package/types/coefficients/fraction.d.ts +14 -12
- package/types/coefficients/fraction.d.ts.map +1 -1
- package/types/coefficients/index.d.ts +1 -1
- package/types/coefficients/index.d.ts.map +1 -1
- package/types/coefficients/root.d.ts +41 -0
- package/types/coefficients/root.d.ts.map +1 -0
- package/types/geometry/TupleAbstract.d.ts +22 -0
- package/types/geometry/TupleAbstract.d.ts.map +1 -0
- package/types/geometry/TupleN.d.ts +24 -0
- package/types/geometry/TupleN.d.ts.map +1 -0
- package/types/geometry/circle.d.ts +26 -17
- package/types/geometry/circle.d.ts.map +1 -1
- package/types/geometry/geomMath.d.ts +2 -1
- package/types/geometry/geomMath.d.ts.map +1 -1
- package/types/geometry/index.d.ts.map +1 -1
- package/types/geometry/line.d.ts +21 -30
- package/types/geometry/line.d.ts.map +1 -1
- package/types/geometry/line3.d.ts +19 -19
- package/types/geometry/line3.d.ts.map +1 -1
- package/types/geometry/matrix.d.ts +11 -11
- package/types/geometry/plane3.d.ts +9 -9
- package/types/geometry/plane3.d.ts.map +1 -1
- package/types/geometry/point.d.ts +12 -7
- package/types/geometry/point.d.ts.map +1 -1
- package/types/geometry/triangle.d.ts +68 -23
- package/types/geometry/triangle.d.ts.map +1 -1
- package/types/geometry/vector.d.ts +24 -44
- package/types/geometry/vector.d.ts.map +1 -1
- package/types/helpers.d.ts +1 -0
- package/types/helpers.d.ts.map +1 -1
- package/types/index.d.ts +6 -4
- package/types/index.d.ts.map +1 -1
- package/types/numeric.d.ts +2 -0
- package/types/numeric.d.ts.map +1 -1
- package/types/pimath.interface.d.ts +38 -44
- package/types/pimath.interface.d.ts.map +1 -1
- package/types/randomization/algebra/rndPolynom.d.ts.map +1 -1
- package/types/randomization/coefficient/rndFraction.d.ts +1 -1
- package/types/randomization/coefficient/rndFraction.d.ts.map +1 -1
- package/types/randomization/geometry/rndLine.d.ts.map +1 -1
- package/types/randomization/random.d.ts +3 -2
- package/types/randomization/random.d.ts.map +1 -1
- package/types/randomization/rndTypes.d.ts +15 -10
- package/types/randomization/rndTypes.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pimath",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A math library for teacher :)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/pimath.js",
|
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
"require": "./dist/pimath.js"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
|
+
"./types/index.d.ts": "./types/index.d.ts",
|
|
16
17
|
"files": [
|
|
17
18
|
"dist",
|
|
18
|
-
"types"
|
|
19
|
+
"types",
|
|
20
|
+
"src"
|
|
19
21
|
],
|
|
20
22
|
"scripts": {
|
|
21
23
|
"dev": "vite serve",
|
|
@@ -36,20 +38,22 @@
|
|
|
36
38
|
"url": "git+https://github.com/basilgass/PiMath.git"
|
|
37
39
|
},
|
|
38
40
|
"devDependencies": {
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
41
|
+
"@tailwindcss/vite": "^4.1.18",
|
|
42
|
+
"@vitejs/plugin-vue": "^6.0.4",
|
|
43
|
+
"autoprefixer": "^10.4.24",
|
|
44
|
+
"dependency-cruiser": "^17.3.8",
|
|
45
|
+
"eslint": "^9.39.2",
|
|
46
|
+
"globals": "^17.3.0",
|
|
47
|
+
"tailwindcss": "^4.1.18",
|
|
45
48
|
"ts-loader": "^9.5.4",
|
|
46
49
|
"ts-node": "^10.9.2",
|
|
47
|
-
"typedoc": "^0.28.
|
|
50
|
+
"typedoc": "^0.28.16",
|
|
48
51
|
"typescript": "^5.9.3",
|
|
49
|
-
"typescript-eslint": "^8.
|
|
50
|
-
"vite": "^7.
|
|
52
|
+
"typescript-eslint": "^8.54.0",
|
|
53
|
+
"vite": "^7.3.1",
|
|
51
54
|
"vite-plugin-dts": "^4.5.4",
|
|
52
|
-
"vitest": "^4.0.
|
|
55
|
+
"vitest": "^4.0.18",
|
|
56
|
+
"vue-router": "^5.0.2"
|
|
53
57
|
},
|
|
54
58
|
"dependencies": {
|
|
55
59
|
"piexpression": "^0.1.3"
|
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EQUATION_SIGN,
|
|
3
|
+
IAlgebra,
|
|
4
|
+
IEquation,
|
|
5
|
+
InputAlgebra,
|
|
6
|
+
InputValue,
|
|
7
|
+
IPiMathObject,
|
|
8
|
+
literalType
|
|
9
|
+
} from "../pimath.interface"
|
|
10
|
+
import {Fraction} from "../coefficients/fraction"
|
|
11
|
+
import {Numeric} from "../numeric"
|
|
12
|
+
import {EquationSolver} from "./equationSolver"
|
|
13
|
+
import {Monom} from "./monom"
|
|
14
|
+
import {Polynom} from "./polynom"
|
|
15
|
+
import type {Solution} from "../analyze/solution"
|
|
16
|
+
|
|
17
|
+
export class Equation implements
|
|
18
|
+
IPiMathObject<Equation>,
|
|
19
|
+
IEquation<Equation>,
|
|
20
|
+
IAlgebra<Equation> {
|
|
21
|
+
|
|
22
|
+
// Left part of the equation
|
|
23
|
+
#left: Polynom
|
|
24
|
+
// Right part of the equation
|
|
25
|
+
#right: Polynom
|
|
26
|
+
// Signe of the equation
|
|
27
|
+
#sign: EQUATION_SIGN
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
constructor(equation: InputAlgebra<Polynom> | Equation)
|
|
31
|
+
constructor(left: InputAlgebra<Polynom>, right: InputAlgebra<Polynom>, sign?: EQUATION_SIGN)
|
|
32
|
+
constructor(left?: InputAlgebra<Polynom> | Equation, right?: InputAlgebra<Polynom>, sign?: EQUATION_SIGN) {
|
|
33
|
+
// Default equation
|
|
34
|
+
this.#left = new Polynom().zero()
|
|
35
|
+
this.#right = new Polynom().zero()
|
|
36
|
+
this.#sign = '='
|
|
37
|
+
|
|
38
|
+
// Only one value, it's an equation
|
|
39
|
+
if (left !== undefined && right === undefined) {
|
|
40
|
+
if (left instanceof Equation) {
|
|
41
|
+
return left.clone()
|
|
42
|
+
} else if (typeof left === 'string') {
|
|
43
|
+
// Parse the equation as a string.
|
|
44
|
+
this.parse(left)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
} else if (left !== undefined && right !== undefined) {
|
|
48
|
+
// Two values, it's an equation with left and right polynoms.
|
|
49
|
+
this.left = new Polynom(left as InputAlgebra<Polynom>)
|
|
50
|
+
this.right = new Polynom(right)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (sign !== undefined) {
|
|
54
|
+
this.sign = sign
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return this
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ------------------------------------------
|
|
61
|
+
public parse = (equationString: string): this => {
|
|
62
|
+
// Find the string separator
|
|
63
|
+
const strSign: string | false = this.#findSign(equationString)
|
|
64
|
+
|
|
65
|
+
if (strSign === false) {
|
|
66
|
+
throw new Error('The equation is not valid (no sign found)')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// The StrSign is found
|
|
70
|
+
const pStr: string[] = equationString.split(strSign)
|
|
71
|
+
|
|
72
|
+
return this.create(new Polynom(pStr[0]), new Polynom(pStr[1]), this.#formatSign(strSign))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public clone = (): Equation => {
|
|
76
|
+
return new Equation(this.#left.clone(), this.#right.clone(), this.#sign)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public get tex(): string {
|
|
80
|
+
return `${this.#left.tex}${this.signAsTex}${this.#right.tex}`
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public get display(): string {
|
|
84
|
+
return `${this.#left.display}${this.signAsTex}${this.#right.display}`
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public static isEquationString(equationString: string): boolean {
|
|
88
|
+
// The equation sign can be one of the following:
|
|
89
|
+
// =, <, >, <=, >=
|
|
90
|
+
|
|
91
|
+
return equationString.includes('=') ||
|
|
92
|
+
equationString.includes('<') ||
|
|
93
|
+
equationString.includes('>') ||
|
|
94
|
+
equationString.includes('<=') ||
|
|
95
|
+
equationString.includes('>=')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public static makeSolutionsUnique(solutions: Solution[], sorted?: boolean): Solution[] {
|
|
99
|
+
const solutionAsTex: string[] = [],
|
|
100
|
+
uniqueSolutions = solutions.filter(sol => {
|
|
101
|
+
if (!solutionAsTex.includes(sol.tex)) {
|
|
102
|
+
solutionAsTex.push(sol.tex)
|
|
103
|
+
return true
|
|
104
|
+
} else {
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
if (sorted === true) {
|
|
110
|
+
uniqueSolutions.sort((a, b) => a.value - b.value)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return uniqueSolutions
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Add a value to the equation
|
|
118
|
+
* if value is an equation, add the left part to the left part of the equation
|
|
119
|
+
* and the right part to the right part of the equation
|
|
120
|
+
* if value is a string, try to create an equation
|
|
121
|
+
* if it fails, create a polynom and add it to the left and right part of the equation
|
|
122
|
+
* @param value | Polynom | Monom | Fraction | string | monom
|
|
123
|
+
*/
|
|
124
|
+
public add(value: InputValue<Equation | Polynom>): this {
|
|
125
|
+
|
|
126
|
+
if (value instanceof Equation) {
|
|
127
|
+
// add the left part of the equation
|
|
128
|
+
this.#left.add(value.left)
|
|
129
|
+
// add the right part of the equation
|
|
130
|
+
this.#right.add(value.right)
|
|
131
|
+
|
|
132
|
+
return this
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (typeof value === 'string' &&
|
|
136
|
+
!Equation.isEquationString(value)) {
|
|
137
|
+
|
|
138
|
+
return this.add(new Equation(value))
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const p = new Polynom(value)
|
|
142
|
+
this.#left.add(p)
|
|
143
|
+
this.#right.add(p)
|
|
144
|
+
|
|
145
|
+
return this
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public create = (left: Polynom, right: Polynom, sign?: string): this => {
|
|
149
|
+
this.#left = left
|
|
150
|
+
this.#right = right
|
|
151
|
+
this.#sign = this.#formatSign(sign ?? "=")
|
|
152
|
+
return this
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Get the degree of the equation
|
|
157
|
+
* @param letter
|
|
158
|
+
*/
|
|
159
|
+
public degree = (letter?: string): Fraction => {
|
|
160
|
+
return Fraction.max(this.#left.degree(letter), this.#right.degree(letter))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* divide an equation by a given value (transformed as a fraction)
|
|
165
|
+
*
|
|
166
|
+
* ```
|
|
167
|
+
* 8x+10=6x \vert 2
|
|
168
|
+
* 4x+5=3x
|
|
169
|
+
* ```
|
|
170
|
+
*
|
|
171
|
+
* |>Alternatively with $3x-4$ maybe it's working ?
|
|
172
|
+
* $$\frac{3x}{5}$$
|
|
173
|
+
*
|
|
174
|
+
* @param value
|
|
175
|
+
* @returns {Equation}
|
|
176
|
+
*/
|
|
177
|
+
public divide = (value: InputValue<Fraction>): this => {
|
|
178
|
+
// Make sure we have a fraction.
|
|
179
|
+
const F: Fraction = new Fraction(value)
|
|
180
|
+
|
|
181
|
+
if (F.isZero()) {
|
|
182
|
+
return this
|
|
183
|
+
} else {
|
|
184
|
+
return this.multiply(F.inverse())
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Create an Equation using two polynoms.
|
|
190
|
+
* Markdown *support* is cool
|
|
191
|
+
* @param values
|
|
192
|
+
* @param asNumeric
|
|
193
|
+
*/
|
|
194
|
+
public evaluate(values: InputValue<Fraction> | literalType<number | Fraction>, asNumeric?: boolean ): boolean {
|
|
195
|
+
// Evaluate the left and right part of the equation.
|
|
196
|
+
// compare the results.
|
|
197
|
+
|
|
198
|
+
// Evaluate the left and right part of the equation.
|
|
199
|
+
const left = this.#left.evaluate(values, asNumeric),
|
|
200
|
+
right = this.#right.evaluate(values, asNumeric)
|
|
201
|
+
|
|
202
|
+
// compare the results.
|
|
203
|
+
if (asNumeric) {
|
|
204
|
+
return left === right
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return (left as Fraction).isEqual(right as Fraction)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// -----------------------------------------------
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Determine if the equation contains a variable.
|
|
214
|
+
* @param letter
|
|
215
|
+
*/
|
|
216
|
+
public hasVariable = (letter: string): boolean => {
|
|
217
|
+
return this.variables.includes(letter)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
public isEqual(value: InputValue<Equation>): boolean {
|
|
221
|
+
const equ = new Equation(value)
|
|
222
|
+
return equ.left.isEqual(this.#left) && equ.right.isEqual(this.#right)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// -----------------------------------------------
|
|
226
|
+
// Equations operations
|
|
227
|
+
|
|
228
|
+
// Equations helpers
|
|
229
|
+
public isEqualTo = (equ: Equation): boolean => {
|
|
230
|
+
const p1 = equ.clone().moveLeft().left,
|
|
231
|
+
p2 = this.clone().moveLeft().left
|
|
232
|
+
|
|
233
|
+
// They are the same.
|
|
234
|
+
return p1.isEqual(p2) || p1.isOppositeAt(p2)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
public isLinearTo = (equ: Equation): boolean => {
|
|
238
|
+
// Move all left.
|
|
239
|
+
const p1 = equ.clone().moveLeft().simplify().left,
|
|
240
|
+
p2 = this.clone().moveLeft().simplify().left
|
|
241
|
+
|
|
242
|
+
// They are the same.
|
|
243
|
+
return p1.isEqual(p2) || p1.isOppositeAt(p2)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Determine if the equation contains more than one letter/variable.
|
|
248
|
+
*/
|
|
249
|
+
public isMultiVariable = (): boolean => {
|
|
250
|
+
return this.#left.isMultiVariable || this.#right.isMultiVariable
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Reorder the polynom to have only one letter on the left, the rest on the right.
|
|
255
|
+
* @param letter
|
|
256
|
+
*/
|
|
257
|
+
public isolate = (letter?: string): this | false => {
|
|
258
|
+
// Determine if we can isolate the variables.
|
|
259
|
+
|
|
260
|
+
// Both part of the equations must be of the first degree.
|
|
261
|
+
if (!this.degree(letter).isOne()) {
|
|
262
|
+
return false
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Modify the equation to isolate the asked variable.
|
|
266
|
+
if (this.isMultiVariable()) {
|
|
267
|
+
return false
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Isolate the letter.
|
|
271
|
+
let mMove: Monom
|
|
272
|
+
// Start by moving everything to the left.
|
|
273
|
+
this.#left.subtract(this.#right)
|
|
274
|
+
this.#right.zero()
|
|
275
|
+
const values = [...this.#left.monoms]
|
|
276
|
+
for (const m of values) {
|
|
277
|
+
if (!m.hasVariable(letter)) {
|
|
278
|
+
mMove = m.clone()
|
|
279
|
+
this.#left.subtract(mMove)
|
|
280
|
+
this.#right.subtract(mMove)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// In theory, we should have only one item on the left.
|
|
285
|
+
if (this.#left.length !== 1) {
|
|
286
|
+
return false
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const cMove: Fraction = this.#left.monoms[0].coefficient.clone()
|
|
290
|
+
this.#left.divide(cMove)
|
|
291
|
+
this.#right.divide(cMove)
|
|
292
|
+
return this
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Getter and setter
|
|
296
|
+
public get left(): Polynom {
|
|
297
|
+
return this.#left
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
public set left(value: Polynom) {
|
|
301
|
+
this.#left = value
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// -----------------------------------------------
|
|
305
|
+
public letters = (): string[] => {
|
|
306
|
+
return [...new Set([...this.#left.letters(), ...this.#right.letters()])]
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// -----------------------------------------------
|
|
310
|
+
/**
|
|
311
|
+
* Reorder will move all monoms containing a letter on the left, all the other on the right.
|
|
312
|
+
*/
|
|
313
|
+
public moveLeft = (): this => {
|
|
314
|
+
this.#left.subtract(this.#right)
|
|
315
|
+
this.#right.zero()
|
|
316
|
+
return this
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Multiple an equation by a fraction value.
|
|
321
|
+
* @param value
|
|
322
|
+
*/
|
|
323
|
+
public multiply = (value: InputValue<Fraction>): this => {
|
|
324
|
+
// Make sure we have a fraction.
|
|
325
|
+
const F: Fraction = new Fraction(value)
|
|
326
|
+
|
|
327
|
+
// Multiply each part of the equation by the fraction
|
|
328
|
+
this.#left.multiply(F)
|
|
329
|
+
this.#right.multiply(F)
|
|
330
|
+
|
|
331
|
+
// The sign of the inequality must be changed.
|
|
332
|
+
if (this.#sign !== '=' && F.sign() === -1) {
|
|
333
|
+
this.#reverseSign()
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return this
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
public get numberOfVars(): number {
|
|
340
|
+
return this.variables.length
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
public opposite = (): this => {
|
|
344
|
+
this.#left = this.#left.opposite()
|
|
345
|
+
this.#right = this.#right.opposite()
|
|
346
|
+
return this
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
public pow(value: number): this {
|
|
350
|
+
this.#left.pow(value)
|
|
351
|
+
this.#right.pow(value)
|
|
352
|
+
return this
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
public reduce(): this {
|
|
356
|
+
// reduce means moving everything to the left
|
|
357
|
+
// remove the fractions
|
|
358
|
+
// simplify the equation
|
|
359
|
+
// reorder the equation
|
|
360
|
+
// start with a positive left part
|
|
361
|
+
|
|
362
|
+
// Move all left. The right part is now zero.
|
|
363
|
+
this.moveLeft()
|
|
364
|
+
|
|
365
|
+
// Reduce the equation: simplify and reorder.
|
|
366
|
+
this.#left.reduce()
|
|
367
|
+
|
|
368
|
+
// Simplify the equation.
|
|
369
|
+
this.simplify()
|
|
370
|
+
|
|
371
|
+
// Make sure the first part is positive.
|
|
372
|
+
if (this.#left.monoms[0].coefficient.isNegative()) {
|
|
373
|
+
this.multiply(-1)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return this
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
public reorder = (allLeft?: boolean): this => {
|
|
380
|
+
// Move all monoms of degree greater than 0 to the left.
|
|
381
|
+
// and all zero degree monoms to the right.
|
|
382
|
+
this.#left.subtract(this.#right)
|
|
383
|
+
this.#right.zero()
|
|
384
|
+
this.#left.reorder()
|
|
385
|
+
|
|
386
|
+
// we have all left (so equal zero) : it's done !
|
|
387
|
+
if (allLeft) {
|
|
388
|
+
return this
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Fetch all zero degree monoms.
|
|
392
|
+
this.#left.monoms
|
|
393
|
+
.filter(m => m.degree().isZero())
|
|
394
|
+
.forEach(m => {
|
|
395
|
+
const move = m.clone()
|
|
396
|
+
this.#left.subtract(move)
|
|
397
|
+
this.#right.subtract(move)
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
// Reorder the left and right polynoms
|
|
401
|
+
this.#left.reorder()
|
|
402
|
+
this.#right.reorder()
|
|
403
|
+
return this
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// ------------------------------------------
|
|
407
|
+
public replaceBy = (letter: string, P: Polynom): this => {
|
|
408
|
+
this.#left.replaceBy(letter, P)
|
|
409
|
+
this.#right.replaceBy(letter, P)
|
|
410
|
+
return this
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
public get right(): Polynom {
|
|
414
|
+
return this.#right
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
public set right(value: Polynom) {
|
|
418
|
+
this.#right = value
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ------------------------------------------
|
|
422
|
+
public get sign(): string {
|
|
423
|
+
return this.#sign
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
public set sign(value: string) {
|
|
427
|
+
// Set the sign value as formatted.
|
|
428
|
+
this.#sign = this.#formatSign(value)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
public get signAsTex(): string {
|
|
432
|
+
if (this.#sign === '>=') {
|
|
433
|
+
return '\\geq'
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (this.#sign === '<=') {
|
|
437
|
+
return '\\leq'
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return this.#sign
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Multiply by the lcm denominator and divide by the gcm numerators.
|
|
445
|
+
*/
|
|
446
|
+
public simplify = (): this => {
|
|
447
|
+
this.multiply(Numeric.lcm(...this.#left.getDenominators(), ...this.#right.getDenominators()))
|
|
448
|
+
this.divide(Numeric.gcd(...this.#left.getNumerators(), ...this.#right.getNumerators()))
|
|
449
|
+
return this
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// -----------------------------------------------
|
|
453
|
+
public solve = (): Solution[] => {
|
|
454
|
+
const solver = new EquationSolver(this.clone())
|
|
455
|
+
return solver.solve()
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
public split(): [Polynom, Polynom] {
|
|
459
|
+
return [this.#left.clone(), this.#right.clone()]
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
public subtract(value: InputValue<Equation | Polynom>): this {
|
|
463
|
+
if (value instanceof Equation) {
|
|
464
|
+
this.#left.subtract(value.left)
|
|
465
|
+
this.#right.subtract(value.right)
|
|
466
|
+
|
|
467
|
+
return this
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (typeof value === 'string' &&
|
|
471
|
+
!Equation.isEquationString(value)) {
|
|
472
|
+
return this.subtract(new Equation(value))
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const p = new Polynom(value)
|
|
476
|
+
this.#left.subtract(p)
|
|
477
|
+
this.#right.subtract(p)
|
|
478
|
+
|
|
479
|
+
return this
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
public test = (values: literalType<Fraction>): boolean => {
|
|
483
|
+
return (this.left.evaluate(values) as Fraction).isEqual(this.right.evaluate(values))
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
public get variables(): string[] {
|
|
487
|
+
return [...new Set(this.#right.variables.concat(this.#left.variables))]
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
#findSign = (equationString: string): string | false => {
|
|
491
|
+
if (equationString.includes('geq')) {
|
|
492
|
+
return (equationString.includes('\\geq')) ? '\\geq' : 'geq'
|
|
493
|
+
} else if (equationString.includes('leq')) {
|
|
494
|
+
return (equationString.includes('\\leq')) ? '\\leq' : 'leq'
|
|
495
|
+
} else if (equationString.includes('>=')) {
|
|
496
|
+
return '>='
|
|
497
|
+
} else if (equationString.includes('=>')) {
|
|
498
|
+
return '=>'
|
|
499
|
+
} else if (equationString.includes('>')) {
|
|
500
|
+
return '>'
|
|
501
|
+
} else if (equationString.includes('<=')) {
|
|
502
|
+
return '<='
|
|
503
|
+
} else if (equationString.includes('=<')) {
|
|
504
|
+
return '=<'
|
|
505
|
+
} else if (equationString.includes('<')) {
|
|
506
|
+
return '<'
|
|
507
|
+
} else if (equationString.includes('=')) {
|
|
508
|
+
return '='
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
throw new Error('The equation is not valid (no sign found)')
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// -----------------------------------------------
|
|
515
|
+
// Equations solving algorithms
|
|
516
|
+
#formatSign = (signStr?: string): EQUATION_SIGN => {
|
|
517
|
+
if (signStr === undefined) {
|
|
518
|
+
return '='
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (signStr.includes('geq')) {
|
|
522
|
+
return '>='
|
|
523
|
+
} else if (signStr.includes('>=')) {
|
|
524
|
+
return '>='
|
|
525
|
+
} else if (signStr.includes('=>')) {
|
|
526
|
+
return '>='
|
|
527
|
+
} else if (signStr.includes('>')) {
|
|
528
|
+
return '>'
|
|
529
|
+
} else if (signStr.includes('leq')) {
|
|
530
|
+
return '<='
|
|
531
|
+
} else if (signStr.includes('<=')) {
|
|
532
|
+
return '<='
|
|
533
|
+
} else if (signStr.includes('=<')) {
|
|
534
|
+
return '<='
|
|
535
|
+
} else if (signStr.includes('<')) {
|
|
536
|
+
return '<'
|
|
537
|
+
} else {
|
|
538
|
+
return '='
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
#reverseSign = (): this => {
|
|
543
|
+
if (this.#sign === '=') {
|
|
544
|
+
return this
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (this.#sign.includes('<')) {
|
|
548
|
+
this.#sign.replace('<', '>')
|
|
549
|
+
return this
|
|
550
|
+
}
|
|
551
|
+
if (this.#sign.includes('>')) {
|
|
552
|
+
this.#sign.replace('>', '<')
|
|
553
|
+
return this
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return this
|
|
557
|
+
}
|
|
558
|
+
}
|