pimath 0.0.131 → 0.0.133

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 (33) hide show
  1. package/dist/main.d.ts +39 -1
  2. package/package.json +2 -3
  3. package/dist/maths/pimath.d.ts +0 -39
  4. package/lib/main.ts +0 -1
  5. package/lib/maths/algebra/equation.ts +0 -891
  6. package/lib/maths/algebra/linearSystem.ts +0 -369
  7. package/lib/maths/algebra/logicalset.ts +0 -183
  8. package/lib/maths/algebra/monom.ts +0 -1027
  9. package/lib/maths/algebra/polynom.ts +0 -1537
  10. package/lib/maths/algebra/rational.ts +0 -244
  11. package/lib/maths/algebra/study/rationalStudy.ts +0 -287
  12. package/lib/maths/algebra/study.ts +0 -506
  13. package/lib/maths/coefficients/fraction.ts +0 -593
  14. package/lib/maths/coefficients/nthRoot.ts +0 -148
  15. package/lib/maths/geometry/circle.ts +0 -379
  16. package/lib/maths/geometry/line.ts +0 -604
  17. package/lib/maths/geometry/point.ts +0 -215
  18. package/lib/maths/geometry/triangle.ts +0 -368
  19. package/lib/maths/geometry/vector.ts +0 -243
  20. package/lib/maths/numeric.ts +0 -162
  21. package/lib/maths/numexp.ts +0 -198
  22. package/lib/maths/pimath.ts +0 -40
  23. package/lib/maths/randomization/random.ts +0 -80
  24. package/lib/maths/randomization/randomCore.ts +0 -19
  25. package/lib/maths/randomization/rndFraction.ts +0 -47
  26. package/lib/maths/randomization/rndGeometryCircle.ts +0 -50
  27. package/lib/maths/randomization/rndGeometryLine.ts +0 -53
  28. package/lib/maths/randomization/rndGeometryPoint.ts +0 -69
  29. package/lib/maths/randomization/rndHelpers.ts +0 -107
  30. package/lib/maths/randomization/rndMonom.ts +0 -57
  31. package/lib/maths/randomization/rndPolynom.ts +0 -90
  32. package/lib/maths/randomization/rndTypes.ts +0 -43
  33. package/lib/maths/shutingyard.ts +0 -496
@@ -1,148 +0,0 @@
1
- /**
2
- * NthRoot is something like "a+b\sqrt{3}
3
- */
4
- export class NthRoot {
5
- private _radical: number;
6
- private _nth: number;
7
- private _coefficient: number;
8
- private _isValid:boolean;
9
-
10
- constructor(...values: number[]) {
11
- this._radical = 1;
12
- this._coefficient = 1;
13
- this._nth = 2;
14
- this._isValid = true;
15
-
16
- if(values !== undefined){
17
- this.parse(values[0], values[1], values[2])
18
- }
19
- }
20
-
21
- // ------------------------------------------
22
- // Getter and setter
23
- // ------------------------------------------
24
- get radical(): number {
25
- return this._radical;
26
- }
27
-
28
- set radical(value: number) {
29
- this._radical = value;
30
- }
31
-
32
- get nth(): number {
33
- return this._nth;
34
- }
35
-
36
- set nth(value: number) {
37
- if (Number.isSafeInteger(value) && value >= 2) {
38
- this._nth = value;
39
- } else {
40
- // Error setting the nth root.
41
- console.log('Error setting the nth root');
42
- this._nth = 2;
43
- }
44
- }
45
-
46
- get coefficient(): number {
47
- return this._coefficient;
48
- }
49
-
50
- set coefficient(value: number) {
51
- this._coefficient = value;
52
- }
53
-
54
- get tex(): string {
55
- let C: string;
56
-
57
- if (this._coefficient === 1) {
58
- C = '';
59
- } else if (this._coefficient === -1) {
60
- C = '-';
61
- } else {
62
- C = this._coefficient.toString();
63
- }
64
-
65
- if (this._radical === 1) {
66
- return `${this._coefficient}`;
67
- } else {
68
- if (this._nth === 2) {
69
- return `${C}\\sqrt{${this._radical}}`
70
- } else {
71
- return `${C}\\sqrt[${this._nth}]{${this._radical}}`
72
- }
73
- }
74
- }
75
-
76
- get display(): string {
77
- let C: string;
78
-
79
- if (this._coefficient === 1) {
80
- C = '';
81
- } else if (this._coefficient === -1) {
82
- C = '-';
83
- } else {
84
- C = this._coefficient.toString();
85
- }
86
-
87
- if (this._radical === 1) {
88
- return `${this._coefficient}`;
89
- } else {
90
- if (this._nth === 2) {
91
- return `${C}sqrt{${this._radical}}`
92
- } else {
93
- return `${C}root(${this._nth}){${this._radical}}`
94
- }
95
- }
96
- }
97
-
98
- get value(): number {
99
- return this._coefficient * Math.pow(this._radical, 1 / this._nth);
100
- }
101
-
102
- // ------------------------------------------
103
- // Creation / parsing functions
104
- // ------------------------------------------
105
- parse = (radical: number, nthroot?: number, coefficient?: number): NthRoot => {
106
- this._coefficient = (coefficient === undefined) ? 1 : coefficient;
107
- this._nth = (nthroot === undefined) ? 2 : nthroot;
108
- this._radical = (radical === undefined) ? 1 : radical;
109
-
110
- if(this._nth%2===0 && this._radical<0){
111
- this._isValid = false;
112
- }
113
- return this;
114
- };
115
-
116
- // ------------------------------------------
117
- // Mathematical operations
118
- // ------------------------------------------
119
- reduce = (): NthRoot => {
120
- // Max value to test.
121
- let V = Math.floor(Math.pow(this._radical, 1 / this._nth));
122
- while (V > 1) {
123
- if (this._radical % Math.pow(V, this._nth) === 0) {
124
- // It's dividable by V^n
125
- this._coefficient *= V;
126
- this._radical = this._radical / Math.pow(V, this._nth);
127
-
128
- // Redifine the new testing value (this is optimization)
129
- V = Math.floor(Math.pow(this._radical, 1 / this._nth));
130
- continue;
131
- }
132
- V--;
133
- }
134
- return this;
135
- };
136
-
137
- multiply = (N: NthRoot): NthRoot => {
138
- this._radical *= N.radical;
139
- return this.reduce();
140
- };
141
-
142
- // ------------------------------------------
143
- // Help functions
144
- // ------------------------------------------
145
- hasRadical = ():boolean => {
146
- return !(this._radical===1 || this._radical===0 || this._isValid===false)
147
- };
148
- }
@@ -1,379 +0,0 @@
1
- import {Point} from "./point";
2
- import {Line, LinePropriety} from "./line";
3
- import {Vector} from "./vector";
4
- import {Triangle} from "./triangle";
5
- import {Numeric} from "../numeric.ts";
6
- import {Fraction} from "../coefficients/fraction";
7
- import {Equation} from "../algebra/equation";
8
- import {Polynom} from "../algebra/polynom";
9
- import {Monom} from "../algebra/monom";
10
-
11
- export class Circle {
12
- private _center: Point;
13
- private _squareRadius: Fraction;
14
- private _cartesian: Equation;
15
- private _exists: boolean;
16
-
17
- constructor(...values: unknown[]) {
18
- this._exists = false
19
-
20
- if (values !== undefined) {
21
- this.parse(...values)
22
- }
23
- }
24
-
25
- get center(): Point {
26
- return this._center;
27
- }
28
-
29
- get squareRadius(): Fraction {
30
- return this._squareRadius
31
- }
32
-
33
- get cartesian(): Equation {
34
- return this._cartesian
35
- }
36
-
37
- get exists(): boolean {
38
- return this._exists;
39
- }
40
-
41
- get radius(): { tex: string, display: string, value: number } {
42
- if (this._squareRadius.isSquare()) {
43
- return {
44
- tex: this._squareRadius.clone().sqrt().tex,
45
- display: this._squareRadius.clone().sqrt().display,
46
- value: this._squareRadius.clone().sqrt().value
47
- }
48
- } else {
49
- return {
50
- tex: `\\sqrt{${this._squareRadius.tex}}`,
51
- display: `sqrt(${this._squareRadius.display})`,
52
- value: this._squareRadius.clone().sqrt().value
53
- }
54
- }
55
- return this._squareRadius
56
- }
57
-
58
- get tex(): string {
59
- if (this._exists) {
60
- let cx, cy
61
- if (this._center.x.isZero()) {
62
- cx = 'x^2'
63
- } else {
64
- cx = `\\left(x${this._center.x.isNegative() ? '+' : '-'}${this._center.x.clone().abs().tex}\\right)^2`
65
- }
66
- if (this._center.y.isZero()) {
67
- cy = 'y^2'
68
- } else {
69
- cy = `\\left(y${this._center.y.isNegative() ? '+' : '-'}${this._center.y.clone().abs().tex}\\right)^2`
70
- }
71
- return `${cx}+${cy}=${this._squareRadius.tex}`
72
- } else {
73
- return `\\text{le cercle n'existe pas.}`
74
- }
75
- }
76
-
77
- get developed(): string {
78
- return this._cartesian.tex
79
- }
80
-
81
- get display(): string {
82
- if (this._exists) {
83
- let cx, cy
84
- if (this._center.x.isZero()) {
85
- cx = 'x^2'
86
- } else {
87
- cx = `(x${this._center.x.isNegative() ? '+' : '-'}${this._center.x.clone().abs().tex})^2`
88
- }
89
- if (this._center.y.isZero()) {
90
- cy = 'y^2'
91
- } else {
92
- cy = `(y${this._center.y.isNegative() ? '+' : '-'}${this._center.y.clone().abs().tex})^2`
93
- }
94
- return `${cx}+${cy}=${this._squareRadius.display}`
95
- } else {
96
- return `\\text{le cercle n'existe pas.}`
97
- }
98
- }
99
-
100
- /**
101
- * Get the relative position between circle and line. It corresponds to the number of intersection.
102
- * @param {Line} L
103
- * @returns {number}
104
- */
105
- relativePosition = (L: Line): number => {
106
- let distance = L.distanceTo(this.center), radius = Math.sqrt(this._squareRadius.value)
107
-
108
- if (distance.value - radius > 0.0000000001) {
109
- return 0 // external
110
- } else if (Math.abs(distance.value - radius) < 0.0000000001) {
111
- return 1 // tangent
112
- } else {
113
- return 2 // external
114
- }
115
- }
116
-
117
- lineIntersection = (L: Line): Point[] => {
118
- let intersectionPoints: Point[] = [], solX: Fraction
119
-
120
- if (this._cartesian === null) {
121
- return []
122
- }
123
- const equX = this._cartesian.clone(), lineX = L.equation.clone().isolate('x'),
124
- lineY = L.equation.clone().isolate('y')
125
-
126
- if (lineX instanceof Equation && lineY instanceof Equation) {
127
- equX.replaceBy('y', lineY.right).simplify()
128
- equX.solve()
129
-
130
- for (let x of equX.solutions) {
131
- if (x.exact === false && isNaN(x.value)) {
132
- continue
133
- }
134
-
135
- solX = new Fraction(x.exact === false ? x.value : x.exact)
136
- intersectionPoints.push(new Point(solX.clone(), lineY.right.evaluate(solX)))
137
- }
138
- }
139
-
140
- return intersectionPoints
141
- }
142
-
143
- tangents = (P: Point | Fraction): Line[] => {
144
- if (P instanceof Fraction) {
145
- return this._tangentsWithSlope(P)
146
- } else if (this.isPointOnCircle(P)) {
147
- return this._tangentsThroughOnePointOnTheCircle(P)
148
- } else if (this.center.distanceTo(P).value > this.radius.value) {
149
- //TODO: Must check it's outside the circle
150
- return this._tangentsThroughOnePointOutsideTheCircle(P)
151
- } else {
152
- console.log('No tangents as the point is inside !')
153
- }
154
- return []
155
- }
156
-
157
- isPointOnCircle = (P: Point): Boolean => {
158
- return this._cartesian.test({x: P.x, y: P.y})
159
- }
160
-
161
- getPointsOnCircle = (numberIsInteger?: boolean): Point[] => {
162
- if (numberIsInteger === undefined) {
163
- numberIsInteger = false
164
- }
165
-
166
- // It means searching for pythagorician triples that make a perfect square.
167
- // (x-4)^2 + (y+3)^2 = 15
168
-
169
- let triplets = Numeric.pythagoricianTripletsWithTarget(this._squareRadius.value, true)
170
-
171
- let points: Point[] = [], pt
172
- triplets.forEach(triplet => {
173
- // Allow positive / negative values
174
- // x-a = t => x = a + t
175
- // x-a = -t => x = a - t
176
-
177
- for (let k of [[1, 1], [-1, 1], [-1, -1], [1, -1]]) {
178
- pt = new Point(
179
- this.center.x.clone().add(k[0] * triplet[0]),
180
- this.center.y.clone().add(k[1] * triplet[1])
181
- )
182
- // Check if the point is not already in points.
183
- if (!pt.isInListOfPoints(points)) {
184
- points.push(pt)
185
- }
186
- }
187
- })
188
- return points
189
- }
190
-
191
- clone(): Circle {
192
- this._center = this._center.clone()
193
- this._squareRadius = this._squareRadius.clone()
194
- this._calculateCartesian()
195
- return this
196
- }
197
-
198
- private _tangentsThroughOnePointOnTheCircle = (P: Point): Line[] => {
199
- let CT = new Vector(this._center, P)
200
- return [new Line(P, CT, LinePropriety.Perpendicular)]
201
- }
202
-
203
- private _tangentsThroughOnePointOutsideTheCircle = (P: Point): Line[] => {
204
- // y = mx + h
205
- // px, py => h = -m px + py => mx - y -m.px + py = 0 =>
206
- // Centre: cx, cy, radius: r
207
- // (m.cx - cy -m.px + py)^2 = r^2 * (m^2 + 1)
208
- // (m(cx-py) - (cy - py))^2 = r^2 * (m^2 + 1)
209
-
210
- let cx_px = this.center.x.clone().subtract(P.x), cy_py = this.center.y.clone().subtract(P.y),
211
- polyLeft = new Polynom('x'), polyRight = new Polynom('x^2+1')
212
-
213
- polyLeft.multiply(cx_px).subtract(cy_py).pow(2)
214
- polyRight.multiply(this.squareRadius)
215
-
216
- let equ = new Equation(polyLeft, polyRight)
217
- equ.moveLeft().simplify().solve()
218
-
219
- return equ.solutions.map(sol => {
220
- // h = -m px + py
221
- let h, equ = new Equation('y', 'x')
222
-
223
- if (sol.exact instanceof Fraction) {
224
- h = P.x.clone().opposed().multiply(sol.exact).add(P.y)
225
- equ.right.multiply(sol.exact).add(h)
226
- } else {
227
- h = P.x.clone().opposed().multiply(sol.value).add(P.y)
228
- equ.right.multiply(sol.value).add(h)
229
- }
230
-
231
- return new Line(equ)
232
- })
233
-
234
- }
235
-
236
- private _tangentsWithSlope = (slope: Fraction): Line[] => {
237
- // d(C;t)=r => ac1+bc2 + x = +- sqrt(a^2 + b^2)*r
238
- // x = -ac1-bc2 +- sqrt(a^2 + b^2)*r
239
- // y = a/bx + h => ax-by + H = 0
240
-
241
- const a = slope.numerator, b = -slope.denominator, c1 = this._center.x.clone(), c2 = this._center.y.clone(),
242
- r = this._squareRadius
243
-
244
- let sq = this._squareRadius.clone().multiply(slope.numerator ** 2 + slope.denominator ** 2),
245
- x1 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).add(sq.clone().sqrt()),
246
- x2 = c1.clone().multiply(a).opposed().subtract(c2.clone().multiply(b)).subtract(sq.clone().sqrt())
247
-
248
- return [new Line(a, b, x1), new Line(a, b, x2)]
249
- }
250
-
251
- private _reset(): Circle {
252
- this._center = null
253
- this._squareRadius = null
254
- this._cartesian = null
255
- this._exists = false
256
-
257
- return this
258
- }
259
-
260
- private parse(...values: unknown[]): Circle {
261
- // Data can be given in these formats:
262
- // one value, a string -> make it an Equation
263
- // one value, an Equation
264
- // one value, a circle -> clone it
265
- // two values: two points (center and pointThrough)
266
- // two values: point and Fraction (center and radius)
267
- // three values: Point, Fraction, Boolean (center, square radius, true)
268
-
269
- this._reset()
270
-
271
- if (typeof values[0] === 'string') {
272
- this._parseEquation(new Equation(values[0]))
273
- } else if (values[0] instanceof Equation) {
274
- this._parseEquation(values[0])
275
- } else if (values[0] instanceof Circle) {
276
- this._parseCopyCircle(values[0])
277
- } else if (values[0] instanceof Point && values.length > 1) {
278
- if (values[1] instanceof Point) {
279
- if (values[2] instanceof Point) {
280
- this._parseThroughtThreePoints(values[0], values[1], values[2])
281
- } else {
282
- this._parseCenterAndPointThrough(values[0], values[1])
283
- }
284
- } else if (values[1] instanceof Fraction || typeof values[1] === 'number') {
285
- this._parseCenterAndRadius(values[0], values[1], (typeof values[2] === "boolean") ? values[2] : false)
286
- }
287
- }
288
-
289
- // Calculate once the different values.
290
- if (this._exists) {
291
- this._calculateCartesian()
292
-
293
- // If the square radius is zero or positive, the circle exists.
294
- if (this._squareRadius !== undefined && this._squareRadius.isNegative()) {
295
- this._exists = false
296
- }
297
- }
298
-
299
- return this
300
- }
301
-
302
- private _calculateCartesian() {
303
- this._cartesian = (new Equation(new Polynom(`(x-(${this._center.x.display}))^2+(y-(${this._center.y.display}))^2`), new Polynom(`${this._squareRadius.display}`))).moveLeft()
304
- }
305
-
306
- private _parseCopyCircle(circle: Circle): Circle {
307
- this._center = circle.center.clone()
308
- this._squareRadius = circle.squareRadius.clone()
309
- this._calculateCartesian()
310
- this._exists = circle.exists
311
- return this
312
- }
313
-
314
- private _parseCenterAndRadius(center: Point, radius: Fraction | number, square?: boolean): Circle {
315
- this._center = center.clone()
316
-
317
- if (square) {
318
- this._squareRadius = (new Fraction(radius))
319
- } else {
320
- this._squareRadius = new Fraction(radius).pow(2)
321
- }
322
-
323
- this._exists = true
324
- return this
325
- }
326
-
327
- private _parseCenterAndPointThrough(center: Point, pointThrough: Point): Circle {
328
- this._center = center.clone()
329
- this._squareRadius = new Vector(this._center, pointThrough).normSquare
330
- this._exists = true
331
- return this
332
- }
333
-
334
- private _parseEquation(equ: Equation): Circle {
335
- this._exists = false
336
-
337
- // Move everything to the left.
338
- equ.moveLeft()
339
-
340
- if (equ.degree('x').value === 2 && equ.degree('y').value === 2) {
341
- // Both must be of degree 2.
342
- let x2 = equ.left.monomByDegree(2, 'x'), y2 = equ.left.monomByDegree(2, 'y'), x1: Monom, y1: Monom, c: Monom
343
-
344
- // Both square monoms must have the same coefficient.
345
- if (x2.coefficient.isEqual(y2.coefficient)) {
346
- equ.divide(x2.coefficient)
347
-
348
- x1 = equ.left.monomByDegree(1, 'x')
349
- y1 = equ.left.monomByDegree(1, 'y')
350
-
351
- c = equ.left.monomByDegree(0)
352
-
353
- this._center = new Point(x1.coefficient.clone().divide(2).opposed(), y1.coefficient.clone().divide(2).opposed())
354
-
355
- this._squareRadius = c.coefficient.clone().opposed()
356
- .add(this._center.x.clone().pow(2))
357
- .add(this._center.y.clone().pow(2))
358
-
359
- this._calculateCartesian()
360
- this._exists = true
361
- } else {
362
- // The circle is not a valid circle
363
- this._center = null
364
- this._squareRadius = null
365
- this._exists = false
366
- }
367
- }
368
- return this
369
- }
370
-
371
- private _parseThroughtThreePoints(A: Point, B: Point, C: Point): Circle {
372
- let T = new Triangle(A, B, C), mAB = T.remarquables.mediators.AB.clone(),
373
- mAC = T.remarquables.mediators.AC.clone()
374
- this.parse(mAB.intersection(mAC).point, A)
375
-
376
- return this
377
- }
378
-
379
- }