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:
Glen Whitney 2022-07-30 04:59:04 -07:00
parent 4d38f4161c
commit c429c19dfe
35 changed files with 294 additions and 43 deletions

View file

@ -1,20 +1,12 @@
export * from './Types/bigint.mjs'
export const divide = {
'bigint,bigint': ({config, 'sign(bigint)': sgn}) => {
if (config.predictable) {
return (n, d) => {
if (sgn(n) === sgn(d)) return n/d
const quot = n/d
if (quot * d == n) return quot
return quot - 1n
}
} else {
return (n, d) => {
const quot = n/d
if (quot * d == n) return quot
return undefined
}
'bigint,bigint': ({config, 'quotient(bigint,bigint)': quot}) => {
if (config.predictable) return quot
return (n, d) => {
const q = n/d
if (q * d == n) return q
return undefined
}
}
}

3
src/bigint/isZero.mjs Normal file
View file

@ -0,0 +1,3 @@
export * from './Types/bigint.mjs'
export const isZero = {bigint: () => b => b === 0n}

View file

@ -1,5 +1,3 @@
export * from './Types/bigint.mjs'
export const multiply = {
'...bigint': () => multiplicands => multiplicands.reduce((x,y) => x*y, 1n)
}
export const multiply = {'bigint,bigint': () => (a,b) => a*b}

View file

@ -1,9 +1,16 @@
import gcdType from '../generic/gcdType.mjs'
export * from './Types/bigint.mjs'
export {add} from './add.mjs'
export {divide} from './divide.mjs'
export const gcd = gcdType('bigint')
export {isZero} from './isZero.mjs'
export {multiply} from './multiply.mjs'
export {negate} from './negate.mjs'
export {one} from './one.mjs'
export {sign} from './sign.mjs'
export {quotient} from './quotient.mjs'
export {roundquotient} from './roundquotient.mjs'
export {sqrt} from './sqrt.mjs'
export {zero} from './zero.mjs'

13
src/bigint/quotient.mjs Normal file
View file

@ -0,0 +1,13 @@
export * from './Types/bigint.mjs'
/* Returns the best integer approximation to n/d */
export const quotient = {
'bigint,bigint': ({'sign(bigint)': sgn}) => (n, d) => {
const dSgn = sgn(d)
if (dSgn === 0n) return 0n
if (sgn(n) === dSgn) return n/d
const quot = n/d
if (quot * d == n) return quot
return quot - 1n
}
}

View file

@ -0,0 +1,15 @@
export * from './Types/bigint.mjs'
/* Returns the closest integer approximation to n/d */
export const roundquotient = {
'bigint,bigint': ({'sign(bigint)': sgn}) => (n, d) => {
const dSgn = sgn(d)
if (dSgn === 0n) return 0n
const candidate = n/d
const rem = n - d*candidate
const absd = d*dSgn
if (2n * rem > absd) return candidate + dSgn
if (-2n * rem >= absd) return candidate - dSgn
return candidate
}
}