89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
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))
|
|
}
|