From 1b9d6b64287cdc4629a774ebee0367cfe7a90cc1 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 4 Jan 2023 12:28:24 +0100 Subject: [PATCH 1/5] chore: use direct function definitions instead of `{ params, returns }` --- src/Complex/arithmetic.ts | 4 ++-- src/Complex/type.ts | 2 +- src/interfaces/arithmetic.ts | 27 +++++++++++---------------- src/interfaces/predicate.ts | 7 ++++--- src/interfaces/relational.ts | 6 +++--- src/interfaces/type.ts | 13 ++++++------- 6 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/Complex/arithmetic.ts b/src/Complex/arithmetic.ts index e11d91e..cc3d49b 100644 --- a/src/Complex/arithmetic.ts +++ b/src/Complex/arithmetic.ts @@ -9,8 +9,8 @@ declare module "../interfaces/type" { // after removing any `_...` suffixes; the following should be // additional dispatches for add and divide, not separate // operations, in the final mathjs bundle. - add_real: {params: [T, RealType], returns: T} - divide_real: {params: [T, RealType], returns: T} + add_real: (a: T, b: RealType) => T + divide_real: (a: T, b: RealType) => T } } diff --git a/src/Complex/type.ts b/src/Complex/type.ts index 43c79fe..50a1314 100644 --- a/src/Complex/type.ts +++ b/src/Complex/type.ts @@ -32,7 +32,7 @@ declare module "../interfaces/type" { } interface Signatures { - complex: {params: [T] | [T,T], returns: Complex} + complex: ((re: T) => Complex) | ((re: T, im: T) => Complex) } } diff --git a/src/interfaces/arithmetic.ts b/src/interfaces/arithmetic.ts index f77ceb1..df2d765 100644 --- a/src/interfaces/arithmetic.ts +++ b/src/interfaces/arithmetic.ts @@ -1,23 +1,18 @@ import type {Complex} from '../Complex/type.js' import type {RealType} from './type.js' -type UnaryOperator = {params: [T], returns: T} -type BinaryOperator = {params: [T, T], returns: T} declare module "./type" { interface Signatures { - add: BinaryOperator - unaryMinus: UnaryOperator - conj: UnaryOperator - subtract: BinaryOperator - multiply: BinaryOperator - square: UnaryOperator - absquare: {params: [T], returns: RealType} - reciprocal: UnaryOperator - divide: BinaryOperator - conservativeSqrt: UnaryOperator - sqrt: { - params: [T], - returns: T extends Complex ? T : T | Complex - } + add: (a: T, b: T) => T + unaryMinus: (a: T) => T + conj: (a: T) => T + subtract: (a: T, b: T) => T + multiply: (a: T, b: T) => T + square: (a: T) => T + absquare: (a: T) => RealType + reciprocal: (a: T) => T + divide: (a: T, b: T) => T + conservativeSqrt: (a: T) => T + sqrt: (a: T)=> T extends Complex ? T : T | Complex } } diff --git a/src/interfaces/predicate.ts b/src/interfaces/predicate.ts index b4c7393..93d3b4a 100644 --- a/src/interfaces/predicate.ts +++ b/src/interfaces/predicate.ts @@ -1,9 +1,10 @@ // Warning: a module must have something besides just a "declare module" // section; otherwise it is ignored. -export type UnaryPredicate = {params: [T], returns: boolean} +export type UnaryPredicate = (a: T) => boolean + declare module "./type" { interface Signatures { - isReal: UnaryPredicate - isSquare: UnaryPredicate + isReal: (a: T) => boolean + isSquare: (a: T) => boolean } } diff --git a/src/interfaces/relational.ts b/src/interfaces/relational.ts index 9b511b0..e2aa3a1 100644 --- a/src/interfaces/relational.ts +++ b/src/interfaces/relational.ts @@ -1,9 +1,9 @@ // Warning: a module must have something besides just a "declare module" // section; otherwise it is ignored. -export type BinaryPredicate = {params: [T, T], returns: boolean} +export type BinaryPredicate = (a: T, b: T) => T declare module "./type" { interface Signatures { - equal: BinaryPredicate - unequal: BinaryPredicate + equal: (a: T, b: T) => boolean + unequal: (a: T, b: T) => boolean } } diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts index 4596d7f..c68c98a 100644 --- a/src/interfaces/type.ts +++ b/src/interfaces/type.ts @@ -58,17 +58,16 @@ export type RealType = ALookup * key 're' in the interface. ****/ export interface Signatures { - zero: {params: [T], returns: ZeroType} - one: {params: [T], returns: OneType} + zero: (a: T) => ZeroType + one: (a: T) => OneType // nan needs to be able to operate on its own output for everything // else to compile. That's why its parameter type is widened: - nan: {params: [T | NaNType], returns: NaNType} - re: {params: [T], returns: RealType} + nan: (a: T | NaNType) => NaNType + re: (a: T) => RealType } type SignatureKey = keyof Signatures -export type Returns = Signatures[Name]['returns'] -export type Signature = - (...args: Signatures[Name]['params']) => Returns +export type Signature = Signatures[Name] +export type Returns = ReturnType[Name]> export type Dependencies = {[K in Name]: Signature} From d147d0a576186f6edfb9fc667f4f755f98470b6b Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 4 Jan 2023 12:35:37 +0100 Subject: [PATCH 2/5] chore: implement `AliasOf` --- src/Complex/arithmetic.ts | 32 ++++++++++++++++---------------- src/interfaces/type.ts | 2 ++ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/Complex/arithmetic.ts b/src/Complex/arithmetic.ts index cc3d49b..900e2a1 100644 --- a/src/Complex/arithmetic.ts +++ b/src/Complex/arithmetic.ts @@ -1,6 +1,6 @@ import {Complex} from './type.js' import type { - Dependencies, Signature, Returns, RealType, ZeroType + Dependencies, Signature, Returns, RealType, AliasOf } from '../interfaces/type.js' declare module "../interfaces/type" { @@ -9,8 +9,8 @@ declare module "../interfaces/type" { // after removing any `_...` suffixes; the following should be // additional dispatches for add and divide, not separate // operations, in the final mathjs bundle. - add_real: (a: T, b: RealType) => T - divide_real: (a: T, b: RealType) => T + addReal: AliasOf<'add', (a: T, b: RealType) => T> + divideReal: AliasOf<'divide', (a: T, b: RealType) => T> } } @@ -19,9 +19,9 @@ export const add = (w, z) => dep.complex(dep.add(w.re, z.re), dep.add(w.im, z.im)) export const add_real = - (dep: Dependencies<'add_real' | 'complex', T>): - Signature<'add_real', Complex> => - (z, r) => dep.complex(dep.add_real(z.re, r), z.im) + (dep: Dependencies<'addReal' | 'complex', T>): + Signature<'addReal', Complex> => + (z, r) => dep.complex(dep.addReal(z.re, r), z.im) export const unaryMinus = (dep: Dependencies<'unaryMinus' | 'complex', T>): @@ -58,14 +58,14 @@ export const absquare = z => dep.add(dep.absquare(z.re), dep.absquare(z.im)) export const divideByReal = - (dep: Dependencies<'divide_real' | 'complex', T>): - Signature<'divide_real', Complex> => - (z, r) => dep.complex(dep.divide_real(z.re, r), dep.divide_real(z.im, r)) + (dep: Dependencies<'divideReal' | 'complex', T>): + Signature<'divideReal', Complex> => + (z, r) => dep.complex(dep.divideReal(z.re, r), dep.divideReal(z.im, r)) export const reciprocal = - (dep: Dependencies<'conj' | 'absquare' | 'divide_real', Complex>): + (dep: Dependencies<'conj' | 'absquare' | 'divideReal', Complex>): Signature<'reciprocal', Complex> => - z => dep.divide_real(dep.conj(z), dep.absquare(z)) + z => dep.divideReal(dep.conj(z), dep.absquare(z)) export const divide = (dep: Dependencies<'multiply' | 'reciprocal', Complex>): @@ -80,9 +80,9 @@ export const divide = export const sqrt = (dep: Dependencies<'add' | 'equal' | 'conservativeSqrt' | 'unaryMinus', RealType> - & Dependencies<'zero' | 'add_real' | 'complex', T> - & Dependencies<'absquare' | 're' | 'divide_real', Complex> - & {add_complex_real: Signature<'add_real', Complex>}): + & Dependencies<'zero' | 'addReal' | 'complex', T> + & Dependencies<'absquare' | 're' | 'divideReal', Complex> + & {add_complex_real: Signature<'addReal', Complex>}): Signature<'sqrt', Complex> => z => { const myabs = dep.conservativeSqrt(dep.absquare(z)) @@ -91,12 +91,12 @@ export const sqrt = if (dep.equal(myabs, negr)) { // pure imaginary square root; z.im already zero return dep.complex( - dep.zero(z.re), dep.add_real(z.im, dep.conservativeSqrt(negr))) + dep.zero(z.re), dep.addReal(z.im, dep.conservativeSqrt(negr))) } const num = dep.add_complex_real(z, myabs) const denomsq = dep.add(dep.add(myabs, myabs), dep.add(r, r)) const denom = dep.conservativeSqrt(denomsq) - return dep.divide_real(num, denom) + return dep.divideReal(num, denom) } export const conservativeSqrt = sqrt diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts index c68c98a..4c91d9b 100644 --- a/src/interfaces/type.ts +++ b/src/interfaces/type.ts @@ -71,3 +71,5 @@ type SignatureKey = keyof Signatures export type Signature = Signatures[Name] export type Returns = ReturnType[Name]> export type Dependencies = {[K in Name]: Signature} + +export type AliasOf = T & {aliasOf?: Name} From 0ea786dcc22985df8559aefc31cc3aa464783df2 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 4 Jan 2023 14:06:30 +0100 Subject: [PATCH 3/5] chore: show how to inject multiple instances of the same function (WIP) --- src/Complex/arithmetic.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Complex/arithmetic.ts b/src/Complex/arithmetic.ts index 900e2a1..93d1559 100644 --- a/src/Complex/arithmetic.ts +++ b/src/Complex/arithmetic.ts @@ -78,11 +78,14 @@ export const divide = // in fact, we need `add_real` on both T and Complex, hence the dependency // with a custom name, not generated via Dependencies<...> export const sqrt = - (dep: Dependencies<'add' | 'equal' | 'conservativeSqrt' | 'unaryMinus', - RealType> - & Dependencies<'zero' | 'addReal' | 'complex', T> + (dep: Dependencies<'equal' | 'conservativeSqrt' | 'unaryMinus', RealType> + & Dependencies<'zero' | 'complex', T> & Dependencies<'absquare' | 're' | 'divideReal', Complex> - & {add_complex_real: Signature<'addReal', Complex>}): + & { + addNumber: Signature<'addReal', T>, // TODO: should be possible to use Signature<'add'> here + addReal: Signature<'add', RealType>, + addComplex: Signature<'addReal', Complex> // TODO: should be possible to use Signature<'add'> here + }): Signature<'sqrt', Complex> => z => { const myabs = dep.conservativeSqrt(dep.absquare(z)) @@ -91,10 +94,10 @@ export const sqrt = if (dep.equal(myabs, negr)) { // pure imaginary square root; z.im already zero return dep.complex( - dep.zero(z.re), dep.addReal(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 denomsq = dep.add(dep.add(myabs, myabs), dep.add(r, r)) + const num = dep.addComplex(z, myabs) + const denomsq = dep.addReal(dep.addReal(myabs, myabs), dep.addReal(r, r)) const denom = dep.conservativeSqrt(denomsq) return dep.divideReal(num, denom) } From e468ec72dd0c3510218bab4e2ec89c508cd6707d Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 4 Jan 2023 14:32:17 +0100 Subject: [PATCH 4/5] chore: rephrase two todo's --- src/Complex/arithmetic.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Complex/arithmetic.ts b/src/Complex/arithmetic.ts index 93d1559..0d403f4 100644 --- a/src/Complex/arithmetic.ts +++ b/src/Complex/arithmetic.ts @@ -82,9 +82,9 @@ export const sqrt = & Dependencies<'zero' | 'complex', T> & Dependencies<'absquare' | 're' | 'divideReal', Complex> & { - addNumber: Signature<'addReal', T>, // TODO: should be possible to use Signature<'add'> here + addNumber: Signature<'addReal', T>, // TODO: should use Signature<'add'> here addReal: Signature<'add', RealType>, - addComplex: Signature<'addReal', Complex> // TODO: should be possible to use Signature<'add'> here + addComplex: Signature<'addReal', Complex> // TODO: should use Signature<'add'> here }): Signature<'sqrt', Complex> => z => { From bd05dc926776db4e49f107c8d27922e488a207e2 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 4 Jan 2023 14:32:44 +0100 Subject: [PATCH 5/5] chore: make SignatureKey generic instead of using unknown --- src/interfaces/type.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/interfaces/type.ts b/src/interfaces/type.ts index 4c91d9b..9e6870d 100644 --- a/src/interfaces/type.ts +++ b/src/interfaces/type.ts @@ -66,10 +66,10 @@ export interface Signatures { re: (a: T) => RealType } -type SignatureKey = keyof Signatures +type SignatureKey = keyof Signatures -export type Signature = Signatures[Name] -export type Returns = ReturnType[Name]> -export type Dependencies = {[K in Name]: Signature} +export type Signature, T> = Signatures[Name] +export type Returns, T> = ReturnType[Name]> +export type Dependencies, T> = {[K in Name]: Signature} export type AliasOf = T & {aliasOf?: Name}