feat: Implement Vector type (#28)
All checks were successful
/ test (push) Successful in 18s
All checks were successful
/ test (push) Successful in 18s
The Vector type is simply a generic type for built-in JavaScript Arrays. The parameter type is the type of all of the entries of the Array. The Vector type also supports inhomogeneous arrays by using the special type `Unknown` as the argument type, but note that when computing with inhomogeneous arrays, method dispatch must be performed separately for every entry in a calculation, making all operations considerably slower than on homogeneous Vector instances. Note also that arithmetic operations on nested Vectors, e.g. `Vector(Vector(NumberT))` are defined so as to interpret such entities as ordinary matrices, represented in row-major format (i.e., the component `Vector(NumberT)` items of such an entity are the _rows_ of the matrix. Reviewed-on: #28 Co-authored-by: Glen Whitney <glen@studioinfinity.org> Co-committed-by: Glen Whitney <glen@studioinfinity.org>
This commit is contained in:
parent
0765ba7202
commit
95d81d0338
47 changed files with 1204 additions and 122 deletions
70
src/vector/helpers.js
Normal file
70
src/vector/helpers.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import {Vector} from './Vector.js'
|
||||
import {Returns, ReturnType, Undefined} from '#core/Type.js'
|
||||
import {Any, match} from '#core/TypePatterns.js'
|
||||
|
||||
export const promoteUnary = name => match(Vector, (math, V, strategy) => {
|
||||
const compOp = math.resolve(name, V.Component, strategy)
|
||||
return Returns(Vector(ReturnType(compOp)), v => v.map(elt => compOp(elt)))
|
||||
})
|
||||
|
||||
export const distributeFirst = name => match(
|
||||
[Vector, Any],
|
||||
(math, [V, E], strategy) => {
|
||||
const compOp = math.resolve(name, [V.Component, E], strategy)
|
||||
return Returns(
|
||||
Vector(ReturnType(compOp)), (v, e) => v.map(f => compOp(f, e)))
|
||||
})
|
||||
|
||||
export const distributeSecond = name => match(
|
||||
[Any, Vector],
|
||||
(math, [E, V], strategy) => {
|
||||
const compOp = math.resolve(name, [E, V.Component], strategy)
|
||||
return Returns(
|
||||
Vector(ReturnType(compOp)), (e, v) => v.map(f => compOp(e, f)))
|
||||
})
|
||||
|
||||
export const promoteBinary = name => [
|
||||
distributeFirst(name),
|
||||
distributeSecond(name),
|
||||
match([Vector, Vector], (math, [V, W], strategy) => {
|
||||
const VComp = V.Component
|
||||
const WComp = W.Component
|
||||
// special case: if the vector nesting depths do not match,
|
||||
// we operate between the elements of the deeper one and the entire
|
||||
// more shallow one:
|
||||
if (V.vectorDepth > W.vectorDepth) {
|
||||
const compOp = math.resolve(name, [VComp, W], strategy)
|
||||
return Returns(
|
||||
Vector(ReturnType(compOp)), (v, w) => v.map(f => compOp(f, w)))
|
||||
}
|
||||
if (V.vectorDepth < W.vectorDepth) {
|
||||
const compOp = math.resolve(name, [V, WComp], strategy)
|
||||
return Returns(
|
||||
Vector(ReturnType(compOp)), (v, w) => w.map(f => compOp(v, f)))
|
||||
}
|
||||
const compOp = math.resolve(name, [VComp, WComp], strategy)
|
||||
const opNoV = math.resolve(name, [Undefined, WComp], strategy)
|
||||
const opNoW = math.resolve(name, [VComp, Undefined], strategy)
|
||||
return Returns(
|
||||
Vector(ReturnType(compOp)),
|
||||
(v, w) => {
|
||||
const vInc = Number(v.length > 1)
|
||||
const wInc = Number(w.length >= v.length || w.length > 1)
|
||||
const retval = []
|
||||
let vIx = 0
|
||||
let wIx = 0
|
||||
while ((vInc && vIx < v.length)
|
||||
|| (wInc && wIx < w.length)
|
||||
) {
|
||||
if (vIx >= v.length) {
|
||||
retval.push(opNoV(undefined, w[wIx]))
|
||||
} else if (wIx >= w.length) {
|
||||
retval.push(opNoW(v[vIx], undefined))
|
||||
} else retval.push(compOp(v[vIx], w[wIx]))
|
||||
vIx += vInc
|
||||
wIx += wInc
|
||||
}
|
||||
return retval
|
||||
})
|
||||
})
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue