So far, abs, add, norm, normsq, and sum are supported. To get them to work, also implements the following: * refactor: Use ReturnType function rather than just accessing .returns * feat: distinguish marking a function as a behavior from its return type * refactor: Rename `NotAType` to `Unknown` because it must be made closer to a bona fide type for the sake of inhomogeneous vectors * feat: make resolving a TypeDispatcher method on a type vector including `Unknown` into a no-op; that simplifies a number of generic behaviors * feat: add `haszero` method parallel to `hasnan` * feat: track the Vector nesting depth of Vector specializations
33 lines
1.2 KiB
JavaScript
33 lines
1.2 KiB
JavaScript
import {promoteBinary, promoteUnary} from './helpers.js'
|
|
import {Vector} from './Vector.js'
|
|
|
|
import {ReturnType} from '#core/Type.js'
|
|
import {match} from '#core/TypePatterns.js'
|
|
import {ReturnsAs} from '#generic/helpers.js'
|
|
|
|
export const normsq = match(Vector, (math, V) => {
|
|
const compNormsq = math.normsq.resolve(V.Component)
|
|
const sum = math.sum.resolve(Vector(ReturnType(compNormsq)))
|
|
return ReturnsAs(sum, v => sum(v.map(compNormsq)))
|
|
})
|
|
// abs and norm differ only on Vector (and perhaps other collections) --
|
|
// norm computes overall by the generic formula, whereas abs distributes
|
|
// elementwise:
|
|
export const abs = promoteUnary('abs')
|
|
export const add = promoteBinary('add')
|
|
|
|
export const sum = match(Vector, (math, V) => {
|
|
const add = math.add.resolve([V.Component, V.Component])
|
|
const haszero = math.haszero(V.Component)
|
|
const zero = haszero ? math.zero(V.Component) : undefined
|
|
return ReturnsAs(add, v => {
|
|
if (v.length === 0) {
|
|
if (haszero) return zero
|
|
throw new TypeError(`Can't sum empty ${V}: no zero element`)
|
|
}
|
|
let ix = 0
|
|
let retval = v[ix]
|
|
while (++ix < v.length) retval = add(retval, v[ix])
|
|
return retval
|
|
})
|
|
})
|