feat: Start adding vector arithmetic

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
This commit is contained in:
Glen Whitney 2025-05-03 19:59:44 -07:00
parent ec97b0e20a
commit cb3a93dd1c
26 changed files with 238 additions and 171 deletions

33
src/vector/arithmetic.js Normal file
View file

@ -0,0 +1,33 @@
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
})
})