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:
Glen Whitney 2022-08-01 10:09:32 +00:00
parent 2609310b8e
commit fe54bc6004
29 changed files with 480 additions and 119 deletions

View file

@ -1 +1,2 @@
export * from './arithmetic.mjs'
export * from './relational.mjs'

View file

@ -1,8 +1,11 @@
import {reducingOperation} from './reducingOperation.mjs'
export * from './Types/generic.mjs'
export const add = reducingOperation
export {lcm} from './lcm.mjs'
export {mod} from './mod.mjs'
export {multiply} from './multiply.mjs'
export const multiply = reducingOperation
export {divide} from './divide.mjs'
export {sign} from './sign.mjs'
export {sqrt} from './sqrt.mjs'

View file

@ -1,4 +1,7 @@
export const divide = {
'any,any': ({multiply, invert}) => (x, y) => multiply(x, invert(y))
'T,T': ({
'multiply(T,T)': multT,
'invert(T)': invT
}) => (x, y) => multT(x, invT(y))
}

View file

@ -1,3 +1,7 @@
/* 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.
*/
/* Returns a object that defines the gcd for the given type */
export default function(type) {
const producer = refs => {

View file

@ -1,6 +1,7 @@
export const lcm = {
'any,any': ({
multiply,
quotient,
gcd}) => (a,b) => multiply(quotient(a, gcd(a,b)), b)
'T,T': ({
'multiply(T,T)': multT,
'quotient(T,T)': quotT,
'gcd(T,T)': gcdT
}) => (a,b) => multT(quotT(a, gcdT(a,b)), b)
}

View file

@ -1,6 +1,7 @@
export const mod = {
'any,any': ({
subtract,
multiply,
quotient}) => (a,m) => subtract(a, multiply(m, quotient(a,m)))
'T,T': ({
'subtract(T,T)': subT,
'multiply(T,T)': multT,
'quotient(T,T)': quotT
}) => (a,m) => subT(a, multT(m, quotT(a,m)))
}

View file

@ -3,6 +3,7 @@ export * from './Types/generic.mjs'
export const multiply = {
'undefined': () => u => u,
'undefined,...any': () => (u, rest) => u,
any: () => x => x,
'any,undefined': () => (x, u) => u,
'any,any,...any': ({self}) => (a,b,rest) => {
const later = [b, ...rest]

View file

@ -0,0 +1,12 @@
export * from './Types/generic.mjs'
export const reducingOperation = {
'undefined': () => u => u,
'undefined,...any': () => (u, rest) => u,
'any,undefined': () => (x, u) => u,
any: () => x => x,
'any,any,...any': ({
self
}) => (a,b,rest) => [b, ...rest].reduce((x,y) => self(x,y), a)
}

View file

@ -0,0 +1,54 @@
export const compare = {
'undefined,undefined': () => () => 0
}
export const isZero = {
'undefined': () => u => u === 0
}
export const equal = {
'!T,T': ({
'compare(T,T)': cmp,
'isZero(T)': isZ
}) => (x,y) => isZ(cmp(x,y))
}
export const unequal = {
'T,T': ({'equal(T.T)': eq}) => (x,y) => !(eq(x,y))
}
export const larger = {
'T,T': ({
'compare(T,T)': cmp,
'one(T)' : uno
}) => (x,y) => cmp(x,y) === uno(y)
}
export const largerEq = {
'T,T': ({
'compare(T,T)': cmp,
'one(T)' : uno,
'isZero(T)' : isZ
}) => (x,y) => {
const c = cmp(x,y)
return isZ(c) || c === uno(y)
}
}
export const smaller = {
'T,T': ({
'compare(T,T)': cmp,
'one(T)' : uno,
'isZero(T)' : isZ
}) => (x,y) => {
const c = cmp(x,y)
return !isZ(c) && c !== uno(y)
}
}
export const smallerEq = {
'T,T': ({
'compare(T,T)': cmp,
'one(T)' : uno
}) => (x,y) => cmp(x,y) !== uno(y)
}

View file

@ -1,6 +1,3 @@
export const sign = {
any: ({negate, divide, abs}) => x => {
if (x === negate(x)) return x // zero
return divide(x, abs(x))
}
T: ({'compare(T,T)': cmp, 'zero(T)': Z}) => x => cmp(x, Z(x))
}

View file

@ -1,3 +1,3 @@
export const square = {
any: ({multiply}) => x => multiply(x,x)
T: ({'multiply(T,T)': multT}) => x => multT(x,x)
}

View file

@ -1,3 +1,3 @@
export const subtract = {
'any,any': ({add, negate}) => (x,y) => add(x, negate(y))
'T,T': ({'add(T,T)': addT, 'negate(T)': negT}) => (x,y) => addT(x, negT(y))
}