diff --git a/src/num.ts b/src/num.ts index 7206e9f..a344ea4 100644 --- a/src/num.ts +++ b/src/num.ts @@ -1,6 +1,6 @@ import { toNative as $$, L, P, _, fromNative as __, id } from './core'; import { EQ, GT, LT, Ord } from './ord'; -import { Bool, False, True } from './bool'; +import { Bool, False, iif, True } from './bool'; export type Num = L<(z: T) => L<(n: L<(p: Num) => T>) => T>>; @@ -52,6 +52,12 @@ export const sub: L<(l: Num) => L<(r: Num) => Num>> export const mul: L<(l: Num) => L<(r: Num) => Num>> = _(l => _(r => l._(Zero)._(_(pl => sum._(r)._(mul._(pl)._(r)))))); +export const div: L<(l: Num) => L<(r: Num) => Num>> + = _(l => _(r => iif._(lt._(l)._(r))._(Zero)._(succ._(div._(sub._(l)._(r))._(r))))); + +export const mod: L<(l: Num) => L<(r: Num) => Num>> += _(l => _(r => iif._(lt._(l)._(r))._(l)._(mod._(sub._(l)._(r))._(r)))); + export const fromNumber: (n: number) => Num = n => !n ? Zero : Succ._(new L(() => fromNumber(n - 1).value)); diff --git a/test/num.spec.ts b/test/num.spec.ts index fbb4c96..40d72a8 100644 --- a/test/num.spec.ts +++ b/test/num.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from '@jest/globals'; import { L, undef } from '../src/core'; import { toNOrd as $o, NOrd } from '../src/ord'; import { toBoolean as $b, fromBoolean as _b } from '../src/bool'; -import { toNumber as $, Num, Succ, Zero, fromNumber as _, cmp, eq, ge, gt, ifz, le, lt, mul, pred, sub, succ, sum } from '../src/num'; +import { toNumber as $, Num, Succ, Zero, fromNumber as _, cmp, div, eq, ge, gt, ifz, le, lt, mod, mul, pred, sub, succ, sum } from '../src/num'; describe('Num', () => { const infinity: Num = new L(() => Succ._(infinity).value); @@ -332,4 +332,56 @@ describe('Num', () => { expect($(mul._(_(0))._(undef))).toBe(0); }); }); + + describe('div', () => { + it('0 div 10 is 0', () => { + expect($(div._(_(0))._(_(10)))).toBe(0); + }); + + it('1 div 10 is 0', () => { + expect($(div._(_(1))._(_(10)))).toBe(0); + }); + + it('10 div 1 is 10', () => { + expect($(div._(_(10))._(_(1)))).toBe(10); + }); + + it('10 div 5 is 2', () => { + expect($(div._(_(10))._(_(5)))).toBe(2); + }); + + it('10 div 3 is 3', () => { + expect($(div._(_(10))._(_(3)))).toBe(3); + }); + + it.failing('0 div ignores second argument', () => { + expect($(div._(_(0))._(undef))).toBe(0); + }); + }); + + describe('mod', () => { + it('0 mod 10 is 0', () => { + expect($(mod._(_(0))._(_(10)))).toBe(0); + }); + + it('1 mod 10 is 1', () => { + expect($(mod._(_(1))._(_(10)))).toBe(1); + }); + + it('10 mod 1 is 0', () => { + expect($(mod._(_(10))._(_(1)))).toBe(0); + }); + + it('10 mod 5 is 0', () => { + expect($(mod._(_(10))._(_(5)))).toBe(0); + }); + + it('10 mod 3 is 1', () => { + expect($(mod._(_(10))._(_(3)))).toBe(1); + }); + + it.failing('0 mod ignores second argument', () => { + expect($(mod._(_(0))._(undef))).toBe(0); + }); + }); });