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' export * from './Types/bigint.mjs'
/* Absolute value squared */ /* Absolute value squared */
export const absquare = { 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 * 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 * from './Types/bigint.mjs'
export const compare = { 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 * from './Types/bigint.mjs'
export const divide = { export const divide = {
'bigint,bigint': ({config, 'quotient(bigint,bigint)': quot}) => { 'bigint,bigint': ({config, 'quotient(bigint,bigint)': quot}) => {
if (config.predictable) return quot if (config.predictable) return quot
return (n, d) => { return Returns('bigint|undefined', (n, d) => {
const q = n/d const q = n/d
if (q * d == n) return q if (q * d == n) return q
return undefined return undefined
} })
} }
} }

View File

@ -1,3 +1,4 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.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 * 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 gcdType from '../generic/gcdType.mjs'
import {identity} from '../generic/identity.mjs' import {identityType} from '../generic/identity.mjs'
export * from './Types/bigint.mjs' export * from './Types/bigint.mjs'
export {absquare} from './absquare.mjs' export {absquare} from './absquare.mjs'
export {add} from './add.mjs' export {add} from './add.mjs'
export {compare} from './compare.mjs' export {compare} from './compare.mjs'
export const conjugate = {bigint: () => identity} export const conjugate = {bigint: identityType('bigint')}
export {divide} from './divide.mjs' export {divide} from './divide.mjs'
export const gcd = gcdType('bigint') export const gcd = gcdType('bigint')
export {isZero} from './isZero.mjs' export {isZero} from './isZero.mjs'

View File

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

View File

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

View File

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

View File

@ -1,3 +1,4 @@
import Returns from '../core/Returns.mjs'
export * from './Types/bigint.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 /* 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 * which types this is instantiated for, namely the "integer" types, and
* not simply allow Pocomath to generate instances for any type it encounters. * not simply allow Pocomath to generate instances for any type it encounters.
@ -7,14 +9,14 @@ export default function(type) {
const producer = refs => { const producer = refs => {
const modder = refs[`mod(${type},${type})`] const modder = refs[`mod(${type},${type})`]
const zeroTester = refs[`isZero(${type})`] const zeroTester = refs[`isZero(${type})`]
return (a,b) => { return Returns(type, (a,b) => {
while (!zeroTester(b)) { while (!zeroTester(b)) {
const r = modder(a,b) const r = modder(a,b)
a = b a = b
b = r b = r
} }
return a return a
} })
} }
const retval = {} const retval = {}
retval[`${type},${type}`] = producer retval[`${type},${type}`] = producer

View File

@ -1,3 +1,11 @@
export function identity(x) { import Returns from '../core/Returns.mjs'
return x
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 gcdType from '../generic/gcdType.mjs'
import {identity} from '../generic/identity.mjs' import {identitySubTypes} from '../generic/identity.mjs'
export * from './Types/number.mjs' export * from './Types/number.mjs'
@ -7,7 +7,7 @@ export {abs} from './abs.mjs'
export {absquare} from './absquare.mjs' export {absquare} from './absquare.mjs'
export {add} from './add.mjs' export {add} from './add.mjs'
export {compare} from './compare.mjs' export {compare} from './compare.mjs'
export const conjugate = {number: () => identity} export const conjugate = {'T:number': identitySubTypes('number')}
export const gcd = gcdType('NumInt') export const gcd = gcdType('NumInt')
export {invert} from './invert.mjs' export {invert} from './invert.mjs'
export {isZero} from './isZero.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>') math.returnTypeOf('chain', 'bigint'), 'Chain<bigint>')
assert.strictEqual( assert.strictEqual(
math.returnTypeOf('returnTypeOf', 'string,string'), 'string') 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', () => { it('can subtract numbers', () => {