70 lines
2.6 KiB
JavaScript
70 lines
2.6 KiB
JavaScript
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
|
|
})
|
|
})
|
|
]
|