nanomath/src/vector/arithmetic.js
Glen Whitney cb3a93dd1c 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
2025-05-03 19:59:44 -07:00

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
})
})