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.
Files changed (111) hide show
  1. package/.eslintrc.js +23 -23
  2. package/dist/pi.js +178 -44
  3. package/dist/pi.js.map +1 -1
  4. package/dist/pi.min.js +1 -1
  5. package/dist/pi.min.js.map +1 -1
  6. package/docs/assets/highlight.css +78 -78
  7. package/docs/assets/main.js +52 -52
  8. package/docs/assets/style.css +1413 -1413
  9. package/docs/classes/Logicalset.Logicalset-1.html +4 -4
  10. package/docs/classes/Polynom.Rational.html +3 -3
  11. package/docs/classes/algebra_equation.Equation.html +25 -25
  12. package/docs/classes/algebra_monom.Monom.html +113 -113
  13. package/docs/classes/algebra_polynom.Polynom.html +29 -29
  14. package/docs/classes/coefficients_fraction.Fraction.html +18 -18
  15. package/docs/classes/coefficients_nthroot.NthRoot.html +2 -2
  16. package/docs/classes/geometry_circle.Circle.html +2 -2
  17. package/docs/classes/geometry_line.Line.html +2 -2
  18. package/docs/classes/geometry_triangle.Triangle.html +16 -16
  19. package/docs/classes/numeric.Numeric.html +13 -13
  20. package/docs/classes/shutingyard.Shutingyard.html +17 -17
  21. package/docs/index.html +10 -10
  22. package/docs/interfaces/algebra_equation.ISolution.html +2 -2
  23. package/docs/modules/Logicalset.html +2 -2
  24. package/docs/modules/Polynom.html +2 -2
  25. package/docs/modules/Vector.html +2 -2
  26. package/esm/maths/algebra/equation.js +2 -2
  27. package/esm/maths/algebra/equation.js.map +1 -1
  28. package/esm/maths/algebra/polynom.d.ts +4 -5
  29. package/esm/maths/algebra/polynom.js +2 -2
  30. package/esm/maths/algebra/polynom.js.map +1 -1
  31. package/esm/maths/algebra/rational.d.ts +8 -10
  32. package/esm/maths/algebra/rational.js +11 -6
  33. package/esm/maths/algebra/study/rationalStudy.d.ts +1 -2
  34. package/esm/maths/algebra/study/rationalStudy.js +14 -14
  35. package/esm/maths/algebra/study/rationalStudy.js.map +1 -1
  36. package/esm/maths/algebra/study.d.ts +9 -22
  37. package/esm/maths/algebra/study.js +33 -23
  38. package/esm/maths/algebra/study.js.map +1 -1
  39. package/esm/maths/coefficients/fraction.d.ts +8 -6
  40. package/esm/maths/coefficients/fraction.js +34 -17
  41. package/esm/maths/coefficients/fraction.js.map +1 -1
  42. package/esm/maths/expressions/expression.d.ts +21 -0
  43. package/esm/maths/expressions/expression.js +161 -0
  44. package/esm/maths/expressions/expression.js.map +1 -0
  45. package/esm/maths/expressions/expressionFactor.d.ts +29 -0
  46. package/esm/maths/expressions/expressionFactor.js +109 -0
  47. package/esm/maths/expressions/expressionFactor.js.map +1 -0
  48. package/esm/maths/expressions/expressionMember.d.ts +16 -0
  49. package/esm/maths/expressions/expressionMember.js +90 -0
  50. package/esm/maths/expressions/expressionMember.js.map +1 -0
  51. package/esm/maths/expressions/expressionOperators.d.ts +8 -0
  52. package/esm/maths/expressions/expressionOperators.js +42 -0
  53. package/esm/maths/expressions/expressionOperators.js.map +1 -0
  54. package/esm/maths/expressions/expressionParser.d.ts +12 -0
  55. package/esm/maths/expressions/expressionParser.js +219 -0
  56. package/esm/maths/expressions/expressionParser.js.map +1 -0
  57. package/esm/maths/expressions/factors/ExpFactor.d.ts +7 -0
  58. package/esm/maths/expressions/factors/ExpFactor.js +22 -0
  59. package/esm/maths/expressions/factors/ExpFactor.js.map +1 -0
  60. package/esm/maths/expressions/factors/ExpFactorConstant.d.ts +13 -0
  61. package/esm/maths/expressions/factors/ExpFactorConstant.js +49 -0
  62. package/esm/maths/expressions/factors/ExpFactorConstant.js.map +1 -0
  63. package/esm/maths/expressions/factors/ExpFactorExponential.d.ts +7 -0
  64. package/esm/maths/expressions/factors/ExpFactorExponential.js +18 -0
  65. package/esm/maths/expressions/factors/ExpFactorExponential.js.map +1 -0
  66. package/esm/maths/expressions/factors/ExpFactorNumber.d.ts +13 -0
  67. package/esm/maths/expressions/factors/ExpFactorNumber.js +36 -0
  68. package/esm/maths/expressions/factors/ExpFactorNumber.js.map +1 -0
  69. package/esm/maths/expressions/factors/ExpFactorPower.d.ts +9 -0
  70. package/esm/maths/expressions/factors/ExpFactorPower.js +22 -0
  71. package/esm/maths/expressions/factors/ExpFactorPower.js.map +1 -0
  72. package/esm/maths/expressions/factors/ExpFactorSin.d.ts +7 -0
  73. package/esm/maths/expressions/factors/ExpFactorSin.js +22 -0
  74. package/esm/maths/expressions/factors/ExpFactorSin.js.map +1 -0
  75. package/esm/maths/expressions/factors/ExpFactorTrigo.d.ts +19 -0
  76. package/esm/maths/expressions/factors/ExpFactorTrigo.js +40 -0
  77. package/esm/maths/expressions/factors/ExpFactorTrigo.js.map +1 -0
  78. package/esm/maths/expressions/factors/ExpFactorVariable.d.ts +12 -0
  79. package/esm/maths/expressions/factors/ExpFactorVariable.js +33 -0
  80. package/esm/maths/expressions/factors/ExpFactorVariable.js.map +1 -0
  81. package/esm/maths/expressions/internals.d.ts +12 -0
  82. package/esm/maths/expressions/internals.js +29 -0
  83. package/esm/maths/expressions/internals.js.map +1 -0
  84. package/esm/maths/shutingyard.d.ts +4 -1
  85. package/esm/maths/shutingyard.js +137 -21
  86. package/esm/maths/shutingyard.js.map +1 -1
  87. package/graph.svg +1033 -0
  88. package/package.json +1 -1
  89. package/src/maths/algebra/equation.ts +2 -2
  90. package/src/maths/algebra/polynom.ts +1 -0
  91. package/src/maths/algebra/study.ts +4 -4
  92. package/src/maths/coefficients/fraction.ts +111 -86
  93. package/src/maths/expressions/expression.ts +191 -0
  94. package/src/maths/expressions/expressionFactor.ts +138 -0
  95. package/src/maths/expressions/expressionMember.ts +114 -0
  96. package/src/maths/expressions/expressionOperators.ts +49 -0
  97. package/src/maths/expressions/expressionParser.ts +249 -0
  98. package/src/maths/expressions/factors/ExpFactor.ts +26 -0
  99. package/src/maths/expressions/factors/ExpFactorConstant.ts +56 -0
  100. package/src/maths/expressions/factors/ExpFactorExponential.ts +19 -0
  101. package/src/maths/expressions/factors/ExpFactorNumber.ts +44 -0
  102. package/src/maths/expressions/factors/ExpFactorPower.ts +24 -0
  103. package/src/maths/expressions/factors/ExpFactorTrigo.ts +44 -0
  104. package/src/maths/expressions/factors/ExpFactorVariable.ts +40 -0
  105. package/src/maths/expressions/internals.ts +14 -0
  106. package/src/maths/shutingyard.ts +156 -26
  107. package/tests/coefficients/fraction.test.ts +17 -0
  108. package/tests/expressions/expressions.test.ts +124 -0
  109. package/tests/shutingyard.test.ts +22 -0
  110. package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40_[Changes]/shelved.patch +0 -21
  111. package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40__Changes_.xml +0 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pimath",
3
- "version": "0.0.66",
3
+ "version": "0.0.69",
4
4
  "description": "A math library for teacher :)",
5
5
  "scripts": {
6
6
  "test": "mocha -r ts-node/register 'tests/**/*.test.ts'",
@@ -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() ? '\\[' : '\\]'}${v};+\\infty\\right\\[`;
579
+ s = `\\left${this.isAlsoEqual() ? '[' : ']'}${v.tex};+\\infty\\right[`;
580
580
  } else {
581
- s = `\\left\\]-\\infty;${v} \\right\\${this.isAlsoEqual() ? '\\]' : '\\['}`;
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
- DEFAULT,
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.DEFAULT,
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._denominator === 1) {
55
- return `${this._numerator}`;
56
- } else if (this._numerator < 0) {
57
- return `-\\frac{ ${-this._numerator} }{ ${this._denominator} }`;
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 `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
64
+ return this.value.toFixed(3)
60
65
  }
61
66
  }
62
67
 
63
68
  get display(): string {
64
- if (this._denominator === 1) {
65
- return `${this._numerator}`;
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 `${this._numerator}/${this._denominator}`;
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 sting value in two parts: Numerator/Denominator
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 "Two many divide signs";
108
- if (S.map(x => x === '' || isNaN(Number(x))).includes(true)) throw "Not a number"
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
+ }