feat: Implement subtypes
This should eventually be moved into typed-function itself, but for now it can be implemented on top of the existing typed-function. Uses subtypes to define (and error-check) gcd and lcm, which are only defined for integer arguments. Resolves #36.
This commit is contained in:
parent
4d38f4161c
commit
c429c19dfe
35 changed files with 294 additions and 43 deletions
|
@ -12,9 +12,19 @@ const Complex = new PocomathInstance('Complex')
|
|||
Complex.installType('Complex', {
|
||||
test: isComplex,
|
||||
from: {
|
||||
number: x => ({re: x, im: 0}),
|
||||
number: x => ({re: x, im: 0})
|
||||
}
|
||||
})
|
||||
Complex.installType('GaussianInteger', {
|
||||
test: z => typeof z.re == 'bigint' && typeof z.im == 'bigint',
|
||||
refines: 'Complex',
|
||||
from: {
|
||||
bigint: x => ({re: x, im: 0n})
|
||||
}
|
||||
})
|
||||
|
||||
Complex.promoteUnary = {
|
||||
Complex: ({self,complex}) => z => complex(self(z.re), self(z.im))
|
||||
}
|
||||
|
||||
export {Complex}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
|
||||
export const abs = {Complex: ({sqrt, add, multiply}) => z => {
|
||||
return sqrt(add(multiply(z.re, z.re), multiply(z.im, z.im)))
|
||||
}}
|
||||
export const abs = {
|
||||
Complex: ({sqrt, 'absquare(Complex)': absq}) => z => sqrt(absq(z))
|
||||
}
|
||||
|
|
5
src/complex/absquare.mjs
Normal file
5
src/complex/absquare.mjs
Normal file
|
@ -0,0 +1,5 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
|
||||
export const absquare = {
|
||||
Complex: ({add, square}) => z => add(square(z.re), square(z.im))
|
||||
}
|
6
src/complex/conjugate.mjs
Normal file
6
src/complex/conjugate.mjs
Normal file
|
@ -0,0 +1,6 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
|
||||
export const conjugate = {
|
||||
Complex: ({negate, complex}) => z => complex(z.re, negate(z.im))
|
||||
}
|
||||
|
17
src/complex/gcd.mjs
Normal file
17
src/complex/gcd.mjs
Normal file
|
@ -0,0 +1,17 @@
|
|||
import PocomathInstance from '../core/PocomathInstance.mjs'
|
||||
import * as Complex from './Types/Complex.mjs'
|
||||
import gcdType from '../generic/gcdType.mjs'
|
||||
|
||||
const imps = {
|
||||
gcdComplexRaw: gcdType('Complex'),
|
||||
gcd: { // Only return gcds with positive real part
|
||||
'Complex, Complex': ({gcdComplexRaw, sign, one, negate}) => (z,m) => {
|
||||
const raw = gcdComplexRaw(z, m)
|
||||
if (sign(raw.re) === one(raw.re)) return raw
|
||||
return negate(raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const gcd = PocomathInstance.merge(Complex, imps)
|
||||
|
5
src/complex/isZero.mjs
Normal file
5
src/complex/isZero.mjs
Normal file
|
@ -0,0 +1,5 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
|
||||
export const isZero = {
|
||||
Complex: ({self}) => z => self(z.re) && self(z.im)
|
||||
}
|
14
src/complex/multiply.mjs
Normal file
14
src/complex/multiply.mjs
Normal file
|
@ -0,0 +1,14 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
|
||||
export const multiply = {
|
||||
'Complex,Complex': ({
|
||||
'complex(any,any)': cplx,
|
||||
add,
|
||||
subtract,
|
||||
self
|
||||
}) => (w,z) => {
|
||||
return cplx(
|
||||
subtract(self(w.re, z.re), self(w.im, z.im)),
|
||||
add(self(w.re, z.im), self(w.im, z.re)))
|
||||
}
|
||||
}
|
|
@ -1,8 +1,18 @@
|
|||
import gcdType from '../generic/gcdType.mjs'
|
||||
|
||||
export * from './Types/Complex.mjs'
|
||||
|
||||
export {abs} from './abs.mjs'
|
||||
export {absquare} from './absquare.mjs'
|
||||
export {add} from './add.mjs'
|
||||
export {conjugate} from './conjugate.mjs'
|
||||
export {complex} from './complex.mjs'
|
||||
export {gcd} from './gcd.mjs'
|
||||
export {isZero} from './isZero.mjs'
|
||||
export {multiply} from './multiply.mjs'
|
||||
export {negate} from './negate.mjs'
|
||||
export {quotient} from './quotient.mjs'
|
||||
export {roundquotient} from './roundquotient.mjs'
|
||||
export {sqrt} from './sqrt.mjs'
|
||||
export {zero} from './zero.mjs'
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
import {Complex} from './Types/Complex.mjs'
|
||||
|
||||
export const negate = {
|
||||
Complex: ({self}) => z => ({re: self(z.re), im: self(z.im)})
|
||||
}
|
||||
const negate = Complex.promoteUnary
|
||||
|
||||
export {Complex, negate}
|
||||
|
|
5
src/complex/quotient.mjs
Normal file
5
src/complex/quotient.mjs
Normal file
|
@ -0,0 +1,5 @@
|
|||
export * from './roundquotient.mjs'
|
||||
|
||||
export const quotient = {
|
||||
'Complex,Complex': ({roundquotient}) => (w,z) => roundquotient(w,z)
|
||||
}
|
17
src/complex/roundquotient.mjs
Normal file
17
src/complex/roundquotient.mjs
Normal file
|
@ -0,0 +1,17 @@
|
|||
export * from './Types/Complex.mjs'
|
||||
|
||||
export const roundquotient = {
|
||||
'Complex,Complex': ({
|
||||
'isZero(Complex)': isZ,
|
||||
conjugate,
|
||||
'multiply(Complex,Complex)': mult,
|
||||
absquare,
|
||||
self,
|
||||
complex
|
||||
}) => (n,d) => {
|
||||
if (isZ(d)) return d
|
||||
const cnum = mult(n, conjugate(d))
|
||||
const dreal = absquare(d)
|
||||
return complex(self(cnum.re, dreal), self(cnum.im, dreal))
|
||||
}
|
||||
}
|
5
src/complex/zero.mjs
Normal file
5
src/complex/zero.mjs
Normal file
|
@ -0,0 +1,5 @@
|
|||
import {Complex} from './Types/Complex.mjs'
|
||||
|
||||
const zero = Complex.promoteUnary
|
||||
|
||||
export {Complex, zero}
|
Loading…
Add table
Add a link
Reference in a new issue