try: try to expand to more Complex functions

This commit is contained in:
Glen Whitney 2022-12-20 14:58:36 -05:00
parent a33feb5434
commit 233669b4b4
8 changed files with 124 additions and 0 deletions

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

@ -20,3 +20,9 @@ export const Complex_type = {
export const complex_unary = <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_binary = <T>(t: T, u: T) => ({re: t, im: u}) export const complex_binary = <T>(t: T, u: T) => ({re: t, im: u})
export const zero = <T>(dep: Dependency<'zero', [T]>) => (z: Complex<T>) =>
complex_binary(dep.zero(z.re), dep.zero(z.im))
export const one = <T>(dep: Dependency<'one', [T]> & Dependency<'zero', [T]>) =>
(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

@ -3,8 +3,11 @@ 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,3 +5,4 @@ export const number_type = {
} }
export const zero = (a: number) => 0 export const zero = (a: number) => 0
export const one = (a: number) => 0