pimath 0.0.64 → 0.0.67

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 (113) hide show
  1. package/.eslintrc.js +23 -23
  2. package/dist/pi.js +236 -56
  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 +9 -5
  33. package/esm/maths/algebra/study/rationalStudy.d.ts +1 -2
  34. package/esm/maths/algebra/study/rationalStudy.js +32 -20
  35. package/esm/maths/algebra/study/rationalStudy.js.map +1 -1
  36. package/esm/maths/algebra/study.d.ts +16 -24
  37. package/esm/maths/algebra/study.js +65 -24
  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/rationalStudy.ts +26 -12
  92. package/src/maths/algebra/study.ts +48 -5
  93. package/src/maths/coefficients/fraction.ts +111 -86
  94. package/src/maths/expressions/expression.ts +191 -0
  95. package/src/maths/expressions/expressionFactor.ts +138 -0
  96. package/src/maths/expressions/expressionMember.ts +114 -0
  97. package/src/maths/expressions/expressionOperators.ts +49 -0
  98. package/src/maths/expressions/expressionParser.ts +249 -0
  99. package/src/maths/expressions/factors/ExpFactor.ts +26 -0
  100. package/src/maths/expressions/factors/ExpFactorConstant.ts +56 -0
  101. package/src/maths/expressions/factors/ExpFactorExponential.ts +19 -0
  102. package/src/maths/expressions/factors/ExpFactorNumber.ts +44 -0
  103. package/src/maths/expressions/factors/ExpFactorPower.ts +24 -0
  104. package/src/maths/expressions/factors/ExpFactorTrigo.ts +44 -0
  105. package/src/maths/expressions/factors/ExpFactorVariable.ts +40 -0
  106. package/src/maths/expressions/internals.ts +14 -0
  107. package/src/maths/shutingyard.ts +156 -26
  108. package/tests/algebra/study.test.ts +29 -4
  109. package/tests/coefficients/fraction.test.ts +17 -0
  110. package/tests/expressions/expressions.test.ts +124 -0
  111. package/tests/shutingyard.test.ts +22 -0
  112. package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40_[Changes]/shelved.patch +0 -21
  113. package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40__Changes_.xml +0 -4
package/.eslintrc.js CHANGED
@@ -1,24 +1,24 @@
1
- module.exports = {
2
- "env": {
3
- "browser": true,
4
- "es6": true
5
- },
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/eslint-recommended"
9
- ],
10
- "globals": {
11
- "Atomics": "readonly",
12
- "SharedArrayBuffer": "readonly"
13
- },
14
- "parser": "@typescript-eslint/parser",
15
- "parserOptions": {
16
- "ecmaVersion": 2018,
17
- "sourceType": "module"
18
- },
19
- "plugins": [
20
- "@typescript-eslint"
21
- ],
22
- "rules": {
23
- }
1
+ module.exports = {
2
+ "env": {
3
+ "browser": true,
4
+ "es6": true
5
+ },
6
+ "extends": [
7
+ "eslint:recommended",
8
+ "plugin:@typescript-eslint/eslint-recommended"
9
+ ],
10
+ "globals": {
11
+ "Atomics": "readonly",
12
+ "SharedArrayBuffer": "readonly"
13
+ },
14
+ "parser": "@typescript-eslint/parser",
15
+ "parserOptions": {
16
+ "ecmaVersion": 2018,
17
+ "sourceType": "module"
18
+ },
19
+ "plugins": [
20
+ "@typescript-eslint"
21
+ ],
22
+ "rules": {
23
+ }
24
24
  };
package/dist/pi.js CHANGED
@@ -434,10 +434,10 @@ class Equation {
434
434
  else {
435
435
  // Must handle the case if the m1 monom is negative.
436
436
  if ((this.isGreater() && m1.sign() === 1) || (!this.isGreater() && m1.sign() === -1)) {
437
- s = `\\left${this.isAlsoEqual() ? '\\[' : '\\]'}${v};+\\infty\\right\\[`;
437
+ s = `\\left${this.isAlsoEqual() ? '\\[' : '\\]'}${v.tex};+\\infty\\right\\[`;
438
438
  }
439
439
  else {
440
- s = `\\left\\]-\\infty;${v} \\right\\${this.isAlsoEqual() ? '\\]' : '\\['}`;
440
+ s = `\\left\\]-\\infty;${v.tex} \\right\\${this.isAlsoEqual() ? '\\]' : '\\['}`;
441
441
  }
442
442
  }
443
443
  this._solutions = [{
@@ -2245,6 +2245,7 @@ class Polynom {
2245
2245
  this._monoms = [];
2246
2246
  this._factors = [];
2247
2247
  this.mark_as_dirty();
2248
+ // TODO: allow to enter a liste of Fraction (a, b, c, ...) to make a polynom ax^n + bx^(n-1) + cx^(n-2) + ...
2248
2249
  if (typeof inputStr === 'string') {
2249
2250
  return this._parseString(inputStr, ...values);
2250
2251
  }
@@ -3444,6 +3445,7 @@ exports.Rational = Rational;
3444
3445
  Object.defineProperty(exports, "__esModule", ({ value: true }));
3445
3446
  exports.Study = exports.TABLE_OF_SIGNS = exports.FUNCTION_EXTREMA = exports.ASYMPTOTE = exports.ZEROTYPE = void 0;
3446
3447
  const fraction_1 = __webpack_require__(506);
3448
+ const numexp_1 = __webpack_require__(735);
3447
3449
  var ZEROTYPE;
3448
3450
  (function (ZEROTYPE) {
3449
3451
  ZEROTYPE["ZERO"] = "z";
@@ -3466,9 +3468,9 @@ var FUNCTION_EXTREMA;
3466
3468
  })(FUNCTION_EXTREMA = exports.FUNCTION_EXTREMA || (exports.FUNCTION_EXTREMA = {}));
3467
3469
  var TABLE_OF_SIGNS;
3468
3470
  (function (TABLE_OF_SIGNS) {
3469
- TABLE_OF_SIGNS[TABLE_OF_SIGNS["DEFAULT"] = 0] = "DEFAULT";
3470
- TABLE_OF_SIGNS[TABLE_OF_SIGNS["GROWS"] = 1] = "GROWS";
3471
- TABLE_OF_SIGNS[TABLE_OF_SIGNS["VARIATIONS"] = 2] = "VARIATIONS";
3471
+ TABLE_OF_SIGNS["SIGNS"] = "signs";
3472
+ TABLE_OF_SIGNS["GROWS"] = "grows";
3473
+ TABLE_OF_SIGNS["VARIATIONS"] = "variatins";
3472
3474
  })(TABLE_OF_SIGNS = exports.TABLE_OF_SIGNS || (exports.TABLE_OF_SIGNS = {}));
3473
3475
  /**
3474
3476
  * The study class is a "function study" class that will get:
@@ -3572,6 +3574,8 @@ class Study {
3572
3574
  if (resultLine[pos] === 'z') {
3573
3575
  // It's a zero. Get the coordinates
3574
3576
  let x, y, zero = zeroes[i].exact, pt, xTex, yTex, pointType;
3577
+ // TODO: NumExp should parse something that isn't yet plotFunction
3578
+ let exp = new numexp_1.NumExp(this.fx.plotFunction);
3575
3579
  if (zero instanceof fraction_1.Fraction) {
3576
3580
  let value = zero, evalY = this.fx.evaluate(value);
3577
3581
  x = zero.value;
@@ -3581,7 +3585,7 @@ class Study {
3581
3585
  }
3582
3586
  else {
3583
3587
  x = zeroes[i].value;
3584
- y = this.fx.evaluate(zeroes[i].value).value;
3588
+ y = exp.evaluate({ x });
3585
3589
  xTex = x.toFixed(2);
3586
3590
  yTex = y.toFixed(2);
3587
3591
  }
@@ -3653,6 +3657,39 @@ class Study {
3653
3657
  tex += `\n\\end{tikzpicture}`;
3654
3658
  return tex;
3655
3659
  };
3660
+ this.drawCode = () => {
3661
+ // Function as string
3662
+ let code = `f(x)=${this.fx.plotFunction}`;
3663
+ // Asymptotes
3664
+ let i = 1;
3665
+ this.asymptotes.forEach(asymptote => {
3666
+ if (asymptote.type === ASYMPTOTE.VERTICAL) {
3667
+ code += `\nav_${i}=line x=${asymptote.zero.value}->red,dash`;
3668
+ i++;
3669
+ }
3670
+ else if (asymptote.type === ASYMPTOTE.HORIZONTAL) {
3671
+ code += `\nah=line y=${asymptote.fx.monoms[0].coefficient.value}->orange,dash`;
3672
+ }
3673
+ else if (asymptote.type === ASYMPTOTE.SLOPE) {
3674
+ code += `\nao=line y=${asymptote.fx.plotFunction}->red,dash`;
3675
+ }
3676
+ i++;
3677
+ });
3678
+ // Extremes
3679
+ for (let zero in this.derivative.extremes) {
3680
+ let extreme = this.derivative.extremes[zero];
3681
+ code += `\nM_${i}(${extreme.value.x},${extreme.value.y})*`;
3682
+ i++;
3683
+ }
3684
+ // Zeroes
3685
+ this.zeroes.forEach(zero => {
3686
+ if (zero.type === ZEROTYPE.ZERO) {
3687
+ code += `\nZ_${i}(${zero.value},0)*`;
3688
+ i++;
3689
+ }
3690
+ });
3691
+ return code;
3692
+ };
3656
3693
  this.fx = fx;
3657
3694
  this.makeStudy();
3658
3695
  return this;
@@ -3687,7 +3724,7 @@ class Study {
3687
3724
  ;
3688
3725
  makeSigns() {
3689
3726
  return {
3690
- type: TABLE_OF_SIGNS.DEFAULT,
3727
+ type: TABLE_OF_SIGNS.SIGNS,
3691
3728
  fx: null,
3692
3729
  factors: [],
3693
3730
  zeroes: [],
@@ -3752,13 +3789,13 @@ exports.RationalStudy = void 0;
3752
3789
  const study_1 = __webpack_require__(996);
3753
3790
  const rational_1 = __webpack_require__(107);
3754
3791
  const fraction_1 = __webpack_require__(506);
3792
+ const polynom_1 = __webpack_require__(38);
3755
3793
  class RationalStudy extends study_1.Study {
3756
3794
  constructor(fx) {
3757
3795
  super(fx);
3758
3796
  return this;
3759
3797
  }
3760
3798
  makeZeroes() {
3761
- console.log('GETTING ZEROES');
3762
3799
  return this._getZeroes(this.fx);
3763
3800
  }
3764
3801
  ;
@@ -3788,44 +3825,52 @@ class RationalStudy extends study_1.Study {
3788
3825
  }
3789
3826
  }
3790
3827
  asymptotes.push({
3828
+ fx: null,
3791
3829
  type: Ztype,
3792
3830
  tex: tex,
3793
3831
  zero: zero,
3794
3832
  limits: `\\lim_{x\\to${zero.tex} }\\ f(x) = \\pm\\infty`,
3795
- deltaX: null
3833
+ deltaX: null,
3834
+ tableOfSign: null
3796
3835
  });
3797
3836
  });
3798
3837
  // Sloped asymptote
3799
3838
  let NDegree = this.fx.numerator.degree(), DDegree = this.fx.denominator.degree();
3800
3839
  if (NDegree.isEqual(DDegree)) {
3801
- let H = this.fx.numerator.monomByDegree().coefficient.clone().divide(this.fx.denominator.monomByDegree().coefficient).tex;
3802
- let { reminder } = reduced.euclidian();
3840
+ let H = this.fx.numerator.monomByDegree().coefficient.clone().divide(this.fx.denominator.monomByDegree().coefficient), Htex = H.tex;
3841
+ let { reminder } = reduced.euclidian(), deltaX = new rational_1.Rational(reminder, reduced.denominator);
3803
3842
  asymptotes.push({
3843
+ fx: new polynom_1.Polynom(H),
3804
3844
  type: study_1.ASYMPTOTE.HORIZONTAL,
3805
- tex: `y=${H}`,
3845
+ tex: `y=${Htex}`,
3806
3846
  zero: null,
3807
- limits: `\\lim_{x\\to\\infty}\\ f(x) = ${H}`,
3808
- deltaX: new rational_1.Rational(reminder, reduced.denominator)
3847
+ limits: `\\lim_{x\\to\\infty}\\ f(x) = ${Htex}`,
3848
+ deltaX,
3849
+ tableOfSign: this._getSigns(deltaX)
3809
3850
  });
3810
3851
  }
3811
3852
  else if (DDegree.greater(NDegree)) {
3812
3853
  asymptotes.push({
3854
+ fx: new polynom_1.Polynom('0'),
3813
3855
  type: study_1.ASYMPTOTE.HORIZONTAL,
3814
3856
  tex: `y=0`,
3815
3857
  zero: null,
3816
3858
  limits: `\\lim_{x\\to\\infty}\\ f(x) = ${0}`,
3817
- deltaX: null
3859
+ deltaX: null,
3860
+ tableOfSign: null
3818
3861
  });
3819
3862
  }
3820
3863
  else if (NDegree.value - 1 === DDegree.value) {
3821
3864
  // Calculate the slope
3822
- let { quotient, reminder } = reduced.euclidian();
3865
+ let { quotient, reminder } = reduced.euclidian(), deltaX = new rational_1.Rational(reminder, reduced.denominator);
3823
3866
  asymptotes.push({
3867
+ fx: quotient.clone(),
3824
3868
  type: study_1.ASYMPTOTE.SLOPE,
3825
3869
  tex: `y=${quotient.tex}`,
3826
3870
  zero: null,
3827
3871
  limits: ``,
3828
- deltaX: new rational_1.Rational(reminder, reduced.denominator)
3872
+ deltaX: new rational_1.Rational(reminder, reduced.denominator),
3873
+ tableOfSign: this._getSigns(deltaX)
3829
3874
  });
3830
3875
  }
3831
3876
  return asymptotes;
@@ -3833,7 +3878,6 @@ class RationalStudy extends study_1.Study {
3833
3878
  ;
3834
3879
  makeDerivative() {
3835
3880
  let dx = this.fx.clone().derivative(), tos = this._getSigns(dx, this._getZeroes(dx), study_1.TABLE_OF_SIGNS.GROWS);
3836
- console.log(tos.factors.length, tos.signs.length);
3837
3881
  let result = this.makeGrowsResult(tos);
3838
3882
  tos.signs.push(result.growsLine);
3839
3883
  tos.extremes = result.extremes;
@@ -3885,6 +3929,9 @@ class RationalStudy extends study_1.Study {
3885
3929
  _getSigns(fx, zeroes, typeOfTable) {
3886
3930
  // Factorize the rational
3887
3931
  let signs = [], factors = [];
3932
+ if (zeroes === undefined) {
3933
+ zeroes = this._getZeroes(fx);
3934
+ }
3888
3935
  fx.numerator.factors.forEach(factor => {
3889
3936
  signs.push(this.makeOneLineForSigns(factor, zeroes, study_1.ZEROTYPE.ZERO));
3890
3937
  factors.push(factor.clone());
@@ -3924,8 +3971,12 @@ const numeric_1 = __webpack_require__(956);
3924
3971
  */
3925
3972
  class Fraction {
3926
3973
  constructor(value, denominatorOrPeriodic) {
3927
- // ------------------------------------------
3928
- // Creation / parsing functions
3974
+ this.isApproximative = () => {
3975
+ return this._numerator.toString().length >= 15 && this._denominator.toString().length >= 15;
3976
+ };
3977
+ this.isExact = () => {
3978
+ return !this.isApproximative();
3979
+ };
3929
3980
  // ------------------------------------------
3930
3981
  /**
3931
3982
  * Parse the value to get the numerator and denominator
@@ -3942,15 +3993,15 @@ class Fraction {
3942
3993
  }
3943
3994
  switch (typeof value) {
3944
3995
  case "string":
3945
- // Split the sting value in two parts: Numerator/Denominator
3996
+ // Split the string value in two parts: Numerator/Denominator
3946
3997
  S = value.split('/');
3947
3998
  // Security checks
3948
3999
  if (S.length > 2)
3949
- throw "Two many divide signs";
4000
+ throw value + " has too many divide signs";
3950
4001
  if (S.map(x => x === '' || isNaN(Number(x))).includes(true))
3951
- throw "Not a number";
4002
+ throw value + " is not a valid number";
3952
4003
  if (S.length === 1) {
3953
- // No divide sign
4004
+ // No divide sign - it's a number
3954
4005
  return this.parse(+S[0]);
3955
4006
  }
3956
4007
  else if (S.length === 2) {
@@ -3967,6 +4018,7 @@ class Fraction {
3967
4018
  }
3968
4019
  else {
3969
4020
  // More than one divide sign ?
4021
+ // This is impossible
3970
4022
  this._numerator = NaN;
3971
4023
  this._denominator = 1;
3972
4024
  }
@@ -4007,6 +4059,8 @@ class Fraction {
4007
4059
  }
4008
4060
  return this;
4009
4061
  };
4062
+ // ------------------------------------------
4063
+ // Mathematical operations
4010
4064
  this.clone = () => {
4011
4065
  let F = new Fraction();
4012
4066
  F.numerator = +this._numerator;
@@ -4034,8 +4088,6 @@ class Fraction {
4034
4088
  return this;
4035
4089
  };
4036
4090
  // ------------------------------------------
4037
- // Mathematical operations
4038
- // ------------------------------------------
4039
4091
  this.opposed = () => {
4040
4092
  this._numerator = -this._numerator;
4041
4093
  return this;
@@ -4314,22 +4366,32 @@ class Fraction {
4314
4366
  if (this.isInfinity()) {
4315
4367
  return `${this.sign() === 1 ? '+' : '-'}\\infty`;
4316
4368
  }
4317
- if (this._denominator === 1) {
4318
- return `${this._numerator}`;
4319
- }
4320
- else if (this._numerator < 0) {
4321
- return `-\\frac{ ${-this._numerator} }{ ${this._denominator} }`;
4369
+ if (this.isExact()) {
4370
+ if (this._denominator === 1) {
4371
+ return `${this._numerator}`;
4372
+ }
4373
+ else if (this._numerator < 0) {
4374
+ return `-\\frac{ ${-this._numerator} }{ ${this._denominator} }`;
4375
+ }
4376
+ else {
4377
+ return `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
4378
+ }
4322
4379
  }
4323
4380
  else {
4324
- return `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
4381
+ return this.value.toFixed(3);
4325
4382
  }
4326
4383
  }
4327
4384
  get display() {
4328
- if (this._denominator === 1) {
4329
- return `${this._numerator}`;
4385
+ if (this.isExact()) {
4386
+ if (this._denominator === 1) {
4387
+ return `${this._numerator}`;
4388
+ }
4389
+ else {
4390
+ return `${this._numerator}/${this._denominator}`;
4391
+ }
4330
4392
  }
4331
4393
  else {
4332
- return `${this._numerator}/${this._denominator}`;
4394
+ return this.value.toFixed(3);
4333
4395
  }
4334
4396
  }
4335
4397
  // Helper function to display fractions
@@ -4364,6 +4426,8 @@ Fraction.min = (...fractions) => {
4364
4426
  }
4365
4427
  return M;
4366
4428
  };
4429
+ // ------------------------------------------
4430
+ // Creation / parsing functions
4367
4431
  Fraction.average = (...fractions) => {
4368
4432
  let M = new Fraction().zero();
4369
4433
  for (let f of fractions) {
@@ -6785,6 +6849,7 @@ var ShutingyardType;
6785
6849
  })(ShutingyardType = exports.ShutingyardType || (exports.ShutingyardType = {}));
6786
6850
  var ShutingyardMode;
6787
6851
  (function (ShutingyardMode) {
6852
+ ShutingyardMode["EXPRESSION"] = "expression";
6788
6853
  ShutingyardMode["POLYNOM"] = "polynom";
6789
6854
  ShutingyardMode["SET"] = "set";
6790
6855
  ShutingyardMode["NUMERIC"] = "numeric";
@@ -6800,6 +6865,9 @@ class Shutingyard {
6800
6865
  // console.log(this._rpn)
6801
6866
  return this._rpn;
6802
6867
  }
6868
+ get rpnToken() {
6869
+ return this._rpn.map(x => x.token);
6870
+ }
6803
6871
  /**
6804
6872
  * Determin if the token is a defined operation
6805
6873
  * Defined operations: + - * / ^ sin cos tan
@@ -6841,6 +6909,22 @@ class Shutingyard {
6841
6909
  };
6842
6910
  this._uniformize = false;
6843
6911
  }
6912
+ else if (this._mode === ShutingyardMode.EXPRESSION) {
6913
+ this._tokenConfig = {
6914
+ '^': { precedence: 4, associative: 'right', type: ShutingyardType.OPERATION },
6915
+ '*': { precedence: 3, associative: 'left', type: ShutingyardType.OPERATION },
6916
+ '/': { precedence: 3, associative: 'left', type: ShutingyardType.OPERATION },
6917
+ '+': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6918
+ '-': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6919
+ '%': { precedence: 3, associative: 'right', type: ShutingyardType.OPERATION },
6920
+ 'sin': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6921
+ 'cos': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6922
+ 'tan': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6923
+ 'sqrt': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6924
+ 'nthrt': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6925
+ };
6926
+ this._uniformize = true;
6927
+ }
6844
6928
  else {
6845
6929
  this._tokenConfig = {
6846
6930
  '^': { precedence: 4, associative: 'right', type: ShutingyardType.OPERATION },
@@ -6848,10 +6932,6 @@ class Shutingyard {
6848
6932
  '/': { precedence: 3, associative: 'left', type: ShutingyardType.OPERATION },
6849
6933
  '+': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6850
6934
  '-': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6851
- // '%': {precedence: 3, associative: 'right', type: ShutingyardType.OPERATION},
6852
- // 'sin': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6853
- // 'cos': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6854
- // 'tan': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6855
6935
  };
6856
6936
  this._uniformize = true;
6857
6937
  }
@@ -6883,9 +6963,6 @@ class Shutingyard {
6883
6963
  tokenType = 'function-argument';
6884
6964
  }
6885
6965
  else {
6886
- // Order token keys by token characters length (descending)
6887
- // TODO: this is done each time ! SHould be done once !
6888
- // const keys = Object.keys(this._tokenConfig).sort((a,b)=>b.length-a.length)
6889
6966
  // Extract operation and function tokens
6890
6967
  for (let key of this._tokenKeys) {
6891
6968
  if (expr.substring(start, start + key.length) === key) {
@@ -6907,7 +6984,7 @@ class Shutingyard {
6907
6984
  if (expr[start].match(/[0-9]/)) {
6908
6985
  if (this._mode === ShutingyardMode.POLYNOM && false) {}
6909
6986
  else {
6910
- token = expr.substring(start).match(/^([0-9.,]+)/)[0];
6987
+ token = expr.substring(start).match(/^([0-9.]+)/)[0];
6911
6988
  }
6912
6989
  tokenType = ShutingyardType.COEFFICIENT;
6913
6990
  }
@@ -6924,19 +7001,114 @@ class Shutingyard {
6924
7001
  }
6925
7002
  return [token, start + token.length, tokenType];
6926
7003
  }
7004
+ normalize(expr) {
7005
+ // Get the list of function token.
7006
+ let fnToken = [], kToken = [];
7007
+ for (let token in this._tokenConfig) {
7008
+ if (this._tokenConfig[token].type === ShutingyardType.FUNCTION) {
7009
+ fnToken.push(token);
7010
+ }
7011
+ }
7012
+ // sort if from the lengthy to the smallest function
7013
+ fnToken.sort((a, b) => b.length - a.length);
7014
+ for (let token in exports.tokenConstant) {
7015
+ kToken.push(token);
7016
+ }
7017
+ // sort if from the lengthy to the smallest function
7018
+ kToken.sort((a, b) => b.length - a.length);
7019
+ let normalizedExpr = "", i = 0, crtToken, nextToken;
7020
+ while (i < expr.length - 1) {
7021
+ // Check if we have a function token.
7022
+ // The function MUST have an open parentheses
7023
+ let tokenIdx = 0;
7024
+ while (tokenIdx < fnToken.length) {
7025
+ let token = fnToken[tokenIdx];
7026
+ if (expr.slice(i, i + token.length + 1) === token + '(') {
7027
+ normalizedExpr += token + '(';
7028
+ i += token.length + 1;
7029
+ // Restart the scan for the function token
7030
+ tokenIdx = 0;
7031
+ }
7032
+ else {
7033
+ // scan for a next function token
7034
+ tokenIdx++;
7035
+ }
7036
+ }
7037
+ // Check for a constant
7038
+ tokenIdx = 0;
7039
+ while (tokenIdx < kToken.length) {
7040
+ let token = kToken[tokenIdx];
7041
+ if (expr.slice(i, i + token.length) === token) {
7042
+ // We have found a constant.
7043
+ // add it, but with remove the last letter
7044
+ normalizedExpr += token.slice(0, -1);
7045
+ i += token.length - 1;
7046
+ // Exit the loop
7047
+ break;
7048
+ }
7049
+ tokenIdx++;
7050
+ }
7051
+ // The function token are solved.
7052
+ crtToken = expr[i];
7053
+ nextToken = expr[i + 1];
7054
+ normalizedExpr += crtToken;
7055
+ if (crtToken.match(/[a-zA-Z]/g)) {
7056
+ // Current element is a letter.
7057
+ // if the next element is a letter, a number or an opening parentheses, add the multiplication sign.
7058
+ if (nextToken.match(/[a-zA-Z\d(]/)) {
7059
+ normalizedExpr += '*';
7060
+ }
7061
+ }
7062
+ else if (crtToken.match(/\d/)) {
7063
+ // Current element is a number.
7064
+ // if the next element is a letter or a parentheses, add the multiplication sign.
7065
+ if (nextToken.match(/[a-zA-Z(]/)) {
7066
+ normalizedExpr += '*';
7067
+ }
7068
+ }
7069
+ else if (crtToken === ')') {
7070
+ // Current element is a closing parentheses.
7071
+ // if the next element is a letter, a number or an opening parentheses, add the multiplication sign
7072
+ if (nextToken.match(/[a-zA-Z\d(]/)) {
7073
+ normalizedExpr += '*';
7074
+ }
7075
+ }
7076
+ // Go to next token
7077
+ i++;
7078
+ }
7079
+ // add the last token
7080
+ return normalizedExpr + nextToken;
7081
+ }
6927
7082
  /**
6928
7083
  * Sanitize an expression by adding missing common operation (multiplication between parentheseses)
6929
7084
  * @param expr
6930
7085
  * @constructor
6931
7086
  */
6932
7087
  Uniformizer(expr) {
7088
+ // TODO: Delete this old version
7089
+ // Prefere "normalize", much more robust !
6933
7090
  // Determiner if need to be uniformized
6934
7091
  if (!this._uniformize) {
6935
7092
  return expr;
6936
7093
  }
7094
+ // Generate the list of function token.
7095
+ let fnToken = [];
7096
+ for (let token in this._tokenConfig) {
7097
+ if (this._tokenConfig[token].type === ShutingyardType.FUNCTION) {
7098
+ fnToken.push(token);
7099
+ }
7100
+ }
7101
+ // sort if from the lengthy to the smallest function
7102
+ fnToken.sort((a, b) => b.length - a.length);
7103
+ let tokenRegExp = new RegExp(`(${fnToken.join('|')})`, 'g');
7104
+ let functionTokenOrder = Array.from(expr.matchAll(tokenRegExp));
6937
7105
  let expr2;
7106
+ // Replace all function by @
7107
+ expr2 = expr.replace(tokenRegExp, '@');
7108
+ // Add * before @ (functionn)
7109
+ expr2 = expr2.replace(/([\da-zA-Z])(@)/g, "$1*$2");
6938
7110
  // Replace missing multiplication between two parenthese
6939
- expr2 = expr.replace(/\)\(/g, ')*(');
7111
+ expr2 = expr2.replace(/\)\(/g, ')*(');
6940
7112
  // Replace missing multiplication between number or setLetter and parenthese.
6941
7113
  // 3x(x-4) => 3x*(x-4)
6942
7114
  expr2 = expr2.replace(/([\da-zA-Z])(\()/g, "$1*$2");
@@ -6946,14 +7118,24 @@ class Shutingyard {
6946
7118
  // 3x => 3*x
6947
7119
  expr2 = expr2.replace(/([0-9])([a-zA-Z])/g, "$1*$2");
6948
7120
  expr2 = expr2.replace(/([a-zA-Z])([0-9])/g, "$1*$2");
7121
+ // Remove letter between function token and it's parenthese.
7122
+ // for (let token of fnToken) {
7123
+ // // Remove
7124
+ // expr2 = expr2.replace(new RegExp(token + '\\*', 'g'), token);
7125
+ // }
6949
7126
  // Add multiplication between letters ?
6950
- // TODO: More robust solution to handle all letters ?
6951
- expr2 = expr2.replace(/([abcxyz])([abcxyz])/g, "$1*$2");
6952
- // Restore operation auto formating (prevent adding the mutliplcation star)
6953
- // TODO: Accept list of functions
6954
- let fnToken = ['sin', 'cos', 'tan'];
6955
- for (let token of fnToken) {
6956
- expr2 = expr2.replace(new RegExp(token + '\\*', 'g'), token);
7127
+ expr2 = expr2.replace(/([a-zA-Z])([a-zA-Z])/g, "$1*$2");
7128
+ expr2 = expr2.replace(/([a-zA-Z])([a-zA-Z])/g, "$1*$2");
7129
+ // Restore operation auto formatting (prevent adding the multiplication star)
7130
+ let exprAsArray = expr2.split('@');
7131
+ if (exprAsArray.length > 0) {
7132
+ expr2 = "";
7133
+ for (let idx in exprAsArray) {
7134
+ }
7135
+ for (let token of fnToken) {
7136
+ // Remove
7137
+ // expr2 = expr2.replace(new RegExp(token + '\\*', 'g'), token);
7138
+ }
6957
7139
  }
6958
7140
  return expr2;
6959
7141
  }
@@ -6967,7 +7149,9 @@ class Shutingyard {
6967
7149
  let outQueue = [], // Output queue
6968
7150
  opStack = [], // Operation queue
6969
7151
  token = '', tokenPos = 0, tokenType = '', previousOpStatckLength = 0;
6970
- expr = this.Uniformizer(expr);
7152
+ // Normalize the input if required.
7153
+ if (this._uniformize)
7154
+ expr = this.normalize(expr);
6971
7155
  let securityLoopLvl1 = 50, securityLoopLvl2_default = 50, securityLoopLvl2;
6972
7156
  while (tokenPos < expr.length) {
6973
7157
  securityLoopLvl1--;
@@ -6986,10 +7170,6 @@ class Shutingyard {
6986
7170
  token,
6987
7171
  tokenType
6988
7172
  });
6989
- // if(previousOpStatckLength == opStack.length && outQueue.length>=2){
6990
- // console.log('opStatckLength', outQueue, opStack.length)
6991
- // outQueue.push('*')
6992
- // }
6993
7173
  break;
6994
7174
  case 'operation':
6995
7175
  previousOpStatckLength = opStack.length;