pimath 0.0.28 → 0.0.32

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 (96) hide show
  1. package/dev/pi.js +864 -487
  2. package/dev/pi.js.map +1 -1
  3. package/dist/pi.js +1 -1
  4. package/dist/pi.js.map +1 -1
  5. package/docs/assets/search.js +1 -1
  6. package/docs/classes/algebra.Equation.html +9 -9
  7. package/docs/classes/algebra.LinearSystem.html +1 -1
  8. package/docs/classes/algebra.Logicalset.html +2 -2
  9. package/docs/classes/algebra.Monom.html +42 -40
  10. package/docs/classes/algebra.Polynom.html +10 -10
  11. package/docs/classes/algebra.PolynomExpFactor.html +1 -0
  12. package/docs/classes/algebra.PolynomExpProduct.html +1 -0
  13. package/docs/classes/algebra.Rational.html +2 -2
  14. package/docs/classes/coefficients.Fraction.html +4 -4
  15. package/docs/classes/coefficients.Nthroot.html +1 -1
  16. package/docs/classes/geometry.Circle.html +2 -2
  17. package/docs/classes/geometry.Line.html +2 -2
  18. package/docs/classes/geometry.Point.html +1 -1
  19. package/docs/classes/geometry.Triangle.html +6 -6
  20. package/docs/classes/geometry.Vector.html +1 -1
  21. package/docs/classes/numeric.Numeric.html +5 -5
  22. package/docs/classes/shutingyard.Shutingyard.html +7 -8
  23. package/docs/enums/shutingyard.ShutingyardMode.html +1 -0
  24. package/docs/enums/shutingyard.ShutingyardType.html +1 -0
  25. package/docs/index.html +1 -1
  26. package/docs/interfaces/geometry.remarquableLines.html +1 -1
  27. package/docs/modules/algebra.html +1 -1
  28. package/docs/modules/coefficients.html +1 -1
  29. package/docs/modules/geometry.html +1 -1
  30. package/docs/modules/numeric.html +1 -1
  31. package/docs/modules/random.Random.html +1 -1
  32. package/docs/modules/random.html +1 -1
  33. package/docs/modules/shutingyard.html +1 -1
  34. package/docs/modules.html +1 -1
  35. package/esm/main.js +3 -1
  36. package/esm/main.js.map +1 -1
  37. package/esm/maths/algebra/equation.js +1 -1
  38. package/esm/maths/algebra/equation.js.map +1 -1
  39. package/esm/maths/algebra/index.d.ts +1 -0
  40. package/esm/maths/algebra/index.js +1 -0
  41. package/esm/maths/algebra/index.js.map +1 -1
  42. package/esm/maths/algebra/monom.d.ts +4 -1
  43. package/esm/maths/algebra/monom.js +52 -37
  44. package/esm/maths/algebra/monom.js.map +1 -1
  45. package/esm/maths/algebra/polynom.d.ts +19 -15
  46. package/esm/maths/algebra/polynom.js +242 -174
  47. package/esm/maths/algebra/polynom.js.map +1 -1
  48. package/esm/maths/coefficients/fraction.d.ts +3 -0
  49. package/esm/maths/coefficients/fraction.js +21 -8
  50. package/esm/maths/coefficients/fraction.js.map +1 -1
  51. package/esm/maths/{numexp.d.ts → expressions/numexp.d.ts} +3 -0
  52. package/esm/maths/{numexp.js → expressions/numexp.js} +46 -15
  53. package/esm/maths/expressions/numexp.js.map +1 -0
  54. package/esm/maths/expressions/polynomexp.bkp.d.ts +33 -0
  55. package/esm/maths/expressions/polynomexp.bkp.js +186 -0
  56. package/esm/maths/expressions/polynomexp.bkp.js.map +1 -0
  57. package/esm/maths/expressions/polynomexp.d.ts +52 -0
  58. package/esm/maths/expressions/polynomexp.js +233 -0
  59. package/esm/maths/expressions/polynomexp.js.map +1 -0
  60. package/esm/maths/geometry/line.d.ts +4 -2
  61. package/esm/maths/geometry/line.js +6 -2
  62. package/esm/maths/geometry/line.js.map +1 -1
  63. package/esm/maths/geometry/vector.js +7 -2
  64. package/esm/maths/geometry/vector.js.map +1 -1
  65. package/esm/maths/shutingyard.d.ts +7 -7
  66. package/esm/maths/shutingyard.js +5 -7
  67. package/esm/maths/shutingyard.js.map +1 -1
  68. package/package.json +1 -1
  69. package/{dev → public}/demo.css +0 -0
  70. package/{dev → public}/index.html +48 -14
  71. package/{dev → public}/playground.html +1 -1
  72. package/src/main.ts +13 -2
  73. package/src/maths/algebra/equation.ts +1 -1
  74. package/src/maths/algebra/index.ts +2 -1
  75. package/src/maths/algebra/monom.ts +71 -49
  76. package/src/maths/algebra/polynom.ts +432 -309
  77. package/src/maths/coefficients/fraction.ts +28 -11
  78. package/src/maths/{numexp.ts → expressions/numexp.ts} +42 -20
  79. package/src/maths/expressions/polynomexp.bkp.ts +223 -0
  80. package/src/maths/expressions/polynomexp.ts +309 -0
  81. package/src/maths/geometry/line.ts +7 -2
  82. package/src/maths/geometry/vector.ts +10 -2
  83. package/src/maths/shutingyard.ts +15 -64
  84. package/tests/algebra/monom.test.ts +12 -8
  85. package/tests/algebra/polynom.test.ts +28 -2
  86. package/tests/numexp.test.ts +34 -0
  87. package/tests/polynomexp.test.ts +15 -0
  88. package/tests/shutingyard.test.ts +4 -4
  89. package/tsconfig.json +0 -1
  90. package/esm/docs.d.ts +0 -6
  91. package/esm/docs.js +0 -7
  92. package/esm/docs.js.map +0 -1
  93. package/esm/maths/numexp.js.map +0 -1
  94. package/esm/maths/random/random.d.ts +0 -13
  95. package/esm/maths/random/random.js +0 -27
  96. package/esm/maths/random/random.js.map +0 -1
@@ -3,11 +3,12 @@
3
3
  */
4
4
 
5
5
  import {literalType, Monom} from './monom';
6
- import {Shutingyard} from '../shutingyard';
6
+ import {Shutingyard, ShutingyardType, Token} from '../shutingyard';
7
7
  import {Numeric} from '../numeric';
8
- import {Random, randomPolynomConfig} from "../random";
9
8
  import {Fraction} from "../coefficients";
9
+ import {log} from "util";
10
10
 
11
+ export type PolynomParsingType = string|Polynom|number|Fraction|Monom
11
12
  /**
12
13
  * Polynom class can handle polynoms, reorder, resolve, ...
13
14
  * ```
@@ -16,16 +17,13 @@ import {Fraction} from "../coefficients";
16
17
  */
17
18
  export class Polynom {
18
19
  private _rawString: string;
19
- private _monoms: Monom[];
20
- private _factors: Polynom[];
21
- private _texString: string;
22
20
 
23
21
  /**
24
22
  *
25
23
  * @param {string} polynomString (optional) Default polynom to parse on class creation
26
24
  * @param values
27
25
  */
28
- constructor(polynomString?: string, ...values: unknown[]) {
26
+ constructor(polynomString?: PolynomParsingType, ...values: unknown[]) {
29
27
  this._monoms = [];
30
28
  this._factors = [];
31
29
  if (polynomString !== undefined) {
@@ -34,8 +32,8 @@ export class Polynom {
34
32
  return this;
35
33
  }
36
34
 
37
- // ------------------------------------------
38
- // Getter and setter
35
+ private _monoms: Monom[];
36
+
39
37
  // ------------------------------------------
40
38
  get monoms() {
41
39
  return this._monoms;
@@ -45,6 +43,11 @@ export class Polynom {
45
43
  this._monoms = M;
46
44
  }
47
45
 
46
+ // ------------------------------------------
47
+ // Getter and setter
48
+
49
+ private _factors: Polynom[];
50
+
48
51
  get factors(): Polynom[] {
49
52
  return this._factors;
50
53
  }
@@ -53,6 +56,12 @@ export class Polynom {
53
56
  this._factors = value;
54
57
  }
55
58
 
59
+ private _texString: string;
60
+
61
+ get texString(): string {
62
+ return this._texString;
63
+ }
64
+
56
65
  get texFactors(): string {
57
66
  this.factorize()
58
67
 
@@ -67,10 +76,6 @@ export class Polynom {
67
76
  return tex;
68
77
  }
69
78
 
70
- get texString(): string {
71
- return this._texString;
72
- }
73
-
74
79
  get length() {
75
80
  // TODO: Must reduce the monoms list to remove the zero coefficient.
76
81
  return this._monoms.length;
@@ -115,47 +120,36 @@ export class Polynom {
115
120
  return this.variables.length;
116
121
  }
117
122
 
118
- private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean): string => {
119
- let P: string = '';
120
-
121
- for (const k of this._monoms) {
122
- if (k.coefficient.value === 0) {
123
- continue;
124
- }
125
-
126
- P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${(output === 'tex') ? k.tex : k.display}`;
127
- }
128
-
129
- if (wrapParentheses === true && this.length > 1) {
130
- if (output === 'tex') {
131
- P = `\\left( ${P} \\right)`;
132
- } else {
133
- P = `(${P})`;
134
- }
135
- }
136
-
137
- if (P === '') {
138
- P = '0';
139
- }
140
- return P;
141
- };
142
-
143
-
144
- // ------------------------------------------
145
- // Creation / parsing functions
146
123
  // ------------------------------------------
147
124
  /**
148
125
  * Parse a string to a polynom.
149
126
  * @param inputStr
150
127
  * @param values: as string, numbers or fractions
151
128
  */
152
- parse = (inputStr: string, ...values: unknown[]): Polynom => {
129
+ parse = (inputStr: PolynomParsingType, ...values: unknown[]): Polynom => {
130
+ // Reset the main variables.
131
+ this._monoms = []
132
+ this._factors = []
133
+
134
+ if(typeof inputStr === 'string') {
135
+ return this._parseString(inputStr, ...values)
136
+ }else if(typeof inputStr === 'number' || inputStr instanceof Fraction || inputStr instanceof Monom){
137
+ this._monoms.push(new Monom(inputStr))
138
+ }else if(inputStr instanceof Polynom){
139
+ for(const m of inputStr.monoms){
140
+ this._monoms.push(m.clone())
141
+ }
142
+ }
153
143
 
144
+ return this
145
+ };
146
+
147
+ private _parseString(inputStr: string, ...values:unknown[]): Polynom{
154
148
  if (values === undefined || values.length === 0) {
155
149
  inputStr = '' + inputStr;
156
150
  this._rawString = inputStr;
157
151
 
158
- // Parse the polynom using the shuting yard algorithm
152
+ // Parse the polynom using the shutting yard algorithm
159
153
  if (inputStr !== '' && !isNaN(Number(inputStr))) {
160
154
  this.empty();
161
155
  // It's a simple number.
@@ -201,52 +195,11 @@ export class Polynom {
201
195
  } else {
202
196
  return this.zero();
203
197
  }
198
+ }
204
199
 
205
- };
206
-
207
- /**
208
- * Main parse using a shutting yard class
209
- * @param inputStr
210
- */
211
- private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
212
- // Get the RPN array of the current expression
213
- const SY: Shutingyard = new Shutingyard().parse(inputStr);
214
- const rpn: { token: string, tokenType: string }[] = SY.rpn;
215
- let m1: Polynom;
216
- let m2: Polynom;
217
-
218
- let stack: Polynom[] = [],
219
- previousToken: string = null,
220
- tempPolynom
221
-
222
- for (const element of rpn) {
223
- if (element.tokenType === 'coefficient' || element.tokenType === 'variable') {
224
- tempPolynom = new Polynom().zero();
225
- tempPolynom.monoms = [new Monom(element.token)]
226
- stack.push(tempPolynom.clone())
227
- } else if (element.tokenType === 'operation') {
228
- m2 = (stack.pop()) || new Polynom().zero();
229
- m1 = (stack.pop()) || new Polynom().zero();
230
- switch (element.token) {
231
- case '+':
232
- stack.push(m1.add(m2))
233
- break;
234
- case '-':
235
- stack.push(m1.subtract(m2))
236
- break;
237
- case '*':
238
- stack.push(m1.multiply(m2))
239
- break;
240
- case '^':
241
- stack.push(m1.pow(+previousToken))
242
- }
243
- }
244
- previousToken = element.token;
245
- }
246
200
 
247
- this._monoms = stack[0].monoms;
248
- return this;
249
- }
201
+ // ------------------------------------------
202
+ // Creation / parsing functions
250
203
 
251
204
  /**
252
205
  * Clone the polynom
@@ -287,6 +240,29 @@ export class Polynom {
287
240
  return this;
288
241
  };
289
242
 
243
+ // ------------------------------------------
244
+ opposed = (): Polynom => {
245
+ this._monoms = this._monoms.map(m => m.opposed());
246
+ return this;
247
+ };
248
+
249
+ add = (...values: unknown[]): Polynom => {
250
+
251
+ for (let value of values) {
252
+ if (value instanceof Polynom) {
253
+ this._monoms = this._monoms.concat(value.monoms);
254
+ } else if (value instanceof Monom) {
255
+ this._monoms.push(value.clone());
256
+ } else if (Number.isSafeInteger(value)) {
257
+ this._monoms.push(new Monom(value.toString()));
258
+ } else {
259
+ this._monoms.push(new Monom(value));
260
+ }
261
+ }
262
+
263
+ return this.reduce();
264
+ };
265
+
290
266
  // // -----------------------------------------------
291
267
  // // Polynom generators and randomizers
292
268
  // // -----------------------------------------------
@@ -351,28 +327,6 @@ export class Polynom {
351
327
 
352
328
  // ------------------------------------------
353
329
  // Mathematical operations
354
- // ------------------------------------------
355
- opposed = (): Polynom => {
356
- this._monoms = this._monoms.map(m => m.opposed());
357
- return this;
358
- };
359
-
360
- add = (...values: unknown[]): Polynom => {
361
-
362
- for (let value of values) {
363
- if (value instanceof Polynom) {
364
- this._monoms = this._monoms.concat(value.monoms);
365
- } else if (value instanceof Monom) {
366
- this._monoms.push(value.clone());
367
- } else if (Number.isSafeInteger(value)) {
368
- this._monoms.push(new Monom(value.toString()));
369
- } else {
370
- this._monoms.push(new Monom(value));
371
- }
372
- }
373
-
374
- return this.reduce();
375
- };
376
330
 
377
331
  subtract = (...values: unknown[]): Polynom => {
378
332
 
@@ -398,7 +352,7 @@ export class Polynom {
398
352
  return this.multiplyByFraction(value);
399
353
  } else if (value instanceof Monom) {
400
354
  return this.multiplyByMonom(value);
401
- } else if (Number.isSafeInteger(value) && typeof value==='number') {
355
+ } else if (Number.isSafeInteger(value) && typeof value === 'number') {
402
356
  return this.multiplyByInteger(value);
403
357
  }
404
358
 
@@ -406,37 +360,6 @@ export class Polynom {
406
360
  return this;
407
361
  }
408
362
 
409
- private multiplyByPolynom = (P: Polynom): Polynom => {
410
- const M: Monom[] = [];
411
- for (const m1 of this._monoms) {
412
- for (const m2 of P.monoms) {
413
- M.push(Monom.xmultiply(m1, m2));
414
- }
415
- }
416
-
417
- this._monoms = M;
418
- return this.reduce();
419
- };
420
-
421
- private multiplyByFraction = (F: Fraction): Polynom => {
422
- for (const m of this._monoms) {
423
- m.coefficient.multiply(F);
424
- }
425
-
426
- return this.reduce();
427
- };
428
-
429
- private multiplyByInteger = (nb: number): Polynom => {
430
- return this.multiplyByFraction(new Fraction(nb));
431
- };
432
-
433
- private multiplyByMonom = (M: Monom): Polynom => {
434
- for (const m of this._monoms) {
435
- m.multiply(M)
436
- }
437
- return this.reduce();
438
- };
439
-
440
363
  /**
441
364
  * Divide the current polynom by another polynom.
442
365
  * @param P
@@ -476,31 +399,19 @@ export class Polynom {
476
399
  reminder.subtract(P.clone().multiply(newM));
477
400
  }
478
401
 
402
+ quotient.reduce()
403
+ reminder.reduce()
479
404
  return {quotient, reminder};
480
405
  };
481
406
 
482
407
  divide = (value: unknown): Polynom => {
483
408
  if (value instanceof Fraction) {
484
- this.divideByFraction(value);
485
- } else if (typeof value==='number' && Number.isSafeInteger(value)) {
409
+ return this.divideByFraction(value);
410
+ } else if (typeof value === 'number' && Number.isSafeInteger(value)) {
486
411
  return this.divideByInteger(value);
487
412
  }
488
- }
489
-
490
- private divideByInteger = (nb: number): Polynom => {
491
- const nbF = new Fraction(nb);
492
- for (const m of this._monoms) {
493
- m.coefficient.divide(nbF);
494
- }
495
- return this;
496
- };
497
413
 
498
- private divideByFraction = (F: Fraction): Polynom => {
499
- for (const m of this._monoms) {
500
- m.coefficient.divide(F);
501
- }
502
- return this;
503
- };
414
+ }
504
415
 
505
416
  pow = (nb: number): Polynom => {
506
417
  if (!Number.isSafeInteger(nb)) {
@@ -520,9 +431,6 @@ export class Polynom {
520
431
  return this.reduce();
521
432
  };
522
433
 
523
-
524
- // ------------------------------------------
525
- // Compare functions
526
434
  // ------------------------------------------
527
435
  /**
528
436
  * Compare the current coefficient with another coefficient
@@ -686,8 +594,11 @@ export class Polynom {
686
594
  // TODO: Maybe it's enough to just make this test !
687
595
  return polynomStringNormalized === P.reduce().reorder().display
688
596
  }
597
+
598
+
689
599
  // ------------------------------------------
690
- // Misc polynoms functions
600
+ // Compare functions
601
+
691
602
  // -------------------------------------
692
603
  reduce = (): Polynom => {
693
604
  for (let i = 0; i < this._monoms.length; i++) {
@@ -777,6 +688,7 @@ export class Polynom {
777
688
  //console.log('Evaluate polynom: ', monom.display, values, monom.evaluate(values).display);
778
689
  r.add(monom.evaluate(values));
779
690
  });
691
+
780
692
  return r;
781
693
  };
782
694
 
@@ -798,6 +710,8 @@ export class Polynom {
798
710
  }
799
711
  return dP
800
712
  }
713
+ // ------------------------------------------
714
+ // Misc polynoms functions
801
715
 
802
716
  integrate = (a: Fraction | number, b: Fraction | number, letter?: string): Fraction => {
803
717
  const primitive = this.primitive(letter)
@@ -813,8 +727,7 @@ export class Polynom {
813
727
 
814
728
  return primitive.evaluate(valuesB).subtract(primitive.evaluate(valuesA))
815
729
  }
816
- // ------------------------------------------
817
- // Polynoms factorization functions
730
+
818
731
  // -------------------------------------
819
732
  /**
820
733
  * Factorize a polynom and store the best results in factors.
@@ -886,151 +799,21 @@ export class Polynom {
886
799
  return factors;
887
800
  }
888
801
 
889
- private _factorize2ndDegree = (letter: string): Polynom[] => {
890
- let P1: Polynom, P2: Polynom,
891
- a, b, c, delta, x1, x2, factor;
892
-
893
- // One variable only
894
- if (this.numberOfVars === 1) {
895
- a = this.monomByDegree(2, letter).coefficient;
896
- b = this.monomByDegree(1, letter).coefficient;
897
- c = this.monomByDegree(0, letter).coefficient;
898
- delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
899
-
900
- if (delta.isZero()) {
901
- x1 = b.clone().opposed().divide(a.clone().multiply(2))
902
- P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
903
- P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
904
- factor = a.divide(x1.denominator).divide(x1.denominator);
802
+ // TODO: get zeroes for more than first degree and for more than natural degrees
803
+ getZeroes = (): (Fraction | boolean)[] => {
804
+ const Z: Fraction[] = [];
905
805
 
906
- if (!factor.isOne()) {
907
- // TODO: Update new Polynom to accept anything...
908
- return [new Polynom(factor.display), P1, P2]
806
+ switch (this.degree().value) {
807
+ case 0:
808
+ if (this._monoms[0].coefficient.value === 0) {
809
+ return [true];
909
810
  } else {
910
- return [P1, P2]
811
+ return [false];
911
812
  }
912
- } else if (delta.isPositive() && delta.isSquare()) {
913
- x1 = b.clone().opposed()
914
- .add(delta.clone().sqrt())
915
- .divide(a.clone().multiply(2))
916
- x2 = b.clone().opposed()
917
- .subtract(delta.clone().sqrt())
918
- .divide(a.clone().multiply(2))
919
-
920
- // (2x+5)(3x-2)
921
- // 6x^2+11x-10
922
- // a = 6, b = 11, c = -10
923
- // delta = 121-4*6*(-10) = 361= 19^2
924
- // x1 = (-11 + 19) / 12 = 8/12 = 2/3
925
- // x2 = (-11 - 19) / 12 = -30/12 = -5/2
926
- factor = a.divide(x1.denominator).divide(x2.denominator);
927
- if (factor.isOne()) {
928
- return [
929
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
930
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
931
- ]
932
- } else {
933
- return [
934
- new Polynom(factor.display),
935
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
936
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
937
- ]
938
-
939
- }
940
- } else {
941
- // No solution possible - return the complete value.
942
- return [this.clone()]
943
- }
944
- } else {
945
- // If multiple variables, only handle perfect squares...
946
- a = this.monomByDegree(2, letter);
947
- b = this.monomByDegree(1, letter);
948
- c = this.monomByDegree(0, letter);
949
-
950
-
951
- if (a.isLiteralSquare() && c.isLiteralSquare()) {
952
- // Check the middle item is same as...
953
- if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
954
- // Determine if the coefficient values matches.
955
-
956
- // Search 4 values (r, s, t, u) that matches:
957
- // (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
958
-
959
- let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
960
- let xFactors = xPolynom._factorize2ndDegree('x');
961
-
962
- let factors = [], xyzPolynom: Polynom;
963
-
964
- if (xFactors.length >= 2) {
965
- for (let p of xFactors) {
966
- if (p.degree().isZero()) {
967
- factors.push(p.clone())
968
- } else {
969
- xyzPolynom = p.clone();
970
- xyzPolynom.monoms[0].literal = a.literalSqrt
971
- xyzPolynom.monoms[1].literal = c.literalSqrt
972
- factors.push(xyzPolynom.clone())
973
- }
974
- }
975
- return factors
976
- }
977
- }
978
- }
979
-
980
- return [this.clone()]
981
- //
982
- // console.log(a.tex, b.tex, c.tex)
983
- // if (a.isSquare() && c.isSquare()) {
984
- // console.log('A C squares')
985
- // if (a.clone().sqrt().multiply(c.clone().sqrt()).multiplyByNumber(2).isSameAs(b)) {
986
- // console.log('HERE')
987
- // if (a.coefficient.sign() === b.coefficient.sign()) {
988
- // return []
989
- // }else{
990
- // return []
991
- // }
992
- // }
993
- // } else if(a.isLiteralSquare() && c.isLiteralSquare()) {
994
- // console.log('A C litteral SQUARES')
995
- // // Check that the middle element is the product of a and c.
996
- //
997
- // if(b.clone().pow(2).isSameAs(a.clone().multiply(c))){
998
- // console.log('SAME')
999
- //
1000
- // }else{
1001
- // console.log('NOT SAME')
1002
- // }
1003
- //
1004
- // return [this.clone()]
1005
- // } else {
1006
- // console.log('NOT SQUARES AT ALL !!!!')
1007
- // }
1008
-
1009
- }
1010
- }
1011
-
1012
- private _factorizeByGroups = (): Polynom[] => {
1013
- // TODO: Factorize by groups.
1014
- return [];
1015
- }
1016
- // ------------------------------------------
1017
- // Polynoms helpers functions
1018
- // -------------------------------------
1019
- // TODO: get zeroes for more than first degree and for more than natural degrees
1020
- getZeroes = (): (Fraction | boolean)[] => {
1021
- const Z: Fraction[] = [];
1022
-
1023
- switch (this.degree().value) {
1024
- case 0:
1025
- if (this._monoms[0].coefficient.value === 0) {
1026
- return [true];
1027
- } else {
1028
- return [false];
1029
- }
1030
- case 1:
1031
- // There is only one monoms,
1032
- if (this._monoms.length === 1) {
1033
- return [new Fraction().zero()];
813
+ case 1:
814
+ // There is only one monoms,
815
+ if (this._monoms.length === 1) {
816
+ return [new Fraction().zero()];
1034
817
  } else {
1035
818
  const P = this.clone().reduce().reorder();
1036
819
  return [P.monoms[1].coefficient.opposed().divide(P.monoms[0].coefficient)];
@@ -1085,9 +868,8 @@ export class Polynom {
1085
868
  return Z;
1086
869
  };
1087
870
 
1088
-
1089
871
  // TODO: analyse the next functions to determine if they are useful or not...
1090
- monomByDegree = (degree?: Fraction|number, letter?: string): Monom => {
872
+ monomByDegree = (degree?: Fraction | number, letter?: string): Monom => {
1091
873
  if (degree === undefined) {
1092
874
  // return the highest degree monom.
1093
875
  return this.monomByDegree(this.degree(letter), letter);
@@ -1105,7 +887,7 @@ export class Polynom {
1105
887
  return new Monom().zero();
1106
888
  };
1107
889
 
1108
- monomsByDegree = (degree?: number|Fraction, letter?: string): Monom[] => {
890
+ monomsByDegree = (degree?: number | Fraction, letter?: string): Monom[] => {
1109
891
  if (degree === undefined) {
1110
892
  // return the highest degree monom.
1111
893
  return this.monomsByDegree(this.degree(letter));
@@ -1137,7 +919,6 @@ export class Polynom {
1137
919
  return new Monom().zero();
1138
920
  };
1139
921
 
1140
-
1141
922
  // Next functions are used for for commonMonom, which is used in the factorize method.
1142
923
  getDenominators = (): number[] => {
1143
924
  const denominators: number[] = [];
@@ -1158,6 +939,8 @@ export class Polynom {
1158
939
  lcmDenominator = (): number => {
1159
940
  return Numeric.lcm(...this.getDenominators());
1160
941
  };
942
+ // ------------------------------------------
943
+ // Polynoms factorization functions
1161
944
 
1162
945
  gcdDenominator = (): number => {
1163
946
  return Numeric.gcd(...this.getDenominators());
@@ -1170,6 +953,9 @@ export class Polynom {
1170
953
  gcdNumerator = (): number => {
1171
954
  return Numeric.gcd(...this.getNumerators());
1172
955
  };
956
+ // ------------------------------------------
957
+ // Polynoms helpers functions
958
+ // -------------------------------------
1173
959
 
1174
960
  commonMonom = (): Monom => {
1175
961
  let M = new Monom().one(), numerator: number, denominator: number, degree = this.degree();
@@ -1190,4 +976,341 @@ export class Polynom {
1190
976
  }
1191
977
  return M;
1192
978
  }
979
+
980
+ private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean): string => {
981
+ let P: string = '';
982
+
983
+ for (const k of this._monoms) {
984
+ if (k.coefficient.value === 0) {
985
+ continue;
986
+ }
987
+
988
+ P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${(output === 'tex') ? k.tex : k.display}`;
989
+ }
990
+
991
+ if (wrapParentheses === true && this.length > 1) {
992
+ if (output === 'tex') {
993
+ P = `\\left( ${P} \\right)`;
994
+ } else {
995
+ P = `(${P})`;
996
+ }
997
+ }
998
+
999
+ if (P === '') {
1000
+ P = '0';
1001
+ }
1002
+ return P;
1003
+ };
1004
+
1005
+
1006
+ static addToken = (stack: Polynom[], element: Token): void => {
1007
+
1008
+ switch(element.tokenType){
1009
+ case ShutingyardType.COEFFICIENT:
1010
+ stack.push(new Polynom( element.token ))
1011
+ break
1012
+
1013
+ case ShutingyardType.VARIABLE:
1014
+ stack.push(new Polynom().add(new Monom(element.token)))
1015
+ break
1016
+
1017
+ case ShutingyardType.CONSTANT:
1018
+ // TODO: add constant support to Polynom parsing.
1019
+ console.log('Actually, not supported - will be added later !')
1020
+ break
1021
+
1022
+ case ShutingyardType.OPERATION:
1023
+ if(stack.length>=2){
1024
+ const b = stack.pop(),
1025
+ a = stack.pop()
1026
+
1027
+ if(element.token === '+'){
1028
+ stack.push(a.add(b))
1029
+ }else if(element.token === '-'){
1030
+ stack.push(a.subtract(b))
1031
+ }else if(element.token === '*'){
1032
+ stack.push(a.multiply(b))
1033
+ }else if(element.token === '/'){
1034
+ if(b.degree().isStrictlyPositive()){
1035
+ console.log('divide by a polynom -> should create a rational polynom !')
1036
+ }else {
1037
+ stack.push(a.divide(b.monoms[0].coefficient))
1038
+
1039
+ }
1040
+ }else if(element.token === '^'){
1041
+ if(b.degree().isStrictlyPositive()) {
1042
+ console.error('Cannot elevate a polynom with another polynom !')
1043
+ }else {
1044
+ if(b.monoms[0].coefficient.isRelative()) {
1045
+ // Integer power
1046
+ stack.push(a.pow(b.monoms[0].coefficient.value))
1047
+ }else{
1048
+ // Only allow power if the previous polynom is only a monom, without coefficient.
1049
+ if(a.monoms.length===1 && a.monoms[0].coefficient.isOne()){
1050
+ for (let letter in a.monoms[0].literal) {
1051
+ a.monoms[0].literal[letter].multiply(b.monoms[0].coefficient)
1052
+ }
1053
+ stack.push(a)
1054
+ }else {
1055
+ console.error('Cannot have power with fraction')
1056
+ }
1057
+ }
1058
+ }
1059
+ }
1060
+ }else{
1061
+ console.log('Stack size: ', stack.length)
1062
+ if(element.token === '-'){
1063
+ stack.push(stack.pop().opposed())
1064
+ }else{
1065
+ console.log('While parsing, cannot apply ', element.token, 'to', stack[0].tex)
1066
+ }
1067
+ }
1068
+ break
1069
+
1070
+ case ShutingyardType.MONOM:
1071
+ // Should never appear.
1072
+ console.error('The monom token should not appear here')
1073
+ break;
1074
+
1075
+ case ShutingyardType.FUNCTION:
1076
+ // Should never appear.
1077
+ console.log('The function token should not appear here - might be introduced later.')
1078
+ break;
1079
+ }
1080
+ }
1081
+ /**
1082
+ * Main parse using a shutting yard class
1083
+ * @param inputStr
1084
+ */
1085
+ private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
1086
+ // Get the RPN array of the current expression
1087
+ const SY: Shutingyard = new Shutingyard().parse(inputStr);
1088
+ const rpn: { token: string, tokenType: string }[] = SY.rpn;
1089
+
1090
+ // New version for reducing shuting yard.
1091
+ this.zero()
1092
+
1093
+ let stack: Polynom[] = [],
1094
+ monom: Monom = new Monom()
1095
+
1096
+ // Loop through the
1097
+ for (const element of rpn) {
1098
+ Polynom.addToken(stack, element);
1099
+ }
1100
+
1101
+ if (stack.length === 1) {
1102
+ this.add(stack[0])
1103
+ }
1104
+
1105
+ return this
1106
+ /**
1107
+ let m1: Polynom;
1108
+ let m2: Polynom;
1109
+
1110
+ let stack: Polynom[] = [],
1111
+ previousToken: string = null,
1112
+ tempPolynom
1113
+
1114
+ for (const element of rpn) {
1115
+ if (element.tokenType === 'coefficient' || element.tokenType === 'variable') {
1116
+ tempPolynom = new Polynom().zero();
1117
+ tempPolynom.monoms = [new Monom(element.token)]
1118
+ stack.push(tempPolynom.clone())
1119
+ } else if (element.tokenType === 'operation') {
1120
+ m2 = (stack.pop()) || new Polynom().zero();
1121
+ m1 = (stack.pop()) || new Polynom().zero();
1122
+ switch (element.token) {
1123
+ case '+':
1124
+ stack.push(m1.add(m2))
1125
+ break;
1126
+ case '-':
1127
+ stack.push(m1.subtract(m2))
1128
+ break;
1129
+ case '*':
1130
+ stack.push(m1.multiply(m2))
1131
+ break;
1132
+ case '^':
1133
+ stack.push(m1.pow(+previousToken))
1134
+ }
1135
+ }
1136
+ previousToken = element.token;
1137
+ }
1138
+
1139
+ this._monoms = stack[0].monoms;
1140
+ return this;*/
1141
+ }
1142
+
1143
+ private multiplyByPolynom = (P: Polynom): Polynom => {
1144
+ const M: Monom[] = [];
1145
+ for (const m1 of this._monoms) {
1146
+ for (const m2 of P.monoms) {
1147
+ M.push(Monom.xmultiply(m1, m2));
1148
+ }
1149
+ }
1150
+
1151
+ this._monoms = M;
1152
+ return this.reduce();
1153
+ };
1154
+
1155
+ private multiplyByFraction = (F: Fraction): Polynom => {
1156
+ for (const m of this._monoms) {
1157
+ m.coefficient.multiply(F);
1158
+ }
1159
+
1160
+ return this.reduce();
1161
+ };
1162
+
1163
+ private multiplyByInteger = (nb: number): Polynom => {
1164
+ return this.multiplyByFraction(new Fraction(nb));
1165
+ };
1166
+
1167
+ private multiplyByMonom = (M: Monom): Polynom => {
1168
+ for (const m of this._monoms) {
1169
+ m.multiply(M)
1170
+ }
1171
+ return this.reduce();
1172
+ };
1173
+
1174
+ private divideByInteger = (nb: number): Polynom => {
1175
+ const nbF = new Fraction(nb);
1176
+ for (const m of this._monoms) {
1177
+ m.coefficient.divide(nbF);
1178
+ }
1179
+ return this;
1180
+ };
1181
+
1182
+ private divideByFraction = (F: Fraction): Polynom => {
1183
+ for (const m of this._monoms) {
1184
+ m.coefficient.divide(F);
1185
+ }
1186
+ return this;
1187
+ };
1188
+
1189
+ private _factorize2ndDegree = (letter: string): Polynom[] => {
1190
+ let P1: Polynom, P2: Polynom,
1191
+ a, b, c, delta, x1, x2, factor;
1192
+
1193
+ // One variable only
1194
+ if (this.numberOfVars === 1) {
1195
+ a = this.monomByDegree(2, letter).coefficient;
1196
+ b = this.monomByDegree(1, letter).coefficient;
1197
+ c = this.monomByDegree(0, letter).coefficient;
1198
+ delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
1199
+
1200
+ if (delta.isZero()) {
1201
+ x1 = b.clone().opposed().divide(a.clone().multiply(2))
1202
+ P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
1203
+ P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
1204
+ factor = a.divide(x1.denominator).divide(x1.denominator);
1205
+
1206
+ if (!factor.isOne()) {
1207
+ // TODO: Update new Polynom to accept anything...
1208
+ return [new Polynom(factor.display), P1, P2]
1209
+ } else {
1210
+ return [P1, P2]
1211
+ }
1212
+ } else if (delta.isPositive() && delta.isSquare()) {
1213
+ x1 = b.clone().opposed()
1214
+ .add(delta.clone().sqrt())
1215
+ .divide(a.clone().multiply(2))
1216
+ x2 = b.clone().opposed()
1217
+ .subtract(delta.clone().sqrt())
1218
+ .divide(a.clone().multiply(2))
1219
+
1220
+ // (2x+5)(3x-2)
1221
+ // 6x^2+11x-10
1222
+ // a = 6, b = 11, c = -10
1223
+ // delta = 121-4*6*(-10) = 361= 19^2
1224
+ // x1 = (-11 + 19) / 12 = 8/12 = 2/3
1225
+ // x2 = (-11 - 19) / 12 = -30/12 = -5/2
1226
+ factor = a.divide(x1.denominator).divide(x2.denominator);
1227
+ if (factor.isOne()) {
1228
+ return [
1229
+ new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1230
+ new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1231
+ ]
1232
+ } else {
1233
+ return [
1234
+ new Polynom(factor.display),
1235
+ new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1236
+ new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1237
+ ]
1238
+
1239
+ }
1240
+ } else {
1241
+ // No solution possible - return the complete value.
1242
+ return [this.clone()]
1243
+ }
1244
+ } else {
1245
+ // If multiple variables, only handle perfect squares...
1246
+ a = this.monomByDegree(2, letter);
1247
+ b = this.monomByDegree(1, letter);
1248
+ c = this.monomByDegree(0, letter);
1249
+
1250
+
1251
+ if (a.isLiteralSquare() && c.isLiteralSquare()) {
1252
+ // Check the middle item is same as...
1253
+ if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
1254
+ // Determine if the coefficient values matches.
1255
+
1256
+ // Search 4 values (r, s, t, u) that matches:
1257
+ // (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
1258
+
1259
+ let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
1260
+ let xFactors = xPolynom._factorize2ndDegree('x');
1261
+
1262
+ let factors = [], xyzPolynom: Polynom;
1263
+
1264
+ if (xFactors.length >= 2) {
1265
+ for (let p of xFactors) {
1266
+ if (p.degree().isZero()) {
1267
+ factors.push(p.clone())
1268
+ } else {
1269
+ xyzPolynom = p.clone();
1270
+ xyzPolynom.monoms[0].literal = a.literalSqrt
1271
+ xyzPolynom.monoms[1].literal = c.literalSqrt
1272
+ factors.push(xyzPolynom.clone())
1273
+ }
1274
+ }
1275
+ return factors
1276
+ }
1277
+ }
1278
+ }
1279
+
1280
+ return [this.clone()]
1281
+ //
1282
+ // console.log(a.tex, b.tex, c.tex)
1283
+ // if (a.isSquare() && c.isSquare()) {
1284
+ // console.log('A C squares')
1285
+ // if (a.clone().sqrt().multiply(c.clone().sqrt()).multiplyByNumber(2).isSameAs(b)) {
1286
+ // console.log('HERE')
1287
+ // if (a.coefficient.sign() === b.coefficient.sign()) {
1288
+ // return []
1289
+ // }else{
1290
+ // return []
1291
+ // }
1292
+ // }
1293
+ // } else if(a.isLiteralSquare() && c.isLiteralSquare()) {
1294
+ // console.log('A C litteral SQUARES')
1295
+ // // Check that the middle element is the product of a and c.
1296
+ //
1297
+ // if(b.clone().pow(2).isSameAs(a.clone().multiply(c))){
1298
+ // console.log('SAME')
1299
+ //
1300
+ // }else{
1301
+ // console.log('NOT SAME')
1302
+ // }
1303
+ //
1304
+ // return [this.clone()]
1305
+ // } else {
1306
+ // console.log('NOT SQUARES AT ALL !!!!')
1307
+ // }
1308
+
1309
+ }
1310
+ }
1311
+
1312
+ private _factorizeByGroups = (): Polynom[] => {
1313
+ // TODO: Factorize by groups.
1314
+ return [];
1315
+ }
1193
1316
  }