feat: Template operations (#41)
Relational functions are added using templates, and existing generic functions are made more strict with them. Also a new built-in typeOf function is added, that automatically updates itself. Resolves #34. Co-authored-by: Glen Whitney <glen@studioinfinity.org> Reviewed-on: #41
This commit is contained in:
parent
2609310b8e
commit
fe54bc6004
29 changed files with 480 additions and 119 deletions
|
@ -1,10 +1,22 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
|
||||
export const add = {
|
||||
'...Complex': ({self}) => addends => {
|
||||
if (addends.length === 0) return {re:0, im:0}
|
||||
const seed = addends.shift()
|
||||
return addends.reduce(
|
||||
(w,z) => ({re: self(w.re, z.re), im: self(w.im, z.im)}), seed)
|
||||
}
|
||||
/* 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
|
||||
}) => (w,z) => cplx(self(w.re, z.re), self(w.im, z.im))
|
||||
}
|
||||
|
|
19
src/complex/equal.mjs
Normal file
19
src/complex/equal.mjs
Normal 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)
|
||||
}
|
|
@ -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'
|
||||
|
|
|
@ -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))),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue