feat: Return type annotations #53

Merged
glen merged 15 commits from return_types into main 2022-08-30 19:36:44 +00:00
17 changed files with 61 additions and 30 deletions
Showing only changes of commit bc434c7163 - Show all commits

View File

@ -1,6 +1,7 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
/* Absolute value squared */
export const absquare = {
bigint: ({'square(bigint)': sqb}) => b => sqb(b)
bigint: ({'square(bigint)': sqb}) => Returns('bigint', b => sqb(b))
}

View File

@ -1,3 +1,4 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
export const add = {'bigint,bigint': () => (a,b) => a+b}
export const add = {'bigint,bigint': () => Returns('bigint', (a,b) => a+b)}

View File

@ -1,5 +1,7 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
export const compare = {
'bigint,bigint': () => (a,b) => a === b ? 0n : (a > b ? 1n : -1n)
'bigint,bigint': () => Returns(
'boolean', (a,b) => a === b ? 0n : (a > b ? 1n : -1n))
}

View File

@ -1,12 +1,13 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
export const divide = {
'bigint,bigint': ({config, 'quotient(bigint,bigint)': quot}) => {
if (config.predictable) return quot
return (n, d) => {
return Returns('bigint|undefined', (n, d) => {
const q = n/d
if (q * d == n) return q
return undefined
}
})
}
}

View File

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

View File

@ -1,3 +1,4 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
export const multiply = {'bigint,bigint': () => (a,b) => a*b}
export const multiply = {'bigint,bigint': () => Returns('bigint', (a,b) => a*b)}

View File

@ -1,12 +1,12 @@
import gcdType from '../generic/gcdType.mjs'
import {identity} from '../generic/identity.mjs'
import {identityType} from '../generic/identity.mjs'
export * from './Types/bigint.mjs'
export {absquare} from './absquare.mjs'
export {add} from './add.mjs'
export {compare} from './compare.mjs'
export const conjugate = {bigint: () => identity}
export const conjugate = {bigint: identityType('bigint')}
export {divide} from './divide.mjs'
export const gcd = gcdType('bigint')
export {isZero} from './isZero.mjs'

View File

@ -1,3 +1,4 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
export const one = {bigint: () => () => 1n}
export const one = {bigint: () => Returns('bigint', () => 1n)}

View File

@ -1,13 +1,14 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
/* Returns the best integer approximation to n/d */
/* Returns the floor integer approximation to n/d */
export const quotient = {
'bigint,bigint': ({'sign(bigint)': sgn}) => (n, d) => {
'bigint,bigint': ({'sign(bigint)': sgn}) => Returns('bigint', (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

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

View File

@ -1,9 +1,10 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
export const sign = {
bigint: () => b => {
bigint: () => Returns('bigint', b => {
if (b === 0n) return 0n
if (b > 0n) return 1n
return -1n
}
})
}

View File

@ -1,5 +1,6 @@
export * from './Types/bigint.mjs'
import Returns from '../core/Returns.mjs'
import isqrt from 'bigint-isqrt'
export * from './Types/bigint.mjs'
export const sqrt = {
bigint: ({
@ -11,18 +12,18 @@ export const sqrt = {
// Don't just return the constant isqrt here because the object
// gets decorated with info that might need to be different
// for different PocomathInstancss
return b => isqrt(b)
return Returns('bigint', b => isqrt(b))
}
if (!cplx) {
return b => {
return Returns('bigint|undefined', b => {
if (b >= 0n) {
const trial = isqrt(b)
if (trial * trial === b) return trial
}
return undefined
})
}
}
return b => {
return Returns('bigint|Complex<bigint>|undefined', b => {
if (b === undefined) return undefined
let real = true
if (b < 0n) {
@ -33,6 +34,6 @@ export const sqrt = {
if (trial * trial !== b) return undefined
if (real) return trial
return cplx(0n, trial)
}
})
}
}

View File

@ -1,3 +1,4 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.mjs'
export const zero = {bigint: () => () => 0n}
export const zero = {bigint: () => Returns('bigint', () => 0n)}

View File

@ -1,3 +1,5 @@
import Returns from '../core/Returns.mjs'
/* Note we do not use a template here so that we can explicitly control
* which types this is instantiated for, namely the "integer" types, and
* not simply allow Pocomath to generate instances for any type it encounters.
@ -7,14 +9,14 @@ export default function(type) {
const producer = refs => {
const modder = refs[`mod(${type},${type})`]
const zeroTester = refs[`isZero(${type})`]
return (a,b) => {
return Returns(type, (a,b) => {
while (!zeroTester(b)) {
const r = modder(a,b)
a = b
b = r
}
return a
}
})
}
const retval = {}
retval[`${type},${type}`] = producer

View File

@ -1,3 +1,11 @@
export function identity(x) {
return x
import Returns from '../core/Returns.mjs'
export function identityType(type) {
return () => Returns(type, x => x)
}
export function identitySubTypes(type) {
return ({T}) => Returns(T, x => x)
}
export const identity = {T: ({T}) => Returns(T, x => x)}

View File

@ -1,5 +1,5 @@
import gcdType from '../generic/gcdType.mjs'
import {identity} from '../generic/identity.mjs'
import {identitySubTypes} from '../generic/identity.mjs'
export * from './Types/number.mjs'
@ -7,7 +7,7 @@ export {abs} from './abs.mjs'
export {absquare} from './absquare.mjs'
export {add} from './add.mjs'
export {compare} from './compare.mjs'
export const conjugate = {number: () => identity}
export const conjugate = {'T:number': identitySubTypes('number')}
export const gcd = gcdType('NumInt')
export {invert} from './invert.mjs'
export {isZero} from './isZero.mjs'

View File

@ -38,6 +38,14 @@ describe('The default full pocomath instance "math"', () => {
math.returnTypeOf('chain', 'bigint'), 'Chain<bigint>')
assert.strictEqual(
math.returnTypeOf('returnTypeOf', 'string,string'), 'string')
assert.strictEqual(
math.returnTypeOf('conjugate', 'bigint'), 'bigint')
assert.strictEqual(
math.returnTypeOf('gcd', 'bigint,bigint'), 'bigint')
math.identity(math.fraction(3,5)) // TODO: ditto
assert.strictEqual(math.returnTypeOf('identity', 'Fraction'), 'Fraction')
assert.strictEqual(
math.returnTypeOf('quotient', 'bigint,bigint'), 'bigint')
})
it('can subtract numbers', () => {