Compare commits

..

5 commits

6 changed files with 52 additions and 52 deletions

View file

@ -1,6 +1,6 @@
import {Complex} from './type.js' import {Complex} from './type.js'
import type { import type {
Dependencies, Signature, Returns, RealType, ZeroType Dependencies, Signature, Returns, RealType, AliasOf
} from '../interfaces/type.js' } from '../interfaces/type.js'
declare module "../interfaces/type" { declare module "../interfaces/type" {
@ -9,8 +9,8 @@ declare module "../interfaces/type" {
// after removing any `_...` suffixes; the following should be // after removing any `_...` suffixes; the following should be
// additional dispatches for add and divide, not separate // additional dispatches for add and divide, not separate
// operations, in the final mathjs bundle. // operations, in the final mathjs bundle.
add_real: {params: [T, RealType<T>], returns: T} addReal: AliasOf<'add', (a: T, b: RealType<T>) => T>
divide_real: {params: [T, RealType<T>], returns: T} divideReal: AliasOf<'divide', (a: T, b: RealType<T>) => T>
} }
} }
@ -19,9 +19,9 @@ export const add =
(w, z) => dep.complex(dep.add(w.re, z.re), dep.add(w.im, z.im)) (w, z) => dep.complex(dep.add(w.re, z.re), dep.add(w.im, z.im))
export const add_real = export const add_real =
<T>(dep: Dependencies<'add_real' | 'complex', T>): <T>(dep: Dependencies<'addReal' | 'complex', T>):
Signature<'add_real', Complex<T>> => Signature<'addReal', Complex<T>> =>
(z, r) => dep.complex(dep.add_real(z.re, r), z.im) (z, r) => dep.complex(dep.addReal(z.re, r), z.im)
export const unaryMinus = export const unaryMinus =
<T>(dep: Dependencies<'unaryMinus' | 'complex', T>): <T>(dep: Dependencies<'unaryMinus' | 'complex', T>):
@ -58,14 +58,14 @@ export const absquare =
z => dep.add(dep.absquare(z.re), dep.absquare(z.im)) z => dep.add(dep.absquare(z.re), dep.absquare(z.im))
export const divideByReal = export const divideByReal =
<T>(dep: Dependencies<'divide_real' | 'complex', T>): <T>(dep: Dependencies<'divideReal' | 'complex', T>):
Signature<'divide_real', Complex<T>> => Signature<'divideReal', Complex<T>> =>
(z, r) => dep.complex(dep.divide_real(z.re, r), dep.divide_real(z.im, r)) (z, r) => dep.complex(dep.divideReal(z.re, r), dep.divideReal(z.im, r))
export const reciprocal = export const reciprocal =
<T>(dep: Dependencies<'conj' | 'absquare' | 'divide_real', Complex<T>>): <T>(dep: Dependencies<'conj' | 'absquare' | 'divideReal', Complex<T>>):
Signature<'reciprocal', Complex<T>> => Signature<'reciprocal', Complex<T>> =>
z => dep.divide_real(dep.conj(z), dep.absquare(z)) z => dep.divideReal(dep.conj(z), dep.absquare(z))
export const divide = export const divide =
<T>(dep: Dependencies<'multiply' | 'reciprocal', Complex<T>>): <T>(dep: Dependencies<'multiply' | 'reciprocal', Complex<T>>):
@ -78,11 +78,14 @@ export const divide =
// in fact, we need `add_real` on both T and Complex<T>, hence the dependency // in fact, we need `add_real` on both T and Complex<T>, hence the dependency
// with a custom name, not generated via Dependencies<...> // with a custom name, not generated via Dependencies<...>
export const sqrt = export const sqrt =
<T>(dep: Dependencies<'add' | 'equal' | 'conservativeSqrt' | 'unaryMinus', <T>(dep: Dependencies<'equal' | 'conservativeSqrt' | 'unaryMinus', RealType<T>>
RealType<T>> & Dependencies<'zero' | 'complex', T>
& Dependencies<'zero' | 'add_real' | 'complex', T> & Dependencies<'absquare' | 're' | 'divideReal', Complex<T>>
& Dependencies<'absquare' | 're' | 'divide_real', Complex<T>> & {
& {add_complex_real: Signature<'add_real', Complex<T>>}): addNumber: Signature<'addReal', T>, // TODO: should use Signature<'add'> here
addReal: Signature<'add', RealType<T>>,
addComplex: Signature<'addReal', Complex<T>> // TODO: should use Signature<'add'> here
}):
Signature<'sqrt', Complex<T>> => Signature<'sqrt', Complex<T>> =>
z => { z => {
const myabs = dep.conservativeSqrt(dep.absquare(z)) const myabs = dep.conservativeSqrt(dep.absquare(z))
@ -91,12 +94,12 @@ export const sqrt =
if (dep.equal(myabs, negr)) { if (dep.equal(myabs, negr)) {
// pure imaginary square root; z.im already zero // pure imaginary square root; z.im already zero
return dep.complex( return dep.complex(
dep.zero(z.re), dep.add_real(z.im, dep.conservativeSqrt(negr))) dep.zero(z.re), dep.addNumber(z.im, dep.conservativeSqrt(negr)))
} }
const num = dep.add_complex_real(z, myabs) const num = dep.addComplex(z, myabs)
const denomsq = dep.add(dep.add(myabs, myabs), dep.add(r, r)) const denomsq = dep.addReal(dep.addReal(myabs, myabs), dep.addReal(r, r))
const denom = dep.conservativeSqrt(denomsq) const denom = dep.conservativeSqrt(denomsq)
return dep.divide_real(num, denom) return dep.divideReal(num, denom)
} }
export const conservativeSqrt = sqrt export const conservativeSqrt = sqrt

View file

@ -32,7 +32,7 @@ declare module "../interfaces/type" {
} }
interface Signatures<T> { interface Signatures<T> {
complex: {params: [T] | [T,T], returns: Complex<T>} complex: ((re: T) => Complex<T>) | ((re: T, im: T) => Complex<T>)
} }
} }

View file

@ -1,23 +1,18 @@
import type {Complex} from '../Complex/type.js' import type {Complex} from '../Complex/type.js'
import type {RealType} from './type.js' import type {RealType} from './type.js'
type UnaryOperator<T> = {params: [T], returns: T}
type BinaryOperator<T> = {params: [T, T], returns: T}
declare module "./type" { declare module "./type" {
interface Signatures<T> { interface Signatures<T> {
add: BinaryOperator<T> add: (a: T, b: T) => T
unaryMinus: UnaryOperator<T> unaryMinus: (a: T) => T
conj: UnaryOperator<T> conj: (a: T) => T
subtract: BinaryOperator<T> subtract: (a: T, b: T) => T
multiply: BinaryOperator<T> multiply: (a: T, b: T) => T
square: UnaryOperator<T> square: (a: T) => T
absquare: {params: [T], returns: RealType<T>} absquare: (a: T) => RealType<T>
reciprocal: UnaryOperator<T> reciprocal: (a: T) => T
divide: BinaryOperator<T> divide: (a: T, b: T) => T
conservativeSqrt: UnaryOperator<T> conservativeSqrt: (a: T) => T
sqrt: { sqrt: (a: T)=> T extends Complex<unknown> ? T : T | Complex<T>
params: [T],
returns: T extends Complex<any> ? T : T | Complex<T>
}
} }
} }

View file

@ -1,9 +1,10 @@
// Warning: a module must have something besides just a "declare module" // Warning: a module must have something besides just a "declare module"
// section; otherwise it is ignored. // section; otherwise it is ignored.
export type UnaryPredicate<T> = {params: [T], returns: boolean} export type UnaryPredicate<T> = (a: T) => boolean
declare module "./type" { declare module "./type" {
interface Signatures<T> { interface Signatures<T> {
isReal: UnaryPredicate<T> isReal: (a: T) => boolean
isSquare: UnaryPredicate<T> isSquare: (a: T) => boolean
} }
} }

View file

@ -1,9 +1,9 @@
// Warning: a module must have something besides just a "declare module" // Warning: a module must have something besides just a "declare module"
// section; otherwise it is ignored. // section; otherwise it is ignored.
export type BinaryPredicate<T> = {params: [T, T], returns: boolean} export type BinaryPredicate<T> = (a: T, b: T) => T
declare module "./type" { declare module "./type" {
interface Signatures<T> { interface Signatures<T> {
equal: BinaryPredicate<T> equal: (a: T, b: T) => boolean
unequal: BinaryPredicate<T> unequal: (a: T, b: T) => boolean
} }
} }

View file

@ -58,17 +58,18 @@ export type RealType<T> = ALookup<T, 'real'>
* key 're' in the interface. * key 're' in the interface.
****/ ****/
export interface Signatures<T> { export interface Signatures<T> {
zero: {params: [T], returns: ZeroType<T>} zero: (a: T) => ZeroType<T>
one: {params: [T], returns: OneType<T>} one: (a: T) => OneType<T>
// nan needs to be able to operate on its own output for everything // nan needs to be able to operate on its own output for everything
// else to compile. That's why its parameter type is widened: // else to compile. That's why its parameter type is widened:
nan: {params: [T | NaNType<T>], returns: NaNType<T>} nan: (a: T | NaNType<T>) => NaNType<T>
re: {params: [T], returns: RealType<T>} re: (a: T) => RealType<T>
} }
type SignatureKey = keyof Signatures<unknown> type SignatureKey<T> = keyof Signatures<T>
export type Returns<Name extends SignatureKey, T> = Signatures<T>[Name]['returns'] export type Signature<Name extends SignatureKey<T>, T> = Signatures<T>[Name]
export type Signature<Name extends SignatureKey, T> = export type Returns<Name extends SignatureKey<T>, T> = ReturnType<Signatures<T>[Name]>
(...args: Signatures<T>[Name]['params']) => Returns<Name, T> export type Dependencies<Name extends SignatureKey<T>, T> = {[K in Name]: Signature<K, T>}
export type Dependencies<Name extends SignatureKey, T> = {[K in Name]: Signature<K, T>}
export type AliasOf<Name extends string, T> = T & {aliasOf?: Name}