pimath 0.0.40 → 0.0.41

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 (34) hide show
  1. package/dist/pi.js +288 -92
  2. package/dist/pi.js.map +1 -1
  3. package/dist/pi.min.js +1 -1
  4. package/dist/pi.min.js.map +1 -1
  5. package/docs/assets/search.js +1 -1
  6. package/esm/index.d.ts +2 -2
  7. package/esm/index.js +2 -2
  8. package/esm/maths/algebra/equation.d.ts +6 -2
  9. package/esm/maths/algebra/equation.js +49 -9
  10. package/esm/maths/algebra/equation.js.map +1 -1
  11. package/esm/maths/algebra/polynom.d.ts +2 -1
  12. package/esm/maths/algebra/polynom.js +98 -62
  13. package/esm/maths/algebra/polynom.js.map +1 -1
  14. package/esm/maths/algebra/rational.d.ts +10 -0
  15. package/esm/maths/algebra/rational.js +101 -10
  16. package/esm/maths/algebra/rational.js.map +1 -1
  17. package/esm/maths/coefficients/fraction.d.ts +3 -1
  18. package/esm/maths/coefficients/fraction.js +33 -4
  19. package/esm/maths/coefficients/fraction.js.map +1 -1
  20. package/esm/maths/coefficients/{nthroot.d.ts → nthRoot.d.ts} +5 -5
  21. package/esm/maths/coefficients/{nthroot.js → nthRoot.js} +5 -5
  22. package/esm/maths/coefficients/{nthroot.js.map → nthRoot.js.map} +1 -1
  23. package/package.json +1 -1
  24. package/src/index.ts +2 -2
  25. package/src/maths/algebra/equation.ts +58 -12
  26. package/src/maths/algebra/polynom.ts +100 -68
  27. package/src/maths/algebra/rational.ts +136 -20
  28. package/src/maths/coefficients/fraction.ts +39 -5
  29. package/src/maths/coefficients/{nthroot.ts → nthRoot.ts} +5 -5
  30. package/tests/algebra/equation.test.ts +38 -0
  31. package/tests/algebra/monom.test.ts +1 -4
  32. package/tests/algebra/rationnal.test.ts +29 -5
  33. package/tests/coefficients/fraction.test.ts +43 -1
  34. package/tests/geometry/circle.test.ts +4 -2
@@ -2,22 +2,28 @@ import {Polynom} from "./polynom";
2
2
  import {literalType, Monom} from "./monom";
3
3
  import {Numeric} from "../numeric";
4
4
  import {Fraction} from "../coefficients/fraction";
5
- import {Nthroot} from "../coefficients/nthroot";
5
+ import {NthRoot} from "../coefficients/nthRoot";
6
6
 
7
7
  /**
8
8
  * Equation is a class to manage equations...
9
9
  */
10
- interface ISolution {
10
+ export interface ISolution {
11
11
  tex: string,
12
12
  value: number,
13
13
  exact: unknown
14
14
  }
15
15
 
16
+ export enum PARTICULAR_SOLUTION {
17
+ real="\\mathbb{R}",
18
+ varnothing="\\varnothing"
19
+ }
20
+
16
21
  export class Equation {
17
22
  private _polynom: Polynom; // Used to solve the equation // TODO: remove the private value ?
23
+
18
24
  // Undetermined texSolutions.
19
- private _varnothing: string = '\\varnothing';
20
- private _real: string = '\\mathbb{R}';
25
+ private _varnothing: string = PARTICULAR_SOLUTION.varnothing;
26
+ private _real: string = PARTICULAR_SOLUTION.real;
21
27
 
22
28
  /**
23
29
  * Create an Equation using two polynoms.
@@ -397,9 +403,29 @@ export class Equation {
397
403
  default:
398
404
  this._solveDegree3plus();
399
405
  }
406
+
407
+ // cleanup the solutions.
408
+ this._solutions = Equation.makeSolutionsUnique(this._solutions)
400
409
  return this;
401
410
  };
402
411
 
412
+ static makeSolutionsUnique(solutions: ISolution[], sorted?: boolean):ISolution[] {
413
+ let solutionAsTex:string[] = [],
414
+ uniqueSolutions = solutions.filter(sol=>{
415
+ if(!solutionAsTex.includes(sol.tex)){
416
+ solutionAsTex.push(sol.tex)
417
+ return true
418
+ }else{
419
+ return false
420
+ }
421
+ })
422
+
423
+ if(sorted===true){
424
+ uniqueSolutions.sort((a, b)=>a.value-b.value)
425
+ }
426
+ return uniqueSolutions
427
+ }
428
+
403
429
  test = (values: literalType): Boolean => {
404
430
  return this.left.evaluate(values).isEqual(this.right.evaluate(values))
405
431
  }
@@ -526,12 +552,13 @@ export class Equation {
526
552
  }
527
553
  } else {
528
554
  this._solutions = [{
529
- tex: v.display,
555
+ tex: v.tex,
530
556
  value: v.value,
531
557
  exact: v
532
558
  }]
533
559
  }
534
- } else {
560
+ }
561
+ else {
535
562
  if (m1.value === 0) {
536
563
  // In this case, the coefficient of the x variable is zero.
537
564
  if (m0.value === 0 && this.isAlsoEqual()) {
@@ -565,7 +592,7 @@ export class Equation {
565
592
  let aF = this._polynom.monomByDegree(2, letter).coefficient,
566
593
  bF = this._polynom.monomByDegree(1, letter).coefficient,
567
594
  cF = this._polynom.monomByDegree(0, letter).coefficient,
568
- delta: number, nthDelta: Nthroot,
595
+ delta: number, nthDelta: NthRoot,
569
596
  lcm = Numeric.lcm(aF.denominator, bF.denominator, cF.denominator),
570
597
  a = aF.multiply(lcm).value,
571
598
  b = bF.multiply(lcm).value,
@@ -594,7 +621,7 @@ export class Equation {
594
621
  }
595
622
  ]
596
623
  } else {
597
- nthDelta = new Nthroot(delta).reduce();
624
+ nthDelta = new NthRoot(delta).reduce();
598
625
  if (nthDelta.hasRadical()) {
599
626
  // -b +- coeff\sqrt{radical}
600
627
  // -------------------------
@@ -696,7 +723,6 @@ export class Equation {
696
723
  }];
697
724
  }
698
725
 
699
-
700
726
  // Handle now the inequations.
701
727
  if (!this.isStrictEqual()) {
702
728
  if (this._solutions.length === 2) {
@@ -763,9 +789,29 @@ export class Equation {
763
789
  return this._solutions;
764
790
  };
765
791
 
766
- private _solveDegree3plus = (): ISolution[] => {
767
- // TODO: try to resolve equations with a degree superior than 2.
768
- this._solutions = [{tex: 'solve x - not yet handled', value: NaN, exact: false}]; // ESLint remove system :(
792
+ private _solveDegree3plus = (letter?: string): ISolution[] => {
793
+ // Push everything to the left
794
+ // factorize
795
+ // solve each factors.
796
+ let equ = this.clone().moveLeft()
797
+ equ.left.factorize()
798
+
799
+ this._solutions = []
800
+
801
+ equ.left.factors.forEach(factor=>{
802
+ if(factor.degree(letter).leq(2)) {
803
+ let factorAsEquation = new Equation(factor, 0)
804
+ factorAsEquation.solve()
805
+ factorAsEquation.solutions.forEach(solution => {
806
+ this._solutions.push(solution)
807
+ })
808
+ }else{
809
+ console.log(factor.tex, ': cannot actually get the solution of this equation')
810
+ }
811
+ })
812
+
813
+ // TODO: check equation resolution for more than degree 2
814
+ // this._solutions = [{tex: 'solve x - not yet handled', value: NaN, exact: false}]; // ESLint remove system :(
769
815
  return this._solutions;
770
816
  };
771
817
  }
@@ -6,6 +6,7 @@ import {literalType, Monom} from './monom';
6
6
  import {Shutingyard, ShutingyardType, Token} from '../shutingyard';
7
7
  import {Numeric} from '../numeric';
8
8
  import {Fraction} from "../coefficients/fraction";
9
+ import {Equation, ISolution} from "./equation";
9
10
 
10
11
  export type PolynomParsingType = string | Polynom | number | Fraction | Monom
11
12
 
@@ -65,6 +66,9 @@ export class Polynom {
65
66
  get texFactors(): string {
66
67
  this.factorize()
67
68
 
69
+ if(this.factors.length===0){
70
+ return this.tex
71
+ }
68
72
  let tex = ''
69
73
  for (let f of this.factors) {
70
74
  if (f.monoms.length > 1) {
@@ -773,6 +777,7 @@ export class Polynom {
773
777
  }
774
778
 
775
779
  let securityLoop = P.degree().clone().multiply(2).value
780
+ let result
776
781
  // securityLoop = 0
777
782
 
778
783
  while (securityLoop >= 0) {
@@ -791,8 +796,8 @@ export class Polynom {
791
796
  for (let m1d of m1) {
792
797
  for (let m2d of m2) {
793
798
  // if(m1d.degree()===m2d.degree()){continue}
794
- let dividerPolynom = new Polynom(),
795
- result
799
+ let dividerPolynom = new Polynom()
800
+
796
801
  dividerPolynom.monoms = [m1d.clone(), m2d.clone()]
797
802
  result = P.euclidian(dividerPolynom)
798
803
 
@@ -813,77 +818,104 @@ export class Polynom {
813
818
  }
814
819
  }
815
820
 
821
+ if(!P.isOne()){factors.push(P.clone())}
822
+
816
823
  this.factors = factors
817
824
  return factors;
818
825
  }
819
826
 
820
827
  // TODO: get zeroes for more than first degree and for more than natural degrees
821
- getZeroes = (): (Fraction | boolean)[] => {
822
- const Z: Fraction[] = [];
823
-
824
- switch (this.degree().value) {
825
- case 0:
826
- if (this._monoms[0].coefficient.value === 0) {
827
- return [true];
828
- } else {
829
- return [false];
830
- }
831
- case 1:
832
- // There is only one monoms,
833
- if (this._monoms.length === 1) {
834
- return [new Fraction().zero()];
835
- } else {
836
- const P = this.clone().reduce().reorder();
837
- return [P.monoms[1].coefficient.opposed().divide(P.monoms[0].coefficient)];
838
- }
839
- // TODO: Determine the zeros of an equation of second degree.
840
- //case 2:
841
- default:
842
- // Make sure the polynom is factorized.
843
- if (this._factors.length === 0) {
844
- this.factorize()
845
- }
846
-
847
- let zeroes = [], zeroesAsTex = [];
848
- for (let P of this._factors) {
849
- if (P.degree().greater(2)) {
850
- // TODO: Handle other polynom.
851
-
852
- } else if (P.degree().value === 2) {
853
- let A = P.monomByDegree(2).coefficient,
854
- B = P.monomByDegree(1).coefficient,
855
- C = P.monomByDegree(0).coefficient,
856
- D = B.clone().pow(2).subtract(A.clone().multiply(C).multiply(4));
857
-
858
- if (D.value > 0) {
859
- /*console.log('Two zeroes for ', P.tex); */
860
- let x1 = (-(B.value) + Math.sqrt(D.value)) / (2 * A.value),
861
- x2 = (-(B.value) - Math.sqrt(D.value)) / (2 * A.value);
862
-
863
- zeroes.push(new Fraction(x1.toFixed(3)).reduce());
864
- zeroes.push(new Fraction(x2.toFixed(3)).reduce());
865
- } else if (D.value === 0) {
866
- /*console.log('One zero for ', P.tex); */
867
-
868
- } else {
869
- console.log('No zero for ', P.tex);
870
- }
871
- } else {
872
- for (let z of P.getZeroes()) {
873
- // Check if the zero is already in the list.
874
- if (z === false || z === true) {
875
- continue;
876
- }
877
- if (zeroesAsTex.indexOf(z.frac) === -1) {
878
- zeroes.push(z);
879
- zeroesAsTex.push(z.frac);
880
- }
881
- }
882
- }
883
- }
884
- return zeroes;
885
- }
886
- return Z;
828
+ getZeroes = (): ISolution[] => {
829
+ let equ = new Equation(this.clone(), 0)
830
+ equ.solve()
831
+ return equ.solutions
832
+
833
+ //
834
+ // const Z: Fraction[] = [];
835
+ //
836
+ // // ISolution: {tex: string, value: number, exact: boolean|Fraction|...}
837
+ //
838
+ // switch (this.degree().value) {
839
+ // case 0:
840
+ // if (this._monoms[0].coefficient.value === 0) {
841
+ // return [{
842
+ // tex: '\\mathbb{R}',
843
+ // value: NaN,
844
+ // exact: false
845
+ // }];
846
+ // } else {
847
+ // return [{
848
+ // tex: '\\varnothing',
849
+ // value: NaN,
850
+ // exact: false
851
+ // }];
852
+ // }
853
+ // case 1:
854
+ // // There is only one monoms,
855
+ // if (this._monoms.length === 1) {
856
+ // return [{
857
+ // tex: '0',
858
+ // value: 0,
859
+ // exact: new Fraction().zero()
860
+ // }];
861
+ // } else {
862
+ // const P = this.clone().reduce().reorder();
863
+ // const coeff = P.monoms[1].coefficient.opposed().divide(P.monoms[0].coefficient)
864
+ // return [{
865
+ // tex: coeff.tex,
866
+ // value: coeff.value,
867
+ // exact: coeff
868
+ // }];
869
+ // }
870
+ // // TODO: Determine the zeros of an equation of second degree.
871
+ // //case 2:
872
+ // default:
873
+ // // Make sure the polynom is factorized.
874
+ // if (this._factors.length === 0) {
875
+ // this.factorize()
876
+ // }
877
+ //
878
+ // let zeroes:Fraction[] = [], zeroesAsTex = [];
879
+ // for (let P of this._factors) {
880
+ // if (P.degree().greater(2)) {
881
+ // // TODO: get zeroes of polynom with a degree greater than 2.
882
+ //
883
+ // } else if (P.degree().value === 2) {
884
+ // let A = P.monomByDegree(2).coefficient,
885
+ // B = P.monomByDegree(1).coefficient,
886
+ // C = P.monomByDegree(0).coefficient,
887
+ // D = B.clone().pow(2).subtract(A.clone().multiply(C).multiply(4));
888
+ //
889
+ // if (D.value > 0) {
890
+ // /*console.log('Two zeroes for ', P.tex); */
891
+ // let x1 = (-(B.value) + Math.sqrt(D.value)) / (2 * A.value),
892
+ // x2 = (-(B.value) - Math.sqrt(D.value)) / (2 * A.value);
893
+ //
894
+ // zeroes.push(new Fraction(x1.toFixed(3)).reduce());
895
+ // zeroes.push(new Fraction(x2.toFixed(3)).reduce());
896
+ // } else if (D.value === 0) {
897
+ // /*console.log('One zero for ', P.tex); */
898
+ // } else {
899
+ // console.log('No zero for ', P.tex);
900
+ // }
901
+ // } else {
902
+ // for (let z of P.getZeroes()) {
903
+ // // Check if the zero is already in the list.
904
+ // // if (z === false || z === true) {
905
+ // // continue;
906
+ // // }
907
+ // if (zeroesAsTex.indexOf(z.frac) === -1) {
908
+ // zeroes.push(z);
909
+ // zeroesAsTex.push(z.frac);
910
+ // }
911
+ // }
912
+ // }
913
+ // }
914
+ //
915
+ //
916
+ // return zeroes;
917
+ // }
918
+ // return Z;
887
919
  };
888
920
 
889
921
  // TODO: analyse the next functions to determine if they are useful or not...
@@ -6,7 +6,7 @@
6
6
  import {Polynom} from "./polynom";
7
7
  import {Fraction} from "../coefficients/fraction";
8
8
  import {literalType} from "./monom";
9
- import {log} from "util";
9
+ import {Equation, ISolution, PARTICULAR_SOLUTION} from "./equation";
10
10
 
11
11
  /**
12
12
  * Rational class can handle rational polynoms
@@ -41,9 +41,6 @@ export class Rational {
41
41
  }
42
42
 
43
43
  get texFactors(): string {
44
- this._numerator.factorize()
45
- this._denominator.factorize()
46
-
47
44
  return `\\dfrac{ ${this._numerator.texFactors} }{ ${this._denominator.texFactors} }`
48
45
  }
49
46
 
@@ -56,16 +53,13 @@ export class Rational {
56
53
 
57
54
  domain = (): string => {
58
55
  let zeroes = this._denominator.getZeroes();
59
- if (zeroes.length === 0 || zeroes[0] === false) {
60
- return '\\mathbb{R}'
61
- } else if (zeroes[0] === true) {
62
- return '\\varnothing'
56
+ if (zeroes.length === 0 || zeroes[0].tex === PARTICULAR_SOLUTION.real) {
57
+ return PARTICULAR_SOLUTION.real
58
+ } else if (zeroes[0].tex === PARTICULAR_SOLUTION.varnothing) {
59
+ return PARTICULAR_SOLUTION.varnothing
63
60
  } else {
64
61
  return '\\mathbb{R}\\setminus\\left{' +
65
- zeroes.map(x => {
66
- return (typeof x === 'boolean') ? '' : x.frac
67
- })
68
- .join(';') + '\\right}'
62
+ zeroes.map(x => x.tex).join(';') + '\\right}'
69
63
  }
70
64
  }
71
65
 
@@ -76,6 +70,18 @@ export class Rational {
76
70
  return this;
77
71
  }
78
72
 
73
+ derivative = (letter?: string): Rational => {
74
+ let N = this._numerator.clone(),
75
+ D = this._denominator.clone(),
76
+ dN = N.clone().derivative(letter),
77
+ dD = D.clone().derivative(letter)
78
+
79
+ this._numerator = dN.clone().multiply(D).subtract(N.clone().multiply(dD))
80
+ this._denominator = D.clone().pow(2)
81
+
82
+ return this
83
+ }
84
+
79
85
  simplify = (P: Polynom): Rational => {
80
86
  let NumeratorEuclidien = this._numerator.euclidian(P);
81
87
  if (!NumeratorEuclidien.reminder.isZero()) {
@@ -131,14 +137,13 @@ export class Rational {
131
137
  let {quotient, reminder} = this._numerator.clone().euclidian(this._denominator)
132
138
 
133
139
  // quotient is positive => it will be infinite.
134
- if(quotient.degree(letter).isStrictlyPositive()){
135
- return value===Infinity ? quotient.limitToInfinity(letter):quotient.limitToNegativeInfinity(letter)
140
+ if (quotient.degree(letter).isStrictlyPositive()) {
141
+ return value === Infinity ? quotient.limitToInfinity(letter) : quotient.limitToNegativeInfinity(letter)
136
142
  // return quotient.monomByDegree(undefined, letter).coefficient.sign()===1?(new Fraction()).infinite():(new Fraction()).infinite().opposed()
137
- }else{
143
+ } else {
138
144
  return quotient.monomByDegree(undefined, letter).coefficient
139
145
  }
140
- }
141
- else {
146
+ } else {
142
147
  let evalValues: literalType = {},
143
148
  evalValuesOffset: literalType = {},
144
149
  theLimit: Fraction | number,
@@ -151,7 +156,7 @@ export class Rational {
151
156
  theLimit = FR._numerator.evaluate(evalValues)
152
157
  .divide(FR._denominator.evaluate(evalValues))
153
158
 
154
- return theLimit.isInfinity()?theLimit.abs():theLimit
159
+ return theLimit.isInfinity() ? theLimit.abs() : theLimit
155
160
  } else {
156
161
  if (offset === 'above') {
157
162
  evalValuesOffset[letter === undefined ? 'x' : letter] = (new Fraction(value)).add(0.000001)
@@ -165,11 +170,122 @@ export class Rational {
165
170
  .divide(FR._denominator.evaluate(evalValuesOffset)).sign()
166
171
 
167
172
  if (theLimit.isInfinity()) {
168
- return theSign===1?theLimit.abs():theLimit.abs().opposed()
169
- }else{
173
+ return theSign === 1 ? theLimit.abs() : theLimit.abs().opposed()
174
+ } else {
170
175
  return theLimit
171
176
  }
172
177
  }
173
178
  }
174
179
  }
180
+
181
+ makeTableOfSigns = (): { factors: Polynom[], zeroes: ISolution[], signs: (string[])[], tex: string } => {
182
+ // Factorize the numerator and the denominator
183
+ this._numerator.factorize()
184
+ this._denominator.factorize()
185
+
186
+ let zeroes = Equation.makeSolutionsUnique([...this._numerator.getZeroes(), ...this._denominator.getZeroes()], true),
187
+ NFactors = this._numerator.factors,
188
+ DFactors = this._denominator.factors
189
+
190
+ let tableOfSigns: (string[])[] = [],
191
+ result: string[] = []
192
+
193
+ NFactors.forEach(factor => {
194
+ tableOfSigns.push(this._makeOneLineOfTableOfSigns(factor, zeroes, 'z'))
195
+ })
196
+ DFactors.forEach(factor => {
197
+ tableOfSigns.push(this._makeOneLineOfTableOfSigns(factor, zeroes, 'd'))
198
+ })
199
+
200
+ // Empty line
201
+ tableOfSigns.push([])
202
+
203
+ // Add the final row as cumulative
204
+ let resultLine: string[] = tableOfSigns[0].map((x, index) => {
205
+ if (index === 0) {
206
+ return ''
207
+ }
208
+ if (index === tableOfSigns[0].length - 1) {
209
+ return ''
210
+ }
211
+ if (index % 2 === 0) {
212
+ return 't'
213
+ }
214
+ return '+'
215
+ })
216
+
217
+ for (let current of tableOfSigns) {
218
+ for (let i = 0; i < current.length; i++) {
219
+ if (i % 2 === 0) {
220
+ // t, z or d
221
+ if (resultLine[i] === 'd') {
222
+ continue
223
+ }
224
+ if (current[i] !== 't') {
225
+ resultLine[i] = current[i]
226
+ }
227
+ } else {
228
+ // + or -
229
+ if (current[i] === '-') {
230
+ resultLine[i] = resultLine[i] === '+' ? '-' : '+'
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ // Add the variation line.
237
+ // TODO: add the variation line.
238
+
239
+ tableOfSigns.push(resultLine)
240
+
241
+ let tos = {
242
+ factors: [...NFactors, ...DFactors],
243
+ zeroes: zeroes,
244
+ signs: tableOfSigns,
245
+ tex: ''
246
+ }
247
+
248
+ this._makeTexFromTableOfSigns(tos)
249
+
250
+ return tos
251
+ }
252
+
253
+ private _makeTexFromTableOfSigns = (tos: { factors: Polynom[], zeroes: ISolution[], signs: (string[])[], tex: string }): string => {
254
+
255
+ let tex = `\\begin{tikzpicture}
256
+ \\tkzTabInit[lgt=3,espcl=2,deltacl=0]{/1.2,\\(${tos.factors.map(x => x.tex).join('\\)/1,\\(')}\\)/1,/.1,\\(f(x)\\)/1.2}{{\\scriptsize \\hspace{1cm} \\(-\\infty\\)},\\(${tos.zeroes.map(x => x.tex).join('\\),\\(')}\\),{\\scriptsize \\hspace{-1cm} \\(+\\infty\\)}}`
257
+ tos.signs.forEach(list => {
258
+ tex += (`\n\\tkzTabLine{${list.join(',')}}`)
259
+ })
260
+ tex += `\n\\end{tikzpicture}`
261
+
262
+ tos.tex = tex
263
+
264
+ return tex
265
+ }
266
+ private _makeOneLineOfTableOfSigns = (factor: Polynom, zeroes: ISolution[], zeroSign: string): string[] => {
267
+ let oneLine: string[] = [],
268
+ // TODO : check if there is no zero ?
269
+ currentZero = factor.getZeroes().map(x=>x.tex)
270
+
271
+ // First +/- sign, before the first zero
272
+ oneLine.push('')
273
+ oneLine.push(factor.evaluate(zeroes[0].value - 1).sign() === 1 ? '+' : '-')
274
+
275
+ for (let i = 0; i < zeroes.length; i++) {
276
+ // Add the zero if it's the current one
277
+ oneLine.push(currentZero.includes(zeroes[i].tex) ? zeroSign : 't')
278
+
279
+ // + / - sign after the current zero
280
+ if (i < zeroes.length - 1) {
281
+ oneLine.push(factor.evaluate((zeroes[i].value + zeroes[i + 1].value) / 2).sign() === 1 ? '+' : '-')
282
+ } else if (i === zeroes.length - 1) {
283
+ oneLine.push(factor.evaluate(zeroes[i].value + 1).sign() === 1 ? '+' : '-')
284
+ }
285
+
286
+ }
287
+ oneLine.push('')
288
+
289
+ return oneLine
290
+ }
175
291
  }
@@ -21,10 +21,6 @@ export class Fraction {
21
21
  return this;
22
22
  }
23
23
 
24
- get isFraction() {
25
- return true;
26
- }
27
-
28
24
  // ------------------------------------------
29
25
  // Getter and setter
30
26
  // ------------------------------------------
@@ -350,6 +346,44 @@ export class Fraction {
350
346
  return M
351
347
  }
352
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
+
353
387
  // ------------------------------------------
354
388
  // Mathematical operations specific to fractions
355
389
  // ------------------------------------------
@@ -470,7 +504,7 @@ export class Fraction {
470
504
  return Math.abs(this._numerator) === Infinity;
471
505
  }
472
506
  isFinite = (): boolean => {
473
- return !this.isInfinity();
507
+ return !this.isInfinity() && !this.isNaN();
474
508
  }
475
509
  isSquare = (): boolean => {
476
510
  return Math.sqrt(this._numerator) % 1 === 0 && Math.sqrt(this._denominator) % 1 === 0
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Nthroot is something like "a+b\sqrt{3}
2
+ * NthRoot is something like "a+b\sqrt{3}
3
3
  */
4
- export class Nthroot {
4
+ export class NthRoot {
5
5
  private _radical: number;
6
6
  private _nth: number;
7
7
  private _coefficient: number;
@@ -80,7 +80,7 @@ export class Nthroot {
80
80
  // ------------------------------------------
81
81
  // Creation / parsing functions
82
82
  // ------------------------------------------
83
- parse = (radical: number, nthroot?: number, coefficient?: number): Nthroot => {
83
+ parse = (radical: number, nthroot?: number, coefficient?: number): NthRoot => {
84
84
  this._coefficient = (coefficient === undefined) ? 1 : coefficient;
85
85
  this._nth = (nthroot === undefined) ? 2 : nthroot;
86
86
  this._radical = (radical === undefined) ? 1 : radical;
@@ -94,7 +94,7 @@ export class Nthroot {
94
94
  // ------------------------------------------
95
95
  // Mathematical operations
96
96
  // ------------------------------------------
97
- reduce = (): Nthroot => {
97
+ reduce = (): NthRoot => {
98
98
  // Max value to test.
99
99
  let V = Math.floor(Math.pow(this._radical, 1 / this._nth));
100
100
  while (V > 1) {
@@ -112,7 +112,7 @@ export class Nthroot {
112
112
  return this;
113
113
  };
114
114
 
115
- multiply = (N: Nthroot): Nthroot => {
115
+ multiply = (N: NthRoot): NthRoot => {
116
116
  this._radical *= N.radical;
117
117
  return this.reduce();
118
118
  };