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:
parent
ec97b0e20a
commit
cb3a93dd1c
26 changed files with 238 additions and 171 deletions
|
@ -1,7 +1,7 @@
|
|||
import {Complex} from './Complex.js'
|
||||
import {maybeComplex, promoteBinary, promoteUnary} from './helpers.js'
|
||||
import {ResolutionError} from '#core/helpers.js'
|
||||
import {Returns, ReturnTyping} from '#core/Type.js'
|
||||
import {Returns, ReturnType, ReturnTyping} from '#core/Type.js'
|
||||
import {match} from '#core/TypePatterns.js'
|
||||
import {ReturnsAs} from '#generic/helpers.js'
|
||||
|
||||
|
@ -9,7 +9,7 @@ const {conservative, full, free} = ReturnTyping
|
|||
|
||||
export const normsq = match(Complex, (math, C, strategy) => {
|
||||
const compNormsq = math.normsq.resolve(C.Component, full)
|
||||
const R = compNormsq.returns
|
||||
const R = ReturnType(compNormsq)
|
||||
const add = math.add.resolve([R,R], strategy)
|
||||
return ReturnsAs(add, z => add(compNormsq(z.re), compNormsq(z.im)))
|
||||
})
|
||||
|
@ -19,19 +19,21 @@ export const add = promoteBinary('add')
|
|||
export const conj = match(Complex, (math, C, strategy) => {
|
||||
const neg = math.negate.resolve(C.Component, full)
|
||||
const compConj = math.conj.resolve(C.Component, full)
|
||||
const cplx = maybeComplex(math, strategy, compConj.returns, neg.returns)
|
||||
const cplx = maybeComplex(
|
||||
math, strategy, ReturnType(compConj), ReturnType(neg))
|
||||
return ReturnsAs(cplx, z => cplx(compConj(z.re), neg(z.im)))
|
||||
})
|
||||
|
||||
export const divide = [
|
||||
match([Complex, T => !T.complex], (math, [C, R], strategy) => {
|
||||
const div = math.divide.resolve([C.Component, R], full)
|
||||
const cplx = maybeComplex(math, strategy, div.returns, div.returns)
|
||||
const NewComp = ReturnType(div)
|
||||
const cplx = maybeComplex(math, strategy, NewComp, NewComp)
|
||||
return ReturnsAs(cplx, (z, r) => cplx(div(z.re, r), div(z.im, r)))
|
||||
}),
|
||||
match([Complex, Complex], (math, [W, Z], strategy) => {
|
||||
const inv = math.invert.resolve(Z, full)
|
||||
const mult = math.multiply.resolve([W, inv.returns], strategy)
|
||||
const mult = math.multiply.resolve([W, ReturnType(inv)], strategy)
|
||||
return ReturnsAs(mult, (w, z) => mult(w, inv(z)))
|
||||
})
|
||||
]
|
||||
|
@ -39,8 +41,9 @@ export const divide = [
|
|||
export const invert = match(Complex, (math, C, strategy) => {
|
||||
const conj = math.conj.resolve(C, full)
|
||||
const normsq = math.normsq.resolve(C, full)
|
||||
const div = math.divide.resolve([C.Component, normsq.returns], full)
|
||||
const cplx = maybeComplex(math, strategy, div.returns, div.returns)
|
||||
const div = math.divide.resolve([C.Component, ReturnType(normsq)], full)
|
||||
const NewComp = ReturnType(div)
|
||||
const cplx = maybeComplex(math, strategy, NewComp, NewComp)
|
||||
return ReturnsAs(cplx, z => {
|
||||
const c = conj(z)
|
||||
const d = normsq(z)
|
||||
|
@ -53,7 +56,8 @@ export const invert = match(Complex, (math, C, strategy) => {
|
|||
export const multiply = [
|
||||
match([T => !T.complex, Complex], (math, [R, C], strategy) => {
|
||||
const mult = math.multiply.resolve([R, C.Component], full)
|
||||
const cplx = maybeComplex(math, strategy, mult.returns, mult.returns)
|
||||
const NewComp = ReturnType(mult)
|
||||
const cplx = maybeComplex(math, strategy, NewComp, NewComp)
|
||||
return ReturnsAs(cplx, (r, z) => cplx(mult(r, z.re), mult(r, z.im)))
|
||||
}),
|
||||
match([Complex, T => !T.complex], (math, [C, R], strategy) => {
|
||||
|
@ -62,15 +66,19 @@ export const multiply = [
|
|||
}),
|
||||
match([Complex, Complex], (math, [W, Z], strategy) => {
|
||||
const conj = math.conj.resolve(W.Component, full)
|
||||
if (conj.returns !== W.Component) {
|
||||
if (ReturnType(conj) !== W.Component) {
|
||||
throw new ResolutionError(
|
||||
`conjugation on ${W.Component} returns type (${conj.returns})`)
|
||||
`conjugation on ${W.Component} returns different type `
|
||||
+ `(${ReturnType(conj)})`)
|
||||
}
|
||||
const mWZ = math.multiply.resolve([W.Component, Z.Component], full)
|
||||
const mZW = math.multiply.resolve([Z.Component, W.Component], full)
|
||||
const sub = math.subtract.resolve([mWZ.returns, mZW.returns], full)
|
||||
const add = math.add.resolve([mWZ.returns, mZW.returns], full)
|
||||
const cplx = maybeComplex(math, strategy, sub.returns, add.returns)
|
||||
const TWZ = ReturnType(mWZ)
|
||||
const TZW = ReturnType(mZW)
|
||||
const sub = math.subtract.resolve([TWZ, TZW], full)
|
||||
const add = math.add.resolve([TWZ, TZW], full)
|
||||
const cplx = maybeComplex(
|
||||
math, strategy, ReturnType(sub), ReturnType(add))
|
||||
return ReturnsAs(cplx, (w, z) => {
|
||||
const real = sub(mWZ( w.re, z.re), mZW(z.im, conj(w.im)))
|
||||
const imag = add(mWZ(conj(w.re), z.im), mZW(z.re, w.im))
|
||||
|
@ -85,7 +93,7 @@ export const negate = promoteUnary('negate')
|
|||
// integer coordinates.
|
||||
export const sqrt = match(Complex, (math, C, strategy) => {
|
||||
const re = math.re.resolve(C)
|
||||
const R = re.returns
|
||||
const R = ReturnType(re)
|
||||
const isReal = math.isReal.resolve(C)
|
||||
// dependencies for the real case:
|
||||
const zComp = math.zero(C.Component)
|
||||
|
@ -98,8 +106,8 @@ export const sqrt = match(Complex, (math, C, strategy) => {
|
|||
const cplx = math.complex.resolve([C.Component, C.Component], full)
|
||||
// additional dependencies for the complex case
|
||||
const abs = math.abs.resolve(C, full)
|
||||
if (abs.returns !== R) {
|
||||
throw new TypeError(`abs on ${C} returns ${abs.returns}, not ${R}`)
|
||||
if (ReturnType(abs) !== R) {
|
||||
throw new TypeError(`abs on ${C} returns ${ReturnType(abs)}, not ${R}`)
|
||||
}
|
||||
const addRR = math.add.resolve([R, R], conservative)
|
||||
const twoR = addRR(oneR, oneR)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue