pimath 0.1.39 → 0.2.0
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 +3127 -2865
- package/dist/pimath.js.map +1 -1
- package/package.json +16 -12
- package/src/algebra/equation.ts +558 -0
- package/src/algebra/equationSolver.ts +488 -0
- package/src/algebra/factor.ts +338 -0
- package/src/algebra/index.ts +11 -0
- package/src/algebra/linearSystem.ts +439 -0
- package/src/algebra/logicalset.ts +255 -0
- package/src/algebra/matrix.ts +474 -0
- package/src/algebra/monom.ts +977 -0
- package/src/algebra/operations.ts +23 -0
- package/src/algebra/polyFactor.ts +668 -0
- package/src/algebra/polynom.ts +1247 -0
- package/src/analyze/index.ts +4 -0
- package/src/analyze/solution.ts +178 -0
- package/src/analyze/tableOfSigns.ts +30 -0
- package/src/coefficients/fraction.ts +718 -0
- package/src/coefficients/index.ts +4 -0
- package/src/coefficients/root.ts +346 -0
- package/src/geometry/TupleN.ts +128 -0
- package/src/geometry/circle.ts +456 -0
- package/src/geometry/geomMath.ts +71 -0
- package/src/geometry/index.ts +11 -0
- package/src/geometry/line.ts +653 -0
- package/src/geometry/line3.ts +211 -0
- package/src/geometry/plane3.ts +179 -0
- package/src/geometry/point.ts +104 -0
- package/src/geometry/sphere3.ts +214 -0
- package/src/geometry/triangle.ts +482 -0
- package/src/geometry/vector.ts +225 -0
- package/src/helpers.ts +35 -0
- package/src/index.ts +61 -0
- package/src/numeric.ts +196 -0
- package/src/pimath.interface.ts +162 -0
- package/src/randomization/algebra/rndEquation.ts +41 -0
- package/src/randomization/algebra/rndMonom.ts +39 -0
- package/src/randomization/algebra/rndPolynom.ts +100 -0
- package/src/randomization/coefficient/rndFraction.ts +38 -0
- package/src/randomization/geometry/rndCircle.ts +27 -0
- package/src/randomization/geometry/rndLine.ts +35 -0
- package/src/randomization/geometry/rndLine3.ts +27 -0
- package/src/randomization/geometry/rndVector.ts +63 -0
- package/src/randomization/random.ts +89 -0
- package/src/randomization/rndHelpers.ts +102 -0
- package/src/randomization/rndTypes.ts +67 -0
- package/types/algebra/equation.d.ts +18 -17
- package/types/algebra/equation.d.ts.map +1 -1
- package/types/algebra/equationSolver.d.ts +7 -3
- package/types/algebra/equationSolver.d.ts.map +1 -1
- package/types/algebra/factor.d.ts +1 -1
- package/types/algebra/factor.d.ts.map +1 -1
- package/types/algebra/linearSystem.d.ts +23 -6
- package/types/algebra/linearSystem.d.ts.map +1 -1
- package/types/algebra/logicalset.d.ts +1 -1
- package/types/algebra/logicalset.d.ts.map +1 -1
- package/types/algebra/monom.d.ts +1 -6
- package/types/algebra/monom.d.ts.map +1 -1
- package/types/algebra/operations.d.ts.map +1 -1
- package/types/algebra/polyFactor.d.ts +9 -4
- package/types/algebra/polyFactor.d.ts.map +1 -1
- package/types/algebra/polynom.d.ts +10 -7
- package/types/algebra/polynom.d.ts.map +1 -1
- package/types/analyze/index.d.ts +2 -0
- package/types/analyze/index.d.ts.map +1 -0
- package/types/analyze/solution.d.ts +27 -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/fraction.d.ts +14 -12
- package/types/coefficients/fraction.d.ts.map +1 -1
- package/types/coefficients/index.d.ts +1 -1
- package/types/coefficients/index.d.ts.map +1 -1
- package/types/coefficients/root.d.ts +41 -0
- package/types/coefficients/root.d.ts.map +1 -0
- package/types/geometry/TupleAbstract.d.ts +22 -0
- package/types/geometry/TupleAbstract.d.ts.map +1 -0
- package/types/geometry/TupleN.d.ts +24 -0
- package/types/geometry/TupleN.d.ts.map +1 -0
- package/types/geometry/circle.d.ts +26 -17
- package/types/geometry/circle.d.ts.map +1 -1
- package/types/geometry/geomMath.d.ts +2 -1
- package/types/geometry/geomMath.d.ts.map +1 -1
- package/types/geometry/index.d.ts.map +1 -1
- package/types/geometry/line.d.ts +21 -30
- package/types/geometry/line.d.ts.map +1 -1
- package/types/geometry/line3.d.ts +19 -19
- package/types/geometry/line3.d.ts.map +1 -1
- package/types/geometry/matrix.d.ts +11 -11
- package/types/geometry/plane3.d.ts +9 -9
- package/types/geometry/plane3.d.ts.map +1 -1
- package/types/geometry/point.d.ts +12 -7
- package/types/geometry/point.d.ts.map +1 -1
- package/types/geometry/triangle.d.ts +68 -23
- package/types/geometry/triangle.d.ts.map +1 -1
- package/types/geometry/vector.d.ts +24 -44
- package/types/geometry/vector.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 +6 -4
- 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 +38 -44
- package/types/pimath.interface.d.ts.map +1 -1
- package/types/randomization/algebra/rndPolynom.d.ts.map +1 -1
- package/types/randomization/coefficient/rndFraction.d.ts +1 -1
- package/types/randomization/coefficient/rndFraction.d.ts.map +1 -1
- package/types/randomization/geometry/rndLine.d.ts.map +1 -1
- package/types/randomization/random.d.ts +3 -2
- package/types/randomization/random.d.ts.map +1 -1
- package/types/randomization/rndTypes.d.ts +15 -10
- package/types/randomization/rndTypes.d.ts.map +1 -1
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import {Fraction} from "./fraction"
|
|
2
|
+
import type {IExpression, InputValue, IPiMathObject} from "../pimath.interface"
|
|
3
|
+
import {stripParenthesis} from "../helpers"
|
|
4
|
+
import {Numeric} from "../numeric"
|
|
5
|
+
|
|
6
|
+
export class Root implements IPiMathObject<Root>, IExpression<Root> {
|
|
7
|
+
#factor: Fraction
|
|
8
|
+
#index: number
|
|
9
|
+
#radical: Fraction
|
|
10
|
+
#withSign = false
|
|
11
|
+
|
|
12
|
+
constructor(value?: InputValue<Root | Fraction>) {
|
|
13
|
+
this.#index = 2
|
|
14
|
+
this.#factor = new Fraction().zero()
|
|
15
|
+
this.#radical = new Fraction().zero()
|
|
16
|
+
|
|
17
|
+
if (value) {
|
|
18
|
+
this.parse(value)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
return this
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
parse(value: InputValue<Root | Fraction>): this {
|
|
26
|
+
// should be able to parse "display" roots.
|
|
27
|
+
// sqrt12 or sqrt(12) or sqrt(12/5) => [2, 12 or 12/5, 1]
|
|
28
|
+
// root(n)10 or root(n)(10) or root(n)(10/3) => [n, 10 or 10/3, 1]
|
|
29
|
+
// 7sqrt12 or 7sqrt(12) or 7sqrt(12/5) => [2, 12 or 12/5, 7]
|
|
30
|
+
// 7root(n)10 or 7root(n)(10) or 7root(n)(10/3) => [n, 10 or 10/3, 7]
|
|
31
|
+
|
|
32
|
+
if (value instanceof Root) {
|
|
33
|
+
this.index = value.index
|
|
34
|
+
this.radical = value.radical.clone()
|
|
35
|
+
this.factor = value.factor.clone()
|
|
36
|
+
|
|
37
|
+
return this
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (value instanceof Fraction) {
|
|
41
|
+
this.index = 2
|
|
42
|
+
this.factor = value.clone()
|
|
43
|
+
this.radical.one()
|
|
44
|
+
|
|
45
|
+
return this
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (typeof value === "string") {
|
|
49
|
+
if (value.includes('sqrt')) {
|
|
50
|
+
return this.#parse_sqrt(value)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (value.includes('root')) {
|
|
54
|
+
return this.#parse_root(value)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.index = 2
|
|
59
|
+
this.factor = new Fraction(value)
|
|
60
|
+
this.radical.one()
|
|
61
|
+
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
clone(): Root {
|
|
66
|
+
return new Root().from(this.index, this.radical, this.factor)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get tex(): string {
|
|
70
|
+
// b \sqrt{}
|
|
71
|
+
// b
|
|
72
|
+
// \sqrt{}
|
|
73
|
+
// -\sqrt{}
|
|
74
|
+
|
|
75
|
+
// Force the plus sign.
|
|
76
|
+
const plus = this.#withSign && this.factor.isPositive() ? '+' : ''
|
|
77
|
+
|
|
78
|
+
// There is no radical - output the factor
|
|
79
|
+
if (this.#radical.isZero()) return `${plus}${this.#factor.tex}`
|
|
80
|
+
|
|
81
|
+
// The radical has an index of 1 - no radical.
|
|
82
|
+
if (this.index === 1) return `${plus}${this.factor.clone().multiply(this.radical).tex}`
|
|
83
|
+
|
|
84
|
+
// Make the root part
|
|
85
|
+
const rad = this.index === 2
|
|
86
|
+
? `\\sqrt{ ${this.#radical.tex} }`
|
|
87
|
+
: `\\sqrt[ ${this.index} ]{ ${this.#radical.tex} }`
|
|
88
|
+
|
|
89
|
+
if (this.#factor.isUnit()) {
|
|
90
|
+
return this.#withSign
|
|
91
|
+
? `${this.#factor.isOne() ? plus : '-'} ${rad}`
|
|
92
|
+
: `${this.#factor.isOne() ? '' : '-'}${rad}`
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return `${plus}${this.#factor.tex} ${rad}`
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get display(): string {
|
|
99
|
+
const plus = this.#withSign && this.factor.isPositive() ? '+' : ''
|
|
100
|
+
|
|
101
|
+
// There is no radical - output the factor
|
|
102
|
+
if (this.#radical.isZero()) return `${plus}${this.#factor.display}`
|
|
103
|
+
|
|
104
|
+
// The radical has an index of 1 - no radical.
|
|
105
|
+
if (this.index === 1) return `${plus}${this.factor.clone().multiply(this.radical).display}`
|
|
106
|
+
|
|
107
|
+
// Make the root part
|
|
108
|
+
const rad = this.index === 2
|
|
109
|
+
? `sqrt(${this.#radical.tex})`
|
|
110
|
+
: `root(${this.index})(${this.#radical.display})`
|
|
111
|
+
|
|
112
|
+
if (this.#factor.isUnit()) return `${this.#factor.isOne() ? plus : '-'}${rad}`
|
|
113
|
+
|
|
114
|
+
return `${plus}${this.#factor.display}${rad}`
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
add(value: InputValue<Root>): this {
|
|
118
|
+
// start by reducing
|
|
119
|
+
this.reduce()
|
|
120
|
+
const rt = new Root(value).reduce()
|
|
121
|
+
|
|
122
|
+
if (
|
|
123
|
+
this.index !== rt.index ||
|
|
124
|
+
!this.radical.isEqual(rt.radical)
|
|
125
|
+
) {
|
|
126
|
+
throw new Error("Add can only be done with two same index and radical")
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.factor.add(rt.factor)
|
|
130
|
+
|
|
131
|
+
return this
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
divide(value: InputValue<Root>): this {
|
|
135
|
+
return this.multiply(new Root(value).inverse())
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
get factor(): Fraction {
|
|
139
|
+
return this.#factor
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
set factor(value: Fraction) {
|
|
143
|
+
this.#factor = value
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
from(index: number, radical: InputValue<Fraction>, factor?: InputValue<Fraction>): this {
|
|
147
|
+
// set the index
|
|
148
|
+
this.index = index
|
|
149
|
+
|
|
150
|
+
// set the racial
|
|
151
|
+
this.radical = new Fraction(radical)
|
|
152
|
+
|
|
153
|
+
// set the factor if any
|
|
154
|
+
this.factor = factor ? new Fraction(factor) : new Fraction().one()
|
|
155
|
+
|
|
156
|
+
return this
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* convert to root(index)(radical), without factor
|
|
161
|
+
*/
|
|
162
|
+
group(): this {
|
|
163
|
+
this.radical.multiply(this.factor.pow(this.index))
|
|
164
|
+
this.factor.one()
|
|
165
|
+
|
|
166
|
+
return this
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
get index(): number {
|
|
170
|
+
return this.#index
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
set index(value: number) {
|
|
174
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
175
|
+
throw new Error("Index must be a strictly positive integer.")
|
|
176
|
+
}
|
|
177
|
+
this.#index = value
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
get indexAsPow(): Fraction {
|
|
181
|
+
return new Fraction(this.index).inverse()
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
inverse(): this {
|
|
185
|
+
this.factor.inverse()
|
|
186
|
+
this.radical.inverse()
|
|
187
|
+
return this
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
isEqual(root: Root): boolean {
|
|
191
|
+
return this.value === root.value
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
isOne(): boolean {
|
|
195
|
+
return this.factor.isOne() && this.radical.isOne()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
isRational(): boolean {
|
|
199
|
+
const reduced = this.clone().reduce()
|
|
200
|
+
|
|
201
|
+
if(reduced.radical.isOne()) return reduced.factor.exact
|
|
202
|
+
|
|
203
|
+
if(reduced.index===1) return reduced.factor.exact && reduced.radical.exact
|
|
204
|
+
|
|
205
|
+
return false
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
isZero(): boolean {
|
|
209
|
+
return this.factor.isZero() || this.radical.isZero()
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
multiply(value: InputValue<Root>): this {
|
|
213
|
+
const rt = new Root(value)
|
|
214
|
+
|
|
215
|
+
this.factor.multiply(rt.factor)
|
|
216
|
+
|
|
217
|
+
if (this.index === rt.index) {
|
|
218
|
+
this.radical.multiply(rt.radical)
|
|
219
|
+
return this
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (this.radical.isEqual(rt.radical)) {
|
|
223
|
+
const F = this.indexAsPow.add(rt.indexAsPow).reduce()
|
|
224
|
+
this.index = F.denominator
|
|
225
|
+
this.radical = this.radical.pow(F.numerator)
|
|
226
|
+
return this
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
throw new Error('Multiply can only be done if radical or index as equals.')
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
one(): this {
|
|
233
|
+
this.radical.one()
|
|
234
|
+
this.factor.one()
|
|
235
|
+
|
|
236
|
+
return this
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
opposite(): this {
|
|
240
|
+
this.factor.opposite()
|
|
241
|
+
return this
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
pow(value: number): this {
|
|
245
|
+
this.factor.pow(value)
|
|
246
|
+
|
|
247
|
+
const g = Numeric.gcd(this.index, value)
|
|
248
|
+
this.index = this.index / g
|
|
249
|
+
this.radical.pow(value / g)
|
|
250
|
+
|
|
251
|
+
return this
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
get radical(): Fraction {
|
|
255
|
+
return this.#radical
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
set radical(value: Fraction) {
|
|
259
|
+
this.#radical = value
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
reduce(): this {
|
|
263
|
+
// 1. extract roots
|
|
264
|
+
// 2. avoid roots at denominator.
|
|
265
|
+
|
|
266
|
+
// Remove the roots at denominator
|
|
267
|
+
if (this.radical.isRational()) {
|
|
268
|
+
const den = this.radical.denominator
|
|
269
|
+
this.radical.denominator = 1
|
|
270
|
+
this.radical.numerator *= den
|
|
271
|
+
|
|
272
|
+
this.factor.divide(den)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Extract the greatest root from.
|
|
276
|
+
const greatest = Numeric.greatestPower(this.radical.value, this.index)
|
|
277
|
+
|
|
278
|
+
this.factor.multiply(Math.pow(greatest, 1 / this.index))
|
|
279
|
+
this.radical.divide(greatest)
|
|
280
|
+
|
|
281
|
+
return this
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
root(value: number): this {
|
|
285
|
+
this.group()
|
|
286
|
+
this.index = this.index * value
|
|
287
|
+
return this
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
sqrt(): this {
|
|
291
|
+
return this.root(2)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
subtract(value: InputValue<Root>): this {
|
|
295
|
+
const rt = new Root(value)
|
|
296
|
+
|
|
297
|
+
return this.add(rt.opposite())
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
public get value(): number {
|
|
301
|
+
return Numeric.numberCorrection(this.factor.value * Math.pow(this.radical.value, 1 / this.index))
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
get withSign(): this {
|
|
305
|
+
this.#withSign = true
|
|
306
|
+
return this
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
get withoutSign(): this {
|
|
310
|
+
this.#withSign = false
|
|
311
|
+
return this
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
zero(): this {
|
|
315
|
+
this.radical.zero()
|
|
316
|
+
this.factor.zero()
|
|
317
|
+
return this
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
#parse_root(value: string): this {
|
|
321
|
+
// value = a root(n)b or a root(n)(b)
|
|
322
|
+
const [factor, index_radical] = value.split('root')
|
|
323
|
+
const [index, radical] = index_radical.split(')')
|
|
324
|
+
|
|
325
|
+
this.index = +stripParenthesis(index)
|
|
326
|
+
|
|
327
|
+
this.radical = new Fraction(stripParenthesis(radical))
|
|
328
|
+
|
|
329
|
+
this.factor = factor === '' ? new Fraction().one() : new Fraction(factor)
|
|
330
|
+
|
|
331
|
+
return this
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
#parse_sqrt(value: string): this {
|
|
335
|
+
// value = asqrtb
|
|
336
|
+
const [factor, radical] = value.split('sqrt')
|
|
337
|
+
|
|
338
|
+
this.index = 2
|
|
339
|
+
|
|
340
|
+
this.radical = new Fraction(stripParenthesis(radical))
|
|
341
|
+
|
|
342
|
+
this.factor = factor === '' ? new Fraction().one() : new Fraction(factor)
|
|
343
|
+
|
|
344
|
+
return this
|
|
345
|
+
}
|
|
346
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POint module contains everything necessary to handle 2d Points
|
|
3
|
+
* It's a "wrapper" of the Vector class.
|
|
4
|
+
* @module Point
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {Fraction} from "../coefficients"
|
|
8
|
+
import type {InputValue} from "../pimath.interface"
|
|
9
|
+
|
|
10
|
+
export abstract class TupleN {
|
|
11
|
+
#array: Fraction[] = []
|
|
12
|
+
#onChange?: () => void
|
|
13
|
+
|
|
14
|
+
constructor(...values: InputValue<Fraction>[]) {
|
|
15
|
+
this.#array = values.map(x => new Fraction(x))
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
public abstract clone(): void
|
|
19
|
+
|
|
20
|
+
public copy(): Fraction[] {
|
|
21
|
+
return this.#array.map(x => x.clone())
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
abstract get tex(): string
|
|
25
|
+
|
|
26
|
+
abstract get display(): string
|
|
27
|
+
|
|
28
|
+
get array(): Fraction[] {
|
|
29
|
+
return this.#array
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set array(value: Fraction[]) {
|
|
33
|
+
this.#array = value
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get dimension(): number {
|
|
37
|
+
return this.array.length
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public fromString(value: string): this {
|
|
41
|
+
// Remove the first letter if it's a parenthesis.
|
|
42
|
+
if (value.startsWith('(')) {
|
|
43
|
+
value = value.substring(1)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Remove the last letter if it's a parenthesis.
|
|
47
|
+
if (value.endsWith(')')) {
|
|
48
|
+
value = value.substring(0, value.length - 1)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Split comma, semi colon or single space.
|
|
52
|
+
const components = value.split(/[,;\s]/g)
|
|
53
|
+
.filter((v) => v.trim() !== '')
|
|
54
|
+
|
|
55
|
+
// there must be at least two Pages.
|
|
56
|
+
if (components.length < 2) {
|
|
57
|
+
return this
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Validate the fraction values.
|
|
61
|
+
this.#array = components.map(x => new Fraction(x))
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get onChange(): undefined | (() => void) {
|
|
66
|
+
return this.#onChange
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
set onChange(value: undefined | (() => void)) {
|
|
70
|
+
this.#onChange = value
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
setDimension(value = 2): this {
|
|
74
|
+
if (value < 2) {
|
|
75
|
+
throw new Error('Dimension must be at least 2')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (value < this.dimension) {
|
|
79
|
+
this.#array = this.#array.slice(0, value)
|
|
80
|
+
} else if (value > this.dimension) {
|
|
81
|
+
for (let i = this.dimension; i < value; i++) {
|
|
82
|
+
this.#array.push(new Fraction(0))
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return this
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get x(): Fraction {
|
|
90
|
+
return this.#array[0]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
set x(value: Fraction | number | string) {
|
|
94
|
+
this.#array[0] = new Fraction(value)
|
|
95
|
+
this.#onChange?.()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get y(): Fraction {
|
|
99
|
+
return this.#array[1]
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
set y(value: Fraction | number | string) {
|
|
103
|
+
this.#array[1] = new Fraction(value)
|
|
104
|
+
this.#onChange?.()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get z(): Fraction {
|
|
108
|
+
if (this.dimension < 3) {
|
|
109
|
+
throw new Error('Vector is not 3D')
|
|
110
|
+
}
|
|
111
|
+
return this.#array[2]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
set z(value: Fraction | number | string) {
|
|
115
|
+
if (this.dimension < 3) {
|
|
116
|
+
throw new Error('Vector is not 3D')
|
|
117
|
+
}
|
|
118
|
+
this.#array[2] = new Fraction(value)
|
|
119
|
+
this.#onChange?.()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
zero = (): this => {
|
|
123
|
+
this.#array.forEach(x => x.zero())
|
|
124
|
+
this.#onChange?.()
|
|
125
|
+
return this
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|