pimath 0.1.39 → 0.1.40
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.
- package/dist/pimath.js +188 -159
- package/dist/pimath.js.map +1 -1
- package/package.json +4 -2
- package/src/algebra/equation.ts +556 -0
- package/src/algebra/equationSolver.ts +539 -0
- package/src/algebra/factor.ts +339 -0
- package/src/algebra/index.ts +11 -0
- package/src/algebra/linearSystem.ts +388 -0
- package/src/algebra/logicalset.ts +256 -0
- package/src/algebra/matrix.ts +474 -0
- package/src/algebra/monom.ts +1015 -0
- package/src/algebra/operations.ts +24 -0
- package/src/algebra/polyFactor.ts +668 -0
- package/src/algebra/polynom.ts +1394 -0
- package/src/analyze/solution.ts +115 -0
- package/src/analyze/tableOfSigns.ts +30 -0
- package/src/coefficients/fraction.ts +678 -0
- package/src/coefficients/index.ts +4 -0
- package/src/coefficients/nthRoot.ts +149 -0
- package/src/coefficients/root.ts +299 -0
- package/src/geometry/circle.ts +386 -0
- package/src/geometry/geomMath.ts +70 -0
- package/src/geometry/index.ts +10 -0
- package/src/geometry/line.ts +677 -0
- package/src/geometry/line3.ts +206 -0
- package/src/geometry/plane3.ts +170 -0
- package/src/geometry/point.ts +66 -0
- package/src/geometry/sphere3.ts +214 -0
- package/src/geometry/triangle.ts +354 -0
- package/src/geometry/vector.ts +341 -0
- package/src/helpers.ts +35 -0
- package/src/index.ts +60 -0
- package/src/numeric.ts +199 -0
- package/src/pimath.interface.ts +160 -0
- package/src/randomization/algebra/rndEquation.ts +41 -0
- package/src/randomization/algebra/rndMonom.ts +39 -0
- package/src/randomization/algebra/rndPolynom.ts +86 -0
- package/src/randomization/coefficient/rndFraction.ts +38 -0
- package/src/randomization/geometry/rndCircle.ts +27 -0
- package/src/randomization/geometry/rndLine.ts +37 -0
- package/src/randomization/geometry/rndLine3.ts +27 -0
- package/src/randomization/geometry/rndVector.ts +63 -0
- package/src/randomization/random.ts +91 -0
- package/src/randomization/rndHelpers.ts +102 -0
- package/src/randomization/rndTypes.ts +63 -0
- package/types/algebra/equationSolver.d.ts +3 -0
- package/types/algebra/equationSolver.d.ts.map +1 -1
- package/types/algebra/polyFactor.d.ts +5 -0
- package/types/algebra/polyFactor.d.ts.map +1 -1
- package/types/analyze/solution.d.ts +21 -0
- package/types/analyze/solution.d.ts.map +1 -0
- package/types/analyze/tableOfSigns.d.ts +9 -0
- package/types/analyze/tableOfSigns.d.ts.map +1 -0
- package/types/coefficients/root.d.ts +38 -0
- package/types/coefficients/root.d.ts.map +1 -0
- package/types/geometry/point.d.ts +1 -1
- package/types/geometry/point.d.ts.map +1 -1
- package/types/helpers.d.ts +1 -0
- package/types/helpers.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/numeric.d.ts +2 -0
- package/types/numeric.d.ts.map +1 -1
- package/types/pimath.interface.d.ts +26 -26
- package/types/pimath.interface.d.ts.map +1 -1
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
import type {compareSign, IExpression, InputValue, IPiMathObject} from "../pimath.interface"
|
|
2
|
+
import {Numeric} from "../numeric"
|
|
3
|
+
|
|
4
|
+
export enum FRAC_TYPE {
|
|
5
|
+
frac = 'frac',
|
|
6
|
+
dfrac = 'dfrac',
|
|
7
|
+
tfrac = 'tfrac'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The fraction class make possible to handle
|
|
12
|
+
* \\(\frac{a}{b}\\) or \\[\frac{a}{b}\\] values.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export class Fraction implements IPiMathObject<Fraction>, IExpression<Fraction> {
|
|
16
|
+
#approximative = false
|
|
17
|
+
#denominator = 1
|
|
18
|
+
#numerator = 1
|
|
19
|
+
#type: FRAC_TYPE = FRAC_TYPE.frac
|
|
20
|
+
|
|
21
|
+
constructor()
|
|
22
|
+
constructor(value: InputValue<Fraction>)
|
|
23
|
+
constructor(numerator: number, denominator: number)
|
|
24
|
+
constructor(decimal: number, periodLength: number)
|
|
25
|
+
constructor(value?: InputValue<Fraction>, denominatorOrPeriodic?: number) {
|
|
26
|
+
|
|
27
|
+
if (value !== undefined) {
|
|
28
|
+
this.parse(value, denominatorOrPeriodic)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return this
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Parse the value to get the numerator and denominator
|
|
37
|
+
* @param value : number or string to parse to get the fraction
|
|
38
|
+
* @param denominatorOrPeriodic (optional|number) : length of the periodic part: 2.333333 => 1 or denominator value
|
|
39
|
+
*/
|
|
40
|
+
public parse = (value: InputValue<Fraction>, denominatorOrPeriodic?: number): Fraction => {
|
|
41
|
+
let S: string[]
|
|
42
|
+
|
|
43
|
+
// A null value means a zero fraction.
|
|
44
|
+
if (value === "") {
|
|
45
|
+
this.#numerator = 0
|
|
46
|
+
this.#denominator = 1
|
|
47
|
+
return this
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
switch (typeof value) {
|
|
51
|
+
case "string":
|
|
52
|
+
// Split the string value in two parts: Numerator/Denominator
|
|
53
|
+
S = value.split('/')
|
|
54
|
+
|
|
55
|
+
// Security checks
|
|
56
|
+
if (S.length > 2) {
|
|
57
|
+
this.#numerator = NaN
|
|
58
|
+
// throw new Error(`The given value is not a valid fraction (${value})`)
|
|
59
|
+
}
|
|
60
|
+
if (S.map(x => x === '' || isNaN(Number(x))).includes(true)) {
|
|
61
|
+
this.#numerator = NaN
|
|
62
|
+
// throw new Error(`The given value is not a valid fraction (${value})`)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (S.length === 1) {
|
|
66
|
+
// No divide sign - it's a number
|
|
67
|
+
return this.parse(+S[0])
|
|
68
|
+
} else if (S.length === 2) {
|
|
69
|
+
// One divide signe
|
|
70
|
+
// We check if the denominator is zero
|
|
71
|
+
if (S[1] === '0') {
|
|
72
|
+
this.#numerator = NaN
|
|
73
|
+
this.#denominator = 1
|
|
74
|
+
} else {
|
|
75
|
+
this.#numerator = +S[0]
|
|
76
|
+
this.#denominator = +S[1]
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
// More than one divide sign ?
|
|
80
|
+
// This is not a fraction
|
|
81
|
+
this.#numerator = NaN
|
|
82
|
+
this.#denominator = 1
|
|
83
|
+
}
|
|
84
|
+
break
|
|
85
|
+
case "number":
|
|
86
|
+
if (Number.isSafeInteger(value)) {
|
|
87
|
+
// The given value is an integer
|
|
88
|
+
this.#numerator = +value
|
|
89
|
+
|
|
90
|
+
if (denominatorOrPeriodic === undefined || !Number.isSafeInteger(denominatorOrPeriodic)) {
|
|
91
|
+
this.#denominator = 1
|
|
92
|
+
} else {
|
|
93
|
+
this.#denominator = +denominatorOrPeriodic
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
// The given value is a float number
|
|
97
|
+
// Get the number of decimals after the float sign
|
|
98
|
+
const [, decimal] = (value.toString()).split('.')
|
|
99
|
+
const p: number = decimal ? decimal.length : 0
|
|
100
|
+
const power = Math.pow(10, p)
|
|
101
|
+
|
|
102
|
+
// Detect if the decimal part is periodic or not...
|
|
103
|
+
if (denominatorOrPeriodic === undefined) {
|
|
104
|
+
// Transform the float number in two integer
|
|
105
|
+
// 0.123 = 0.123*10^3 / 10^3
|
|
106
|
+
this.#numerator = value * power
|
|
107
|
+
this.#denominator = power
|
|
108
|
+
} else if (Number.isSafeInteger(denominatorOrPeriodic)) {
|
|
109
|
+
this.#numerator = value * power - Math.floor(value * Math.pow(10, p - denominatorOrPeriodic))
|
|
110
|
+
this.denominator = power - Math.pow(10, p - denominatorOrPeriodic)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this.#numerator = Numeric.numberCorrection(this.#numerator)
|
|
114
|
+
this.#denominator = Numeric.numberCorrection(this.#denominator)
|
|
115
|
+
|
|
116
|
+
this.reduce()
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
case "object":
|
|
120
|
+
if (value instanceof Fraction) {
|
|
121
|
+
this.#numerator = +value.numerator
|
|
122
|
+
this.#denominator = +value.denominator
|
|
123
|
+
}
|
|
124
|
+
break
|
|
125
|
+
}
|
|
126
|
+
return this
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public clone = (): Fraction => {
|
|
130
|
+
const F = new Fraction()
|
|
131
|
+
F.numerator = +this.#numerator
|
|
132
|
+
F.denominator = +this.#denominator
|
|
133
|
+
return F
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Display getter
|
|
137
|
+
public get tex(): string {
|
|
138
|
+
if (this.isInfinity()) {
|
|
139
|
+
return `${this.sign() === 1 ? '+' : '-'}\\infty`
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if (this.isExact()) {
|
|
144
|
+
if (this.#denominator === 1) {
|
|
145
|
+
return `${this.#numerator}`
|
|
146
|
+
} else if (this.#numerator < 0) {
|
|
147
|
+
return `-\\${this.#type}{ ${-this.#numerator} }{ ${this.#denominator} }`
|
|
148
|
+
} else {
|
|
149
|
+
return `\\${this.#type}{ ${this.#numerator} }{ ${this.#denominator} }`
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
return this.value.toFixed(3)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public get display(): string {
|
|
157
|
+
if (this.isExact()) {
|
|
158
|
+
if (this.#denominator === 1) {
|
|
159
|
+
return `${this.#numerator}`
|
|
160
|
+
} else {
|
|
161
|
+
return `${this.#numerator}/${this.#denominator}`
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
return this.value.toFixed(3)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public static average = (...fractions: (InputValue<Fraction>)[]): Fraction => {
|
|
169
|
+
const M = new Fraction().zero()
|
|
170
|
+
|
|
171
|
+
for (const f of fractions) {
|
|
172
|
+
M.add(f)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
M.divide(fractions.length)
|
|
176
|
+
|
|
177
|
+
return M
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public static isFraction(value: InputValue<Fraction>) {
|
|
181
|
+
if (value instanceof Fraction ||
|
|
182
|
+
(typeof value === "number" && !isNaN(+value))
|
|
183
|
+
) {
|
|
184
|
+
return true
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if(typeof value === "string"){
|
|
188
|
+
const [num, den] = value.split('/')
|
|
189
|
+
|
|
190
|
+
return !isNaN(+num) && !isNaN(+den)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return false
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public static max = (...fractions: InputValue<Fraction>[]): Fraction => {
|
|
198
|
+
let M = new Fraction(fractions[0])
|
|
199
|
+
|
|
200
|
+
for (const m of fractions) {
|
|
201
|
+
const compare = new Fraction(m)
|
|
202
|
+
if (compare.isGreater(M)) {
|
|
203
|
+
M = compare.clone()
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return M
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ------------------------------------------
|
|
211
|
+
// Compare functions
|
|
212
|
+
|
|
213
|
+
public static min = (...fractions: (InputValue<Fraction>)[]): Fraction => {
|
|
214
|
+
let M = new Fraction(fractions[0])
|
|
215
|
+
|
|
216
|
+
for (const m of fractions) {
|
|
217
|
+
const compare = new Fraction(m)
|
|
218
|
+
if (compare.isLesser(M)) {
|
|
219
|
+
M = compare.clone()
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return M
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public static sort = (fractions: (InputValue<Fraction>)[], reverse?: boolean): Fraction[] => {
|
|
227
|
+
const fractionsObject: Fraction[] = fractions.map(f => f instanceof Fraction ? f : new Fraction(f))
|
|
228
|
+
|
|
229
|
+
const sorted = fractionsObject.sort((a, b) => a.value - b.value)
|
|
230
|
+
|
|
231
|
+
if (reverse) {
|
|
232
|
+
sorted.reverse()
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return sorted
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public static unique = (fractions: (InputValue<Fraction>)[]): Fraction[] => {
|
|
239
|
+
const unique: Record<string, boolean> = {},
|
|
240
|
+
distinct: Fraction[] = []
|
|
241
|
+
|
|
242
|
+
fractions.forEach(x => {
|
|
243
|
+
if (!(x instanceof Fraction)) {
|
|
244
|
+
x = new Fraction(x)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (!unique[x.clone().reduce().tex]) {
|
|
248
|
+
distinct.push(x.clone())
|
|
249
|
+
unique[x.tex] = true
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
return distinct
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
public static xMultiply = (...values: (InputValue<Fraction>)[]): Fraction => {
|
|
257
|
+
const R = new Fraction()
|
|
258
|
+
// Parse the value.
|
|
259
|
+
// If it's a fraction, return a clone of it
|
|
260
|
+
// If it's an integer, return the fraction F/1
|
|
261
|
+
for (const value of values) {
|
|
262
|
+
|
|
263
|
+
const F = new Fraction(value)
|
|
264
|
+
R.numerator = R.numerator * F.numerator
|
|
265
|
+
R.denominator = R.denominator * F.denominator
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return R
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
public abs = (): this => {
|
|
272
|
+
this.#numerator = Math.abs(this.#numerator)
|
|
273
|
+
this.#denominator = Math.abs(this.#denominator)
|
|
274
|
+
return this
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public add = (F: InputValue<Fraction>): Fraction => {
|
|
278
|
+
if (F instanceof Fraction) {
|
|
279
|
+
const N: number = this.#numerator,
|
|
280
|
+
D: number = this.#denominator
|
|
281
|
+
|
|
282
|
+
this.#numerator = N * F.denominator + F.numerator * D
|
|
283
|
+
this.#denominator = D * F.denominator
|
|
284
|
+
} else {
|
|
285
|
+
return this.add(new Fraction(F))
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return this.reduce()
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
public amplify = (k: number): this => {
|
|
292
|
+
if (Number.isSafeInteger(k)) {
|
|
293
|
+
this.#numerator *= k
|
|
294
|
+
this.#denominator *= k
|
|
295
|
+
}
|
|
296
|
+
return this
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Simple function to determine if it's a fraction
|
|
301
|
+
*/
|
|
302
|
+
public areEquals = (...F: Fraction[]): boolean => {
|
|
303
|
+
return F.every(f => f.isEqual(F[0]))
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ------------------------------------------
|
|
307
|
+
/**
|
|
308
|
+
* Compare the current coefficient with another coefficient
|
|
309
|
+
* @param F (Coefficient) The coefficient to _compare
|
|
310
|
+
* @param sign (string| default is =): authorized values: =, <, <=, >, >= with some variations.
|
|
311
|
+
*/
|
|
312
|
+
public compare = (F: InputValue<Fraction>, sign?: compareSign): boolean => {
|
|
313
|
+
sign ??= '='
|
|
314
|
+
|
|
315
|
+
let compareFraction: Fraction
|
|
316
|
+
if (F instanceof Fraction) {
|
|
317
|
+
compareFraction = F.clone()
|
|
318
|
+
} else {
|
|
319
|
+
compareFraction = new Fraction(F)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
switch (sign) {
|
|
323
|
+
case '>':
|
|
324
|
+
return this.value > compareFraction.value
|
|
325
|
+
case ">=":
|
|
326
|
+
case "=>":
|
|
327
|
+
case "geq":
|
|
328
|
+
return this.value >= compareFraction.value
|
|
329
|
+
case "<":
|
|
330
|
+
return this.value < compareFraction.value
|
|
331
|
+
case "<=":
|
|
332
|
+
case "=<":
|
|
333
|
+
case "leq":
|
|
334
|
+
return this.value <= compareFraction.value
|
|
335
|
+
case "=":
|
|
336
|
+
return this.value === compareFraction.value
|
|
337
|
+
case "<>":
|
|
338
|
+
return this.value !== compareFraction.value
|
|
339
|
+
default:
|
|
340
|
+
return false
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
public get denominator(): number {
|
|
345
|
+
return this.#denominator
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
public set denominator(value: number) {
|
|
349
|
+
this.#denominator = value
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
public get dfrac(): this {
|
|
353
|
+
this.#type = FRAC_TYPE.dfrac
|
|
354
|
+
return this
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
public divide = (F: Fraction | number): Fraction => {
|
|
358
|
+
const Q = new Fraction(F)
|
|
359
|
+
|
|
360
|
+
if (Q.numerator === 0) {
|
|
361
|
+
return new Fraction().infinite()
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const N: number = this.#numerator,
|
|
365
|
+
D: number = this.#denominator
|
|
366
|
+
|
|
367
|
+
this.#numerator = N * Q.denominator
|
|
368
|
+
this.#denominator = D * Q.numerator
|
|
369
|
+
return this.reduce()
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
public get frac(): this {
|
|
373
|
+
this.#type = FRAC_TYPE.frac
|
|
374
|
+
return this
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
public infinite = (): this => {
|
|
378
|
+
this.#numerator = Infinity
|
|
379
|
+
this.#denominator = 1
|
|
380
|
+
return this
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
public invalid = (): this => {
|
|
384
|
+
this.#numerator = NaN
|
|
385
|
+
this.#denominator = 1
|
|
386
|
+
return this
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
public inverse = (): this => {
|
|
390
|
+
const sign = this.sign()
|
|
391
|
+
const n = Math.abs(this.#numerator)
|
|
392
|
+
this.#numerator = Math.abs(this.#denominator) * sign
|
|
393
|
+
this.#denominator = n
|
|
394
|
+
|
|
395
|
+
return this
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
public isApproximative = (): boolean => {
|
|
399
|
+
return this.#approximative ||
|
|
400
|
+
this.#numerator.toString().length >= 15 && this.#denominator.toString().length >= 15
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
public isEqual = (than: Fraction | number): boolean => {
|
|
404
|
+
return this.compare(than, '=')
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
public isEven = (): boolean => {
|
|
408
|
+
return this.isRelative() && this.value % 2 === 0
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
public isExact = (): boolean => {
|
|
412
|
+
return !this.isApproximative()
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
public isFinite = (): boolean => {
|
|
416
|
+
return !this.isInfinity() && !this.isNaN()
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
public isGeq = (than: Fraction | number): boolean => {
|
|
420
|
+
return this.compare(than, '>=')
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
public isGreater = (than: Fraction | number): boolean => {
|
|
424
|
+
return this.compare(than, '>')
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
public isInfinity = (): boolean => {
|
|
428
|
+
return Math.abs(this.#numerator) === Infinity
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
public isInverted = (p: Fraction): boolean => {
|
|
432
|
+
return this.isEqual(new Fraction().one().divide(p.clone()))
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
public isLeq = (than: Fraction | number): boolean => {
|
|
436
|
+
return this.compare(than, '<=')
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/* Compare shortcuts */
|
|
440
|
+
public isLesser = (than: Fraction | number): boolean => {
|
|
441
|
+
return this.compare(than, '<')
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
public isNaN = (): boolean => {
|
|
445
|
+
return isNaN(this.#numerator)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
public isNatural = (): boolean => {
|
|
449
|
+
return this.isRelative() && this.isPositive()
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
public isNegative = (): boolean => {
|
|
453
|
+
return this.sign() === -1
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
public isNegativeOne = (): boolean => {
|
|
457
|
+
return this.#numerator === -1 && this.#denominator === 1
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// ------------------------------------------
|
|
461
|
+
|
|
462
|
+
public isNotEqual = (than: Fraction | number): boolean => {
|
|
463
|
+
return this.compare(than, '<>')
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
public isNotZero = (): boolean => {
|
|
467
|
+
return this.#numerator !== 0
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
public isOdd = (): boolean => {
|
|
471
|
+
return this.isRelative() && this.value % 2 === 1
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
public isOne = (): boolean => {
|
|
475
|
+
return this.#numerator === 1 && this.#denominator === 1
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
public isOpposite = (p: Fraction): boolean => {
|
|
479
|
+
return this.isEqual(p.clone().opposite())
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
public isPositive = (): boolean => {
|
|
483
|
+
return this.sign() === 1
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
public isRational = (): boolean => {
|
|
487
|
+
return !this.isRelative()
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
public isReduced = (): boolean => {
|
|
491
|
+
return Math.abs(Numeric.gcd(this.#numerator, this.#denominator)) === 1
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
public isRelative = (): boolean => {
|
|
495
|
+
return this.clone().reduce().denominator === 1
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
public isSquare = (): boolean => {
|
|
499
|
+
return Math.sqrt(this.#numerator) % 1 === 0 && Math.sqrt(this.#denominator) % 1 === 0
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
public isStrictlyNegative = (): boolean => {
|
|
503
|
+
return this.value < 0
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
public isStrictlyPositive = (): boolean => {
|
|
507
|
+
return this.value > 0
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Mathematical operations specific to fractions
|
|
511
|
+
public isZero = (): boolean => {
|
|
512
|
+
return this.#numerator === 0
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
public multiply = (F: Fraction | number): this => {
|
|
516
|
+
// Parse the value.
|
|
517
|
+
// If it's a fraction, return a clone of it
|
|
518
|
+
// If it's an integer, return the fraction F/1
|
|
519
|
+
const Q = new Fraction(F)
|
|
520
|
+
|
|
521
|
+
this.#numerator = this.#numerator * Q.numerator
|
|
522
|
+
this.#denominator = this.#denominator * Q.denominator
|
|
523
|
+
|
|
524
|
+
return this.reduce()
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// ------------------------------------------
|
|
528
|
+
public get numerator(): number {
|
|
529
|
+
return this.#numerator
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
public set numerator(value: number) {
|
|
533
|
+
this.#numerator = value
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
public one = (): this => {
|
|
537
|
+
this.#numerator = 1
|
|
538
|
+
this.#denominator = 1
|
|
539
|
+
return this
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
public opposite = (): this => {
|
|
543
|
+
this.#numerator = -this.#numerator
|
|
544
|
+
return this
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
public pow = (p: number | Fraction): Fraction => {
|
|
548
|
+
if (p instanceof Fraction) {
|
|
549
|
+
return this.pow(p.value)
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
this.reduce()
|
|
553
|
+
if (p < 0) {
|
|
554
|
+
this.inverse()
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Check if numerator and denominator are roots of...
|
|
558
|
+
// otherwise, convert to numeric.
|
|
559
|
+
const controlNumerator = Math.floor(Math.pow(this.#numerator, Math.abs(p))),
|
|
560
|
+
controlDenominator = Math.floor(Math.pow(this.#denominator, Math.abs(p)))
|
|
561
|
+
|
|
562
|
+
if (controlNumerator ** Math.abs(p) === this.#numerator
|
|
563
|
+
&&
|
|
564
|
+
controlDenominator ** Math.abs(p) === this.#denominator) {
|
|
565
|
+
this.#numerator = this.#numerator ** Math.abs(p)
|
|
566
|
+
this.#denominator = this.#denominator ** Math.abs(p)
|
|
567
|
+
} else {
|
|
568
|
+
this.#numerator = this.#numerator ** Math.abs(p)
|
|
569
|
+
this.#denominator = this.#denominator ** Math.abs(p)
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
return this
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// ------------------------------------------
|
|
576
|
+
public reduce = (): this => {
|
|
577
|
+
const g = Numeric.gcd(this.#numerator, this.#denominator)
|
|
578
|
+
this.#numerator = this.#numerator / g
|
|
579
|
+
this.#denominator = this.#denominator / g
|
|
580
|
+
|
|
581
|
+
if (this.#denominator < 0) {
|
|
582
|
+
this.#denominator = -this.#denominator
|
|
583
|
+
this.#numerator = -this.#numerator
|
|
584
|
+
}
|
|
585
|
+
return this
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// ------------------------------------------
|
|
589
|
+
// Getter and setter
|
|
590
|
+
|
|
591
|
+
public root = (p: number): this => {
|
|
592
|
+
|
|
593
|
+
// Check if they are perfect roots..
|
|
594
|
+
if (p === 0) {
|
|
595
|
+
return this
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// If negative, inverse the fraction
|
|
599
|
+
if (p < 0) {
|
|
600
|
+
this.inverse()
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// if p is not a safe integer, throw error
|
|
604
|
+
if (!Number.isSafeInteger(p)) {
|
|
605
|
+
throw new Error("The root must be an integer.")
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// if the fraction is negative and the root is even, throw error
|
|
609
|
+
if (this.isNegative() && p % 2 === 0) {
|
|
610
|
+
throw new Error("The root of a negative number must be odd.")
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// get the sign of the fraction and make it positive
|
|
614
|
+
const sign = this.sign()
|
|
615
|
+
this.abs()
|
|
616
|
+
|
|
617
|
+
// Reduce the fraction
|
|
618
|
+
this.reduce()
|
|
619
|
+
|
|
620
|
+
// Check if numerator and denominator are roots of...
|
|
621
|
+
// otherwise, convert to numeric.
|
|
622
|
+
const controlNumerator = Math.floor(Math.pow(this.#numerator, Math.abs(1 / p))),
|
|
623
|
+
controlDenominator = Math.floor(Math.pow(this.#denominator, Math.abs(1 / p)))
|
|
624
|
+
|
|
625
|
+
this.#numerator = Math.pow(this.#numerator, Math.abs(1 / p))
|
|
626
|
+
this.#denominator = Math.pow(this.#denominator, Math.abs(1 / p))
|
|
627
|
+
|
|
628
|
+
if (controlNumerator !== this.#numerator
|
|
629
|
+
||
|
|
630
|
+
controlDenominator !== this.#denominator) {
|
|
631
|
+
// The fraction is not a perfect root - make it approximative
|
|
632
|
+
this.#numerator = this.#numerator / this.#denominator
|
|
633
|
+
this.#denominator = 1
|
|
634
|
+
this.#approximative = true
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Restore the sign
|
|
638
|
+
this.multiply(sign)
|
|
639
|
+
|
|
640
|
+
return this
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
public sign = (): 1 | -1 => {
|
|
644
|
+
return (this.#numerator * this.#denominator >= 0) ? 1 : -1
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
public sqrt = (): this => {
|
|
648
|
+
return this.root(2)
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
public subtract = (F: Fraction | number): Fraction => {
|
|
652
|
+
if (F instanceof Fraction) {
|
|
653
|
+
return this.add(F.clone().opposite())
|
|
654
|
+
} else {
|
|
655
|
+
return this.add(-F)
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
public get texWithSign(): string {
|
|
660
|
+
return this.isPositive() ? `+${this.tex}` : this.tex
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
public get tfrac(): this {
|
|
664
|
+
this.#type = FRAC_TYPE.tfrac
|
|
665
|
+
return this
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
public get value(): number {
|
|
669
|
+
const result = this.#numerator / this.#denominator
|
|
670
|
+
return result === 0 ? 0 : result
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
public zero = (): this => {
|
|
674
|
+
this.#numerator = 0
|
|
675
|
+
this.#denominator = 1
|
|
676
|
+
return this
|
|
677
|
+
}
|
|
678
|
+
}
|