Compare commits

...

2 Commits

11 changed files with 148 additions and 19 deletions

View File

@ -1 +1,8 @@
export * as Complex from './native.js' import {ForType} from '../core/Dispatcher.js'
import * as Complex from './native.js'
export {Complex}
declare module "../core/Dispatcher" {
interface ImplementationTypes extends ForType<'Complex', typeof Complex> {}
}

88
src/Complex/arithmetic.ts Normal file
View File

@ -0,0 +1,88 @@
import {Complex, complex_binary} from './type.js'
import {Dependency} from '../core/Dispatcher.js'
export const add = <T>(dep: Dependency<'add', [T,T]>) =>
(w: Complex<T>, z: Complex<T>) =>
complex_binary(dep.add(w.re, z.re), dep.add(w.im, z.im))
export const unaryMinus = <T>(dep: Dependency<'unaryMinus', [T]>) =>
(z: Complex<T>) =>
complex_binary(dep.unaryMinus(z.re), dep.unaryMinus(z.im))
export const conj = <T>(dep: Dependency<'unaryMinus', [T]>) =>
(z: Complex<T>) =>
complex_binary(z.re, dep.unaryMinus(z.im))
export const subtract = <T>(dep: Dependency<'subtract', [T,T]>) =>
(w: Complex<T>, z: Complex<T>) =>
complex_binary(dep.subtract(w.re, z.re), dep.subtract(w.im, z.im))
export const multiply =
<T>(dep: Dependency<'add', [T,T]>
& Dependency<'subtract', [T,T]>
& Dependency<'multiply', [T,T]>
& Dependency<'conj', [T]>) =>
(w: Complex<T>, z: Complex<T>) => {
const mult = dep.multiply
const realpart = dep.subtract(
mult( w.re, z.re), mult(dep.conj(w.im), z.im))
const imagpart = dep.add(
mult(dep.conj(w.re), z.im), mult( w.im, z.re))
return complex_binary(realpart, imagpart)
}
declare module "../core/Dispatcher" {
interface ImplementationTypes {
add_Complex: typeof add
multiply_Complex: typeof multiply
}
}
type AbsquareReturns<T> = T extends Complex<infer U> ? AbsquareReturns<U> : T
export const absquare =
<T>(dep: Dependency<'absquare', [T]>
& Dependency<'add', [AbsquareReturns<T>, AbsquareReturns<T>]>) =>
(z: Complex<T>) => dep.add(dep.absquare(z.re), dep.absquare(z.im))
export const reciprocal =
<T>(dep: Dependency<'unaryMinus', [T]>
& Dependency<'absquare', [Complex<T>]>
& Dependency<'divide', [T, T]>) =>
(z: Complex<T>) => {
const denom = dep.absquare(z)
return complex_binary(
dep.divide(z.re, denom), dep.divide(dep.unaryMinus(z.im), denom))
}
export const divide =
<T>(dep: Dependency<'multiply', [Complex<T>, Complex<T>]>
& Dependency<'reciprocal', [Complex<T>]>) =>
(w: Complex<T>, z: Complex<T>) => dep.multiply(w, dep.reciprocal(z))
export const sqrt =
<T>(dep: Dependency<'equal', [T,T]>
& Dependency<'add', [T,T]>
& Dependency<'isSquare', [T]>
& Dependency<'zero', [T]>
& Dependency<'sqrt', [T]>
& Dependency<'absquare', [Complex<T>]>
& Dependency<'one', [T]>
& Dependency<'divide', [T,T]>
& Dependency<'subtract', [T,T]>
& Dependency<'unaryMinus', [T]>
) =>
(z: Complex<T>) => {
if (dep.equal(z.re, dep.add(z.re, z.im)) && dep.isSquare(z.re)) {
// imaginary part negligible, just take square root of real part
return complex_binary(dep.sqrt(z.re), dep.zero(z.im))
}
const myabs = dep.sqrt(dep.absquare(z))
const real1 = dep.one(z.re)
const real2 = dep.add(real1, real1)
const realQuot = dep.divide(dep.add(myabs, z.re), real2)
const imagQuot = dep.divide(dep.subtract(myabs, z.re), real2)
let realPart = dep.sqrt(realQuot)
if (!(dep.isSquare(z.im))) realPart = dep.unaryMinus(realPart)
return complex_binary(realPart, dep.sqrt(imagQuot))
}

View File

@ -0,0 +1,6 @@
import {Complex} from './type.js'
import {Dependency} from '../core/Dispatcher.js'
export const equal = <T>(dep: Dependency<'equal', [T,T]>) =>
(w: Complex<T>, z: Complex<T>) =>
dep.equal(w.re, z.re) && dep.equal(w.im, z.im)

View File

@ -1,4 +1,3 @@
/// <reference path="../numbers/type.ts">
import {joinTypes, typeOfDependency, Dependency} from '../core/Dispatcher.js' import {joinTypes, typeOfDependency, Dependency} from '../core/Dispatcher.js'
export type Complex<T> = {re: T; im: T;} export type Complex<T> = {re: T; im: T;}
@ -18,13 +17,12 @@ export const Complex_type = {
} }
} }
export const complex_1 = <T>(dep: Dependency<'zero', [T]>) => export const complex_unary = <T>(dep: Dependency<'zero', [T]>) =>
(t: T) => ({re: t, im: dep.zero(t)}) (t: T) => ({re: t, im: dep.zero(t)})
export const complex_2 = <T>(t: T, u: T) => ({re: t, im: u}) export const complex_binary = <T>(t: T, u: T) => ({re: t, im: u})
declare module "../core/Dispatcher" { export const zero = <T>(dep: Dependency<'zero', [T]>) => (z: Complex<T>) =>
interface ImplementationTypes { complex_binary(dep.zero(z.re), dep.zero(z.im))
complex_1_Complex: typeof complex_1 export const one = <T>(dep: Dependency<'one', [T]> & Dependency<'zero', [T]>) =>
complex_2_Complex: typeof complex_2 (z: Complex<T>) =>
} complex_binary(dep.one(z.re), dep.zero(z.im))
}

View File

@ -1,4 +1,5 @@
export type Config = { export type Config = {
epsilon: number
predictable: boolean predictable: boolean
} }

View File

@ -14,6 +14,12 @@ type Signature = Parameter[]
export interface ImplementationTypes {} export interface ImplementationTypes {}
export type typeOfDependency = {typeOf: (x: unknown) => TypeName} export type typeOfDependency = {typeOf: (x: unknown) => TypeName}
// Helper for collecting implementations
// (Really just suffixes the type name onto the keys of exports)
export type ForType<T extends string, Exports> = keyof Exports extends string
? {[K in keyof Exports as `${K}_${T}`]: Exports[K]}
: never
//dummy implementation for now //dummy implementation for now
export function joinTypes(a: TypeName, b: TypeName) { export function joinTypes(a: TypeName, b: TypeName) {
if (a === b) return a if (a === b) return a

View File

@ -1 +1,8 @@
export * as numbers from './native.js' import {ForType} from '../core/Dispatcher.js'
import * as numbers from './native.js'
export {numbers}
declare module "../core/Dispatcher" {
interface ImplementationTypes extends ForType<'numbers', typeof numbers> {}
}

View File

@ -1,11 +1,13 @@
/// <reference path="../Complex/type.ts">
import {configDependency} from '../core/Config.js' import {configDependency} from '../core/Config.js'
import {Dependency, ImplementationTypes} from '../core/Dispatcher.js' import {Dependency} from '../core/Dispatcher.js'
export const add = (a: number, b: number) => a + b export const add = (a: number, b: number) => a + b
export const unaryMinus = (a: number) => -a export const unaryMinus = (a: number) => -a
export const conj = (a: number) => a
export const subtract = (a: number, b: number) => a - b export const subtract = (a: number, b: number) => a - b
export const multiply = (a: number, b: number) => a * b export const multiply = (a: number, b: number) => a * b
export const absquare = (a: number) => a * a
export const reciprocal = (a: number) => 1 / a
export const divide = (a: number, b: number) => a / b export const divide = (a: number, b: number) => a / b
export const sqrt = export const sqrt =
(dep: configDependency (dep: configDependency

1
src/numbers/predicate.ts Normal file
View File

@ -0,0 +1 @@
export const isSquare = (a:number) => a >=0

18
src/numbers/relational.ts Normal file
View File

@ -0,0 +1,18 @@
import {configDependency} from '../core/Config.js'
const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16
export const equal = (dep: configDependency) => (x: number, y: number) => {
const eps = dep.config.epsilon
if (eps === null || eps === undefined) return x === y
if (x === y) return true
if (isNaN(x) || isNaN(y)) return false
if (isFinite(x) && isFinite(y)) {
const diff = Math.abs(x - y)
if (diff < DBL_EPSILON) return true
return diff <= Math.max(Math.abs(x), Math.abs(y)) * eps
}
return false
}

View File

@ -5,9 +5,4 @@ export const number_type = {
} }
export const zero = (a: number) => 0 export const zero = (a: number) => 0
export const one = (a: number) => 0
declare module "../core/Dispatcher" {
interface ImplementationTypes {
zero_numbers: typeof zero
}
}