pimath 0.0.66 → 0.0.69
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/.eslintrc.js +23 -23
- package/dist/pi.js +178 -44
- package/dist/pi.js.map +1 -1
- package/dist/pi.min.js +1 -1
- package/dist/pi.min.js.map +1 -1
- package/docs/assets/highlight.css +78 -78
- package/docs/assets/main.js +52 -52
- package/docs/assets/style.css +1413 -1413
- package/docs/classes/Logicalset.Logicalset-1.html +4 -4
- package/docs/classes/Polynom.Rational.html +3 -3
- package/docs/classes/algebra_equation.Equation.html +25 -25
- package/docs/classes/algebra_monom.Monom.html +113 -113
- package/docs/classes/algebra_polynom.Polynom.html +29 -29
- package/docs/classes/coefficients_fraction.Fraction.html +18 -18
- package/docs/classes/coefficients_nthroot.NthRoot.html +2 -2
- package/docs/classes/geometry_circle.Circle.html +2 -2
- package/docs/classes/geometry_line.Line.html +2 -2
- package/docs/classes/geometry_triangle.Triangle.html +16 -16
- package/docs/classes/numeric.Numeric.html +13 -13
- package/docs/classes/shutingyard.Shutingyard.html +17 -17
- package/docs/index.html +10 -10
- package/docs/interfaces/algebra_equation.ISolution.html +2 -2
- package/docs/modules/Logicalset.html +2 -2
- package/docs/modules/Polynom.html +2 -2
- package/docs/modules/Vector.html +2 -2
- package/esm/maths/algebra/equation.js +2 -2
- package/esm/maths/algebra/equation.js.map +1 -1
- package/esm/maths/algebra/polynom.d.ts +4 -5
- package/esm/maths/algebra/polynom.js +2 -2
- package/esm/maths/algebra/polynom.js.map +1 -1
- package/esm/maths/algebra/rational.d.ts +8 -10
- package/esm/maths/algebra/rational.js +11 -6
- package/esm/maths/algebra/study/rationalStudy.d.ts +1 -2
- package/esm/maths/algebra/study/rationalStudy.js +14 -14
- package/esm/maths/algebra/study/rationalStudy.js.map +1 -1
- package/esm/maths/algebra/study.d.ts +9 -22
- package/esm/maths/algebra/study.js +33 -23
- package/esm/maths/algebra/study.js.map +1 -1
- package/esm/maths/coefficients/fraction.d.ts +8 -6
- package/esm/maths/coefficients/fraction.js +34 -17
- package/esm/maths/coefficients/fraction.js.map +1 -1
- package/esm/maths/expressions/expression.d.ts +21 -0
- package/esm/maths/expressions/expression.js +161 -0
- package/esm/maths/expressions/expression.js.map +1 -0
- package/esm/maths/expressions/expressionFactor.d.ts +29 -0
- package/esm/maths/expressions/expressionFactor.js +109 -0
- package/esm/maths/expressions/expressionFactor.js.map +1 -0
- package/esm/maths/expressions/expressionMember.d.ts +16 -0
- package/esm/maths/expressions/expressionMember.js +90 -0
- package/esm/maths/expressions/expressionMember.js.map +1 -0
- package/esm/maths/expressions/expressionOperators.d.ts +8 -0
- package/esm/maths/expressions/expressionOperators.js +42 -0
- package/esm/maths/expressions/expressionOperators.js.map +1 -0
- package/esm/maths/expressions/expressionParser.d.ts +12 -0
- package/esm/maths/expressions/expressionParser.js +219 -0
- package/esm/maths/expressions/expressionParser.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactor.d.ts +7 -0
- package/esm/maths/expressions/factors/ExpFactor.js +22 -0
- package/esm/maths/expressions/factors/ExpFactor.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorConstant.d.ts +13 -0
- package/esm/maths/expressions/factors/ExpFactorConstant.js +49 -0
- package/esm/maths/expressions/factors/ExpFactorConstant.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorExponential.d.ts +7 -0
- package/esm/maths/expressions/factors/ExpFactorExponential.js +18 -0
- package/esm/maths/expressions/factors/ExpFactorExponential.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorNumber.d.ts +13 -0
- package/esm/maths/expressions/factors/ExpFactorNumber.js +36 -0
- package/esm/maths/expressions/factors/ExpFactorNumber.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorPower.d.ts +9 -0
- package/esm/maths/expressions/factors/ExpFactorPower.js +22 -0
- package/esm/maths/expressions/factors/ExpFactorPower.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorSin.d.ts +7 -0
- package/esm/maths/expressions/factors/ExpFactorSin.js +22 -0
- package/esm/maths/expressions/factors/ExpFactorSin.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorTrigo.d.ts +19 -0
- package/esm/maths/expressions/factors/ExpFactorTrigo.js +40 -0
- package/esm/maths/expressions/factors/ExpFactorTrigo.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorVariable.d.ts +12 -0
- package/esm/maths/expressions/factors/ExpFactorVariable.js +33 -0
- package/esm/maths/expressions/factors/ExpFactorVariable.js.map +1 -0
- package/esm/maths/expressions/internals.d.ts +12 -0
- package/esm/maths/expressions/internals.js +29 -0
- package/esm/maths/expressions/internals.js.map +1 -0
- package/esm/maths/shutingyard.d.ts +4 -1
- package/esm/maths/shutingyard.js +137 -21
- package/esm/maths/shutingyard.js.map +1 -1
- package/graph.svg +1033 -0
- package/package.json +1 -1
- package/src/maths/algebra/equation.ts +2 -2
- package/src/maths/algebra/polynom.ts +1 -0
- package/src/maths/algebra/study.ts +4 -4
- package/src/maths/coefficients/fraction.ts +111 -86
- package/src/maths/expressions/expression.ts +191 -0
- package/src/maths/expressions/expressionFactor.ts +138 -0
- package/src/maths/expressions/expressionMember.ts +114 -0
- package/src/maths/expressions/expressionOperators.ts +49 -0
- package/src/maths/expressions/expressionParser.ts +249 -0
- package/src/maths/expressions/factors/ExpFactor.ts +26 -0
- package/src/maths/expressions/factors/ExpFactorConstant.ts +56 -0
- package/src/maths/expressions/factors/ExpFactorExponential.ts +19 -0
- package/src/maths/expressions/factors/ExpFactorNumber.ts +44 -0
- package/src/maths/expressions/factors/ExpFactorPower.ts +24 -0
- package/src/maths/expressions/factors/ExpFactorTrigo.ts +44 -0
- package/src/maths/expressions/factors/ExpFactorVariable.ts +40 -0
- package/src/maths/expressions/internals.ts +14 -0
- package/src/maths/shutingyard.ts +156 -26
- package/tests/coefficients/fraction.test.ts +17 -0
- package/tests/expressions/expressions.test.ts +124 -0
- package/tests/shutingyard.test.ts +22 -0
- package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40_[Changes]/shelved.patch +0 -21
- package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40__Changes_.xml +0 -4
package/package.json
CHANGED
|
@@ -576,9 +576,9 @@ export class Equation {
|
|
|
576
576
|
} else {
|
|
577
577
|
// Must handle the case if the m1 monom is negative.
|
|
578
578
|
if ((this.isGreater() && m1.sign() === 1) || (!this.isGreater() && m1.sign() === -1)) {
|
|
579
|
-
s = `\\left${this.isAlsoEqual() ? '
|
|
579
|
+
s = `\\left${this.isAlsoEqual() ? '[' : ']'}${v.tex};+\\infty\\right[`;
|
|
580
580
|
} else {
|
|
581
|
-
s = `\\left
|
|
581
|
+
s = `\\left]-\\infty;${v.tex} \\right${this.isAlsoEqual() ? ']' : '['}`;
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
584
|
this._solutions = [{
|
|
@@ -259,6 +259,7 @@ export class Polynom {
|
|
|
259
259
|
this._factors = []
|
|
260
260
|
this.mark_as_dirty()
|
|
261
261
|
|
|
262
|
+
// TODO: allow to enter a liste of Fraction (a, b, c, ...) to make a polynom ax^n + bx^(n-1) + cx^(n-2) + ...
|
|
262
263
|
if (typeof inputStr === 'string') {
|
|
263
264
|
return this._parseString(inputStr, ...values)
|
|
264
265
|
} else if (
|
|
@@ -72,9 +72,9 @@ export interface ITableOfSigns {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export enum TABLE_OF_SIGNS {
|
|
75
|
-
|
|
76
|
-
GROWS,
|
|
77
|
-
VARIATIONS
|
|
75
|
+
SIGNS = "signs",
|
|
76
|
+
GROWS = "grows",
|
|
77
|
+
VARIATIONS = "variatins"
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|
|
@@ -323,7 +323,7 @@ export class Study {
|
|
|
323
323
|
|
|
324
324
|
makeSigns(): ITableOfSigns {
|
|
325
325
|
return {
|
|
326
|
-
type: TABLE_OF_SIGNS.
|
|
326
|
+
type: TABLE_OF_SIGNS.SIGNS,
|
|
327
327
|
fx: null,
|
|
328
328
|
factors: [],
|
|
329
329
|
zeroes: [],
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {Numeric} from "../numeric";
|
|
2
2
|
|
|
3
|
-
export type FractionParsingType = number|string|Fraction
|
|
3
|
+
export type FractionParsingType = number | string | Fraction
|
|
4
|
+
|
|
4
5
|
/**
|
|
5
6
|
* The fraction class make possible to handle
|
|
6
7
|
* TODO: Write the documentation correctly.
|
|
7
8
|
* \\(\frac{a}{b}\\) or \\[\frac{a}{b}\\] values.
|
|
8
9
|
*/
|
|
9
10
|
export class Fraction {
|
|
10
|
-
private _numerator: number;
|
|
11
11
|
private _denominator: number;
|
|
12
|
+
private _numerator: number;
|
|
12
13
|
|
|
13
14
|
constructor(value?: unknown, denominatorOrPeriodic?: number) {
|
|
14
15
|
this._numerator = 1;
|
|
@@ -47,24 +48,32 @@ export class Fraction {
|
|
|
47
48
|
|
|
48
49
|
// Display getter
|
|
49
50
|
get tex(): string {
|
|
50
|
-
if(this.isInfinity()){
|
|
51
|
-
return `${this.sign()===1?'+':'-'}\\infty`
|
|
51
|
+
if (this.isInfinity()) {
|
|
52
|
+
return `${this.sign() === 1 ? '+' : '-'}\\infty`
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
if (this.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if (this.isExact()) {
|
|
56
|
+
if (this._denominator === 1) {
|
|
57
|
+
return `${this._numerator}`;
|
|
58
|
+
} else if (this._numerator < 0) {
|
|
59
|
+
return `-\\frac{ ${-this._numerator} }{ ${this._denominator} }`;
|
|
60
|
+
} else {
|
|
61
|
+
return `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
|
|
62
|
+
}
|
|
58
63
|
} else {
|
|
59
|
-
return
|
|
64
|
+
return this.value.toFixed(3)
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
get display(): string {
|
|
64
|
-
if (this.
|
|
65
|
-
|
|
69
|
+
if (this.isExact()) {
|
|
70
|
+
if (this._denominator === 1) {
|
|
71
|
+
return `${this._numerator}`;
|
|
72
|
+
} else {
|
|
73
|
+
return `${this._numerator}/${this._denominator}`;
|
|
74
|
+
}
|
|
66
75
|
} else {
|
|
67
|
-
return
|
|
76
|
+
return this.value.toFixed(3)
|
|
68
77
|
}
|
|
69
78
|
}
|
|
70
79
|
|
|
@@ -76,12 +85,89 @@ export class Fraction {
|
|
|
76
85
|
get dfrac(): string {
|
|
77
86
|
return this.tex.replace('\\frac', '\\dfrac');
|
|
78
87
|
}
|
|
88
|
+
|
|
79
89
|
get tfrac(): string {
|
|
80
90
|
return this.tex.replace('\\frac', '\\tfrac')
|
|
81
91
|
}
|
|
82
92
|
|
|
93
|
+
static max = (...fractions: (Fraction | number)[]): Fraction => {
|
|
94
|
+
let M = new Fraction(fractions[0])
|
|
95
|
+
|
|
96
|
+
for (let m of fractions) {
|
|
97
|
+
let compare = new Fraction(m)
|
|
98
|
+
if (compare.greater(M)) {
|
|
99
|
+
M = compare.clone()
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return M
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static min = (...fractions: (Fraction | number)[]): Fraction => {
|
|
107
|
+
let M = new Fraction(fractions[0])
|
|
108
|
+
|
|
109
|
+
for (let m of fractions) {
|
|
110
|
+
let compare = new Fraction(m)
|
|
111
|
+
if (compare.lesser(M)) {
|
|
112
|
+
M = compare.clone()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return M
|
|
117
|
+
}
|
|
118
|
+
|
|
83
119
|
// ------------------------------------------
|
|
84
120
|
// Creation / parsing functions
|
|
121
|
+
|
|
122
|
+
static average = (...fractions: (Fraction | number)[]): Fraction => {
|
|
123
|
+
let M = new Fraction().zero()
|
|
124
|
+
|
|
125
|
+
for (let f of fractions) {
|
|
126
|
+
M.add(f)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
M.divide(fractions.length)
|
|
130
|
+
|
|
131
|
+
return M
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static unique = (fractions: Fraction[], sorted?: boolean): Fraction[] => {
|
|
135
|
+
// TODO: make sure it's wokring -> test !
|
|
136
|
+
let unique: { [Key: string]: boolean } = {},
|
|
137
|
+
distinct: Fraction[] = []
|
|
138
|
+
fractions.forEach(x => {
|
|
139
|
+
if (!unique[x.clone().reduce().tex]) {
|
|
140
|
+
distinct.push(x.clone())
|
|
141
|
+
unique[x.tex] = true
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
if (sorted) {
|
|
146
|
+
return Fraction.sort(distinct)
|
|
147
|
+
} else {
|
|
148
|
+
return distinct
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static sort = (fractions: Fraction[], reverse?: boolean): Fraction[] => {
|
|
153
|
+
// Todo make sure it's the correct order, not reverse -> make a test
|
|
154
|
+
let sorted = fractions.sort((a, b) => a.value - b.value)
|
|
155
|
+
|
|
156
|
+
if (reverse) {
|
|
157
|
+
sorted.reverse()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return sorted
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
isApproximative = (): boolean => {
|
|
164
|
+
return this._numerator.toString().length >= 15 && this._denominator.toString().length >= 15
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
isExact = (): boolean => {
|
|
168
|
+
return !this.isApproximative()
|
|
169
|
+
}
|
|
170
|
+
|
|
85
171
|
// ------------------------------------------
|
|
86
172
|
/**
|
|
87
173
|
* Parse the value to get the numerator and denominator
|
|
@@ -100,16 +186,15 @@ export class Fraction {
|
|
|
100
186
|
|
|
101
187
|
switch (typeof value) {
|
|
102
188
|
case "string":
|
|
103
|
-
// Split the
|
|
189
|
+
// Split the string value in two parts: Numerator/Denominator
|
|
104
190
|
S = value.split('/');
|
|
105
191
|
|
|
106
192
|
// Security checks
|
|
107
|
-
if (S.length > 2) throw "
|
|
108
|
-
if (S.map(x => x === '' || isNaN(Number(x))).includes(true)) throw "
|
|
109
|
-
|
|
193
|
+
if (S.length > 2) throw value + " has too many divide signs";
|
|
194
|
+
if (S.map(x => x === '' || isNaN(Number(x))).includes(true)) throw value + " is not a valid number"
|
|
110
195
|
|
|
111
196
|
if (S.length === 1) {
|
|
112
|
-
// No divide sign
|
|
197
|
+
// No divide sign - it's a number
|
|
113
198
|
return this.parse(+S[0]);
|
|
114
199
|
} else if (S.length === 2) {
|
|
115
200
|
// One divide signe
|
|
@@ -123,6 +208,7 @@ export class Fraction {
|
|
|
123
208
|
}
|
|
124
209
|
} else {
|
|
125
210
|
// More than one divide sign ?
|
|
211
|
+
// This is impossible
|
|
126
212
|
this._numerator = NaN;
|
|
127
213
|
this._denominator = 1;
|
|
128
214
|
}
|
|
@@ -164,6 +250,9 @@ export class Fraction {
|
|
|
164
250
|
return this;
|
|
165
251
|
};
|
|
166
252
|
|
|
253
|
+
// ------------------------------------------
|
|
254
|
+
// Mathematical operations
|
|
255
|
+
|
|
167
256
|
clone = (): Fraction => {
|
|
168
257
|
let F = new Fraction();
|
|
169
258
|
F.numerator = +this._numerator;
|
|
@@ -195,8 +284,6 @@ export class Fraction {
|
|
|
195
284
|
return this;
|
|
196
285
|
};
|
|
197
286
|
|
|
198
|
-
// ------------------------------------------
|
|
199
|
-
// Mathematical operations
|
|
200
287
|
// ------------------------------------------
|
|
201
288
|
opposed = (): Fraction => {
|
|
202
289
|
this._numerator = -this._numerator;
|
|
@@ -259,6 +346,7 @@ export class Fraction {
|
|
|
259
346
|
|
|
260
347
|
return this;
|
|
261
348
|
}
|
|
349
|
+
|
|
262
350
|
pow = (p: number | Fraction): Fraction => {
|
|
263
351
|
// TODO: Fraction.pow with a value different than a safe integer !
|
|
264
352
|
if (p instanceof Fraction) {
|
|
@@ -275,13 +363,13 @@ export class Fraction {
|
|
|
275
363
|
let controlNumerator = Math.floor(Math.pow(this._numerator, Math.abs(p))),
|
|
276
364
|
controlDenominator = Math.floor(Math.pow(this._denominator, Math.abs(p)))
|
|
277
365
|
|
|
278
|
-
if(controlNumerator ** Math.abs(p) === this._numerator
|
|
366
|
+
if (controlNumerator ** Math.abs(p) === this._numerator
|
|
279
367
|
&&
|
|
280
|
-
controlDenominator ** Math.abs(p) === this._denominator){
|
|
368
|
+
controlDenominator ** Math.abs(p) === this._denominator) {
|
|
281
369
|
|
|
282
370
|
this._numerator = this._numerator ** Math.abs(p);
|
|
283
371
|
this._denominator = this._denominator ** Math.abs(p);
|
|
284
|
-
}else{
|
|
372
|
+
} else {
|
|
285
373
|
this._numerator = this._numerator ** Math.abs(p);
|
|
286
374
|
this._denominator = this._denominator ** Math.abs(p);
|
|
287
375
|
}
|
|
@@ -320,72 +408,9 @@ export class Fraction {
|
|
|
320
408
|
return this;
|
|
321
409
|
};
|
|
322
410
|
|
|
323
|
-
|
|
324
|
-
static max = (...fractions: (Fraction | number)[]): Fraction => {
|
|
325
|
-
let M = new Fraction(fractions[0])
|
|
326
|
-
|
|
327
|
-
for (let m of fractions) {
|
|
328
|
-
let compare = new Fraction(m)
|
|
329
|
-
if (compare.greater(M)) {
|
|
330
|
-
M = compare.clone()
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return M
|
|
335
|
-
}
|
|
336
|
-
static min = (...fractions: (Fraction | number)[]): Fraction => {
|
|
337
|
-
let M = new Fraction(fractions[0])
|
|
338
|
-
|
|
339
|
-
for (let m of fractions) {
|
|
340
|
-
let compare = new Fraction(m)
|
|
341
|
-
if (compare.lesser(M)) {
|
|
342
|
-
M = compare.clone()
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return M
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
static average = (...fractions: (Fraction|number)[]): Fraction => {
|
|
350
|
-
let M = new Fraction().zero()
|
|
351
|
-
|
|
352
|
-
for(let f of fractions){
|
|
353
|
-
M.add(f)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
M.divide(fractions.length)
|
|
357
|
-
|
|
358
|
-
return M
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
static unique = (fractions: Fraction[], sorted?: boolean): Fraction[] => {
|
|
362
|
-
// TODO: make sure it's wokring -> test !
|
|
363
|
-
let unique:{[Key:string]:boolean} = {},
|
|
364
|
-
distinct: Fraction[] = []
|
|
365
|
-
fractions.forEach(x => {
|
|
366
|
-
if(!unique[x.clone().reduce().tex]){
|
|
367
|
-
distinct.push(x.clone())
|
|
368
|
-
unique[x.tex]=true
|
|
369
|
-
}
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
if(sorted) {
|
|
373
|
-
return Fraction.sort(distinct)
|
|
374
|
-
}else{
|
|
375
|
-
return distinct
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
static sort = (fractions: Fraction[], reverse?:boolean): Fraction[] => {
|
|
379
|
-
// Todo make sure it's the correct order, not reverse -> make a test
|
|
380
|
-
let sorted = fractions.sort((a, b)=>a.value-b.value)
|
|
381
|
-
|
|
382
|
-
if(reverse){sorted.reverse()}
|
|
383
|
-
|
|
384
|
-
return sorted
|
|
385
|
-
}
|
|
386
|
-
|
|
387
411
|
// ------------------------------------------
|
|
388
412
|
// Mathematical operations specific to fractions
|
|
413
|
+
|
|
389
414
|
// ------------------------------------------
|
|
390
415
|
reduce = (): Fraction => {
|
|
391
416
|
let g = Numeric.gcd(this._numerator, this._denominator);
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {ExpressionFactor, ExpressionMember} from "./internals";
|
|
2
|
+
|
|
3
|
+
export type ExpressionMemberType = { member: ExpressionMember, sign: number }
|
|
4
|
+
|
|
5
|
+
export class Expression {
|
|
6
|
+
private _members: ExpressionMemberType[]
|
|
7
|
+
|
|
8
|
+
constructor(...values: (ExpressionMember | ExpressionFactor | ExpressionMemberType)[]) {
|
|
9
|
+
this._members = []
|
|
10
|
+
this.addMembers(...values)
|
|
11
|
+
return this
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get tex(): string {
|
|
15
|
+
let tex:string = ""
|
|
16
|
+
for (let item of this._members) {
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
if (tex === "") {
|
|
20
|
+
tex = (item.sign === -1 ? "-" : "") + item.member.tex
|
|
21
|
+
} else {
|
|
22
|
+
tex += (item.sign === -1 ? "-" : "+") + item.member.tex
|
|
23
|
+
}
|
|
24
|
+
}catch{
|
|
25
|
+
console.log('Error while generating the TeX code for ', item.constructor.name)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return tex
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get members(): ExpressionMemberType[] {
|
|
32
|
+
return this._members;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set members(value: ExpressionMemberType[]) {
|
|
36
|
+
this._members = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
addMembers(...values: (ExpressionMemberType | ExpressionMember | ExpressionFactor)[]): Expression {
|
|
40
|
+
for (let item of values) {
|
|
41
|
+
if (item instanceof ExpressionMember) {
|
|
42
|
+
this._members.push({
|
|
43
|
+
member: item,
|
|
44
|
+
sign: 1
|
|
45
|
+
})
|
|
46
|
+
}else if (item instanceof ExpressionFactor){
|
|
47
|
+
this._members.push({
|
|
48
|
+
member: new ExpressionMember(item),
|
|
49
|
+
sign: 1
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this._members.push(item)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return this
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
add(value: Expression | ExpressionMember | ExpressionFactor) {
|
|
61
|
+
if (value instanceof Expression) {
|
|
62
|
+
this.members = this.members.concat(...value.members)
|
|
63
|
+
} else if (value instanceof ExpressionMember) {
|
|
64
|
+
this.members.push({
|
|
65
|
+
member: value,
|
|
66
|
+
sign: 1
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
} else if (value instanceof ExpressionFactor) {
|
|
70
|
+
this.members.push({
|
|
71
|
+
member: new ExpressionMember(value),
|
|
72
|
+
sign: 1
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return this
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
subtract(value: Expression | ExpressionMember | ExpressionFactor) {
|
|
80
|
+
|
|
81
|
+
if (value instanceof Expression) {
|
|
82
|
+
this.members = this.members.concat(
|
|
83
|
+
...value.members
|
|
84
|
+
.map(item => {
|
|
85
|
+
return {member: item.member, sign: -item.sign}
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
} else if (value instanceof ExpressionMember) {
|
|
90
|
+
this.members.push({
|
|
91
|
+
member: value,
|
|
92
|
+
sign: -1
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
} else if (value instanceof ExpressionFactor) {
|
|
96
|
+
this.members.push({
|
|
97
|
+
member: new ExpressionMember(value),
|
|
98
|
+
sign: -1
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return this
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
hasVariable(variable?: string): boolean {
|
|
107
|
+
|
|
108
|
+
if (variable === undefined) {
|
|
109
|
+
return !this.isNumeric()
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
for (let item of this._members) {
|
|
114
|
+
if (item.member.hasVariable(variable)) {
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// The variable hasn't been found !
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
isZero(): boolean {
|
|
124
|
+
// TODO: Must check if all the members has a value of zero
|
|
125
|
+
if (this._members.length === 0) {
|
|
126
|
+
return true
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (let item of this._members) {
|
|
130
|
+
if (item.member.isZero()) {
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
isNumeric(): boolean {
|
|
139
|
+
|
|
140
|
+
for (let item of this._members) {
|
|
141
|
+
if (!item.member.isNumeric()) {
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
isSingle(): Boolean {
|
|
151
|
+
if(this.members.length>1){
|
|
152
|
+
return false
|
|
153
|
+
}else if(this.members[0]?.member.factors.length>1){
|
|
154
|
+
return false
|
|
155
|
+
}else{
|
|
156
|
+
return true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
isFactor(): Boolean {
|
|
162
|
+
return this.members.length===1
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
structure(depth?: number): string {
|
|
167
|
+
let struct: string[] = [],
|
|
168
|
+
indent = "",
|
|
169
|
+
dftIndent = "\t"
|
|
170
|
+
|
|
171
|
+
if(depth===undefined){depth = 0}
|
|
172
|
+
for(let i=0;i<depth; i++){
|
|
173
|
+
indent += dftIndent
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
struct.push(`${indent}${this.constructor.name}: ${this.tex}`)
|
|
177
|
+
for(let item of this._members){
|
|
178
|
+
struct.push(`${indent}${dftIndent}${item.member.constructor.name}: ${item.member.tex}`)
|
|
179
|
+
for(let factor of item.member.factors){
|
|
180
|
+
struct.push(`${indent}${dftIndent}${dftIndent}${factor.constructor.name}: ${factor.tex}`)
|
|
181
|
+
if(factor.argument!==null){
|
|
182
|
+
struct.push(factor.argument.structure(depth+3))
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return struct.join('\n')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import {Expression} from "./internals";
|
|
2
|
+
|
|
3
|
+
export abstract class ExpressionFactor {
|
|
4
|
+
constructor(
|
|
5
|
+
private _argument: Expression,
|
|
6
|
+
private _power?: number,
|
|
7
|
+
private _root?: number,
|
|
8
|
+
private _inline?: boolean
|
|
9
|
+
) {
|
|
10
|
+
if (this._power === undefined) {
|
|
11
|
+
this._power = 1
|
|
12
|
+
}
|
|
13
|
+
if (this._root === undefined) {
|
|
14
|
+
this._root = 1
|
|
15
|
+
}
|
|
16
|
+
if (this._inline === undefined) {
|
|
17
|
+
this._inline = false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get inline(): boolean {
|
|
22
|
+
return this._inline;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
set inline(value: boolean) {
|
|
26
|
+
this._inline = value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get tex(): string {
|
|
30
|
+
return this.makeTeX()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get power(): number {
|
|
34
|
+
return this._power;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
set power(value: number) {
|
|
38
|
+
if (!Number.isSafeInteger(value)) {
|
|
39
|
+
throw `Power value (${value}) is not a safe integer`
|
|
40
|
+
}
|
|
41
|
+
this._power = value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get root(): number {
|
|
45
|
+
return this._root;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
set root(value: number) {
|
|
49
|
+
if (!Number.isSafeInteger(value)) {
|
|
50
|
+
throw `Root value (${value}) is not a safe integer`
|
|
51
|
+
}
|
|
52
|
+
this._root = value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get argument(): Expression {
|
|
56
|
+
return this._argument;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
set argument(value: Expression) {
|
|
60
|
+
this._argument = value;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
abstract makeTeX(numberOfFactors?: number, position?: number): string
|
|
64
|
+
|
|
65
|
+
abstract derivative(variable: string): Expression
|
|
66
|
+
|
|
67
|
+
abstract integrate(variable: string): Expression
|
|
68
|
+
|
|
69
|
+
hasVariable(variable?: string): boolean {
|
|
70
|
+
|
|
71
|
+
if (variable === undefined) {
|
|
72
|
+
return !this.isNumeric()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The argument is an Expression
|
|
76
|
+
if (this._argument instanceof Expression) {
|
|
77
|
+
return this._argument.hasVariable(variable)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return false
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
isNumeric(): boolean {
|
|
85
|
+
if (this._argument instanceof Expression) {
|
|
86
|
+
return this.isNumeric()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
hasRoot(): boolean {
|
|
93
|
+
return this.root > 1
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
hasPower(inline?: boolean): boolean {
|
|
97
|
+
if (inline === true) {
|
|
98
|
+
return !(this.power === 1)
|
|
99
|
+
} else {
|
|
100
|
+
return !(this.power === 1 || this.power === -1)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
texPowerAndRoot(tex: string): string {
|
|
106
|
+
return this.texPower(this.texRoot(tex))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
texPower(tex: string): string {
|
|
110
|
+
if (this.hasPower(this.inline)) {
|
|
111
|
+
return `${tex}^{ ${Math.abs(this.power)} }`
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return tex
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
wrapWithParentheses(tex: string): string {
|
|
118
|
+
return `\\left( ${tex} \\right)`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
texRoot(tex: string): string {
|
|
122
|
+
if (this.root === 2) {
|
|
123
|
+
return `\\sqrt{ ${tex} }`
|
|
124
|
+
} else if (this.root > 2) {
|
|
125
|
+
return `\\sqrt[${this.root}]{ ${tex} }`
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return tex
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
isZero(): Boolean {
|
|
132
|
+
if (this._argument instanceof Expression) {
|
|
133
|
+
return this._argument.isZero()
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return this._argument === 0
|
|
137
|
+
}
|
|
138
|
+
}
|