refactor: Make generics more strict via templates

This commit also adds a built-in `typeOf` function to every PocomathInstance.
  It also adds a notation (prefix '!') for "eager" templeates that
  instantiate themselves for all types immediately upon definition.
This commit is contained in:
Glen Whitney 2022-08-01 02:57:38 -07:00
parent fd3d6b2eb3
commit 36e7b750ce
23 changed files with 233 additions and 44 deletions

View file

@ -1,10 +1,20 @@
export * from './Types/Complex.mjs'
export const add = {
/* Relying on conversions for both complex + number and complex + bigint
* leads to an infinite loop when adding a number and a bigint, since they
* both convert to Complex.
*/
'Complex,number': ({
'self(number,number)': addNum,
'complex(any,any)': cplx
}) => (z,x) => cplx(addNum(z.re, x), z.im),
'Complex,bigint': ({
'self(bigint,bigint)': addBigInt,
'complex(any,any)': cplx
}) => (z,x) => cplx(addBigInt(z.re, x), z.im),
'Complex,Complex': ({
self,
'complex(any,any)': cplx

19
src/complex/equal.mjs Normal file
View file

@ -0,0 +1,19 @@
export * from './Types/Complex.mjs'
export const equal = {
'Complex,number': ({
'isZero(number)': isZ,
'self(number,number)': eqNum
}) => (z, x) => eqNum(z.re, x) && isZ(z.im),
'Complex,bigint': ({
'isZero(bigint)': isZ,
'self(bigint,bigint)': eqBigInt
}) => (z, b) => eqBigInt(z.re, b) && isZ(z.im),
'Complex,Complex': ({self}) => (w,z) => self(w.re, z.re) && self(w.im, z.im),
'GaussianInteger,GaussianInteger': ({
'self(bigint,bigint)': eq
}) => (a,b) => eq(a.re, b.re) && eq(a.im, b.im)
}

View file

@ -7,6 +7,7 @@ export {absquare} from './absquare.mjs'
export {add} from './add.mjs'
export {conjugate} from './conjugate.mjs'
export {complex} from './complex.mjs'
export {equal} from './equal.mjs'
export {gcd} from './gcd.mjs'
export {invert} from './invert.mjs'
export {isZero} from './isZero.mjs'

View file

@ -3,7 +3,7 @@ export * from './Types/Complex.mjs'
export const sqrt = {
Complex: ({
config,
zero,
isZero,
sign,
one,
add,
@ -16,11 +16,8 @@ export const sqrt = {
}) => {
if (config.predictable) {
return z => {
const imZero = zero(z.im)
const imSign = sign(z.im)
const reOne = one(z.re)
const reSign = sign(z.re)
if (imSign === imZero && reSign === reOne) return complex(self(z.re))
if (isZero(z.im) && sign(z.re) === reOne) return complex(self(z.re))
const reTwo = add(reOne, reOne)
return complex(
multiply(sign(z.im), self(divide(add(abs(z),z.re), reTwo))),
@ -29,11 +26,8 @@ export const sqrt = {
}
}
return z => {
const imZero = zero(z.im)
const imSign = sign(z.im)
const reOne = one(z.re)
const reSign = sign(z.re)
if (imSign === imZero && reSign === reOne) return self(z.re)
if (isZero(z.im) && sign(z.re) === reOne) return self(z.re)
const reTwo = add(reOne, reOne)
return complex(
multiply(sign(z.im), self(divide(add(abs(z),z.re), reTwo))),