diff --git a/src/bigint/all.mjs b/src/bigint/all.mjs index 74dce18..f9da9f0 100644 --- a/src/bigint/all.mjs +++ b/src/bigint/all.mjs @@ -1,5 +1,6 @@ import PocomathInstance from '../core/PocomathInstance.mjs' import * as bigints from './native.mjs' import * as generic from '../generic/all.mjs' +import * as floor from '../ops/floor.mjs' -export default PocomathInstance.merge('bigint', bigints, generic) +export default PocomathInstance.merge('bigint', bigints, generic, floor) diff --git a/src/complex/all.mjs b/src/complex/all.mjs index 5d9f3b3..98eae90 100644 --- a/src/complex/all.mjs +++ b/src/complex/all.mjs @@ -1,5 +1,6 @@ import PocomathInstance from '../core/PocomathInstance.mjs' import * as complexes from './native.mjs' import * as generic from '../generic/arithmetic.mjs' +import * as floor from '../ops/floor.mjs' -export default PocomathInstance.merge('complex', complexes, generic) +export default PocomathInstance.merge('complex', complexes, generic, floor) diff --git a/src/core/PocomathInstance.mjs b/src/core/PocomathInstance.mjs index 180ca17..4858a54 100644 --- a/src/core/PocomathInstance.mjs +++ b/src/core/PocomathInstance.mjs @@ -471,6 +471,7 @@ export default class PocomathInstance { } for (const instType of instantiationSet) { + if (!(instType in this.Types)) continue if (this.Types[instType] === anySpec) continue const signature = substituteInSig(trimSignature, theTemplateParam, instType) diff --git a/src/number/all.mjs b/src/number/all.mjs index 4a1228e..bedaa24 100644 --- a/src/number/all.mjs +++ b/src/number/all.mjs @@ -1,6 +1,7 @@ import PocomathInstance from '../core/PocomathInstance.mjs' import * as numbers from './native.mjs' import * as generic from '../generic/all.mjs' +import * as floor from '../ops/floor.mjs' -export default PocomathInstance.merge('number', numbers, generic) +export default PocomathInstance.merge('number', numbers, generic, floor) diff --git a/src/ops/floor.mjs b/src/ops/floor.mjs new file mode 100644 index 0000000..98d524a --- /dev/null +++ b/src/ops/floor.mjs @@ -0,0 +1,25 @@ +import {Complex} from '../complex/Types/Complex.mjs' + +/* Note we don't **export** any types here, so that only the options + * below that correspond to types that have been installed are activated. + */ + +export const floor = { + bigint: () => x => x, + NumInt: () => x => x, // Because Pocomath isn't part of typed-function, or + GaussianInteger: () => x => x, // at least have access to the real + // typed-function parse, we unfortunately can't coalesce these into one + // entry with type `bigint|NumInt|GaussianInteger` because they couldn't + // be separately activated then + + number: ({'equal(number,number)': eq}) => n => { + if (eq(n, Math.round(n))) return Math.round(n) + return Math.floor(n) + }, + + Complex: Complex.promoteUnary.Complex, + + // OK to include a type totally not in Pocomath yet, it'll never be + // activated. + Fraction: ({quotient}) => f => quotient(f.n, f.d), +} diff --git a/src/pocomath.mjs b/src/pocomath.mjs index 65f8103..cb9bf94 100644 --- a/src/pocomath.mjs +++ b/src/pocomath.mjs @@ -4,7 +4,9 @@ import * as numbers from './number/native.mjs' import * as bigints from './bigint/native.mjs' import * as complex from './complex/native.mjs' import * as generic from './generic/all.mjs' +import * as floor from './ops/floor.mjs' -const math = PocomathInstance.merge('math', numbers, bigints, complex, generic) +const math = PocomathInstance.merge( + 'math', numbers, bigints, complex, generic, floor) export default math diff --git a/test/_pocomath.mjs b/test/_pocomath.mjs index 1a6fabe..3e6f2fe 100644 --- a/test/_pocomath.mjs +++ b/test/_pocomath.mjs @@ -3,12 +3,12 @@ import PocomathInstance from '../src/core/PocomathInstance.mjs' import math from '../src/pocomath.mjs' describe('The default full pocomath instance "math"', () => { - it('has no undefined types', () => { + it('has no unexpected undefined types', () => { const undef = math.undefinedTypes() if (undef.length) { - console.log('Probable typo: found undefined types', undef) + console.log('NOTE: Found undefined types', undef) } - assert.strictEqual(undef.length, 0) + assert.strictEqual(undef.length, 1) // Mentioning 'Fraction' but not using }) it('has a built-in typeOf operator', () => { diff --git a/test/bigint/_all.mjs b/test/bigint/_all.mjs index 29b3d27..371b2a0 100644 --- a/test/bigint/_all.mjs +++ b/test/bigint/_all.mjs @@ -64,4 +64,8 @@ describe('bigint', () => { assert.strictEqual(math.lcm(0n, 0n), 0n) }) + it('allows floor as a no-op', () => { + assert.strictEqual(math.floor(-333n), -333n) + }) + }) diff --git a/test/complex/_all.mjs b/test/complex/_all.mjs index ae146b6..e486fc3 100644 --- a/test/complex/_all.mjs +++ b/test/complex/_all.mjs @@ -51,4 +51,12 @@ describe('complex', () => { math.complex(4n, 5n)) }) + it('computes floor', () => { + assert.deepStrictEqual( + math.floor(math.complex(19, 22.7)), + math.complex(19, 22)) + const gi = math.complex(-1n, 1n) + assert.strictEqual(math.floor(gi), gi) // literally a no-op + }) + }) diff --git a/test/custom.mjs b/test/custom.mjs index 7aef959..ba4c713 100644 --- a/test/custom.mjs +++ b/test/custom.mjs @@ -38,12 +38,20 @@ describe('A custom instance', () => { const pm = new PocomathInstance('piecemeal') pm.install(numbers) assert.strictEqual(pm.subtract(5, 10), -5) + assert.strictEqual(pm.floor(3.7), 3) + assert.throws(() => pm.floor(10n), TypeError) pm.install(complexAdd) pm.install(complexNegate) pm.install(complexComplex) // Should be enough to allow complex subtraction, as subtract is generic: assert.deepStrictEqual( - pm.subtract({re:5, im:0}, {re:10, im:1}), {re:-5, im: -1}) + pm.subtract(pm.complex(5, 0), pm.complex(10, 1)), + math.complex(-5, -1)) + // And now floor has been activated for Complex as well, since the type + // is present + assert.deepStrictEqual( + pm.floor(math.complex(1.9, 0)), + math.complex(1)) }) it("can defer definition of (even used) types", () => { diff --git a/test/number/_all.mjs b/test/number/_all.mjs index f8e7312..49c7da6 100644 --- a/test/number/_all.mjs +++ b/test/number/_all.mjs @@ -37,4 +37,10 @@ describe('number', () => { assert.ok(math.largerEq(12.5, math.divide(25,2))) }) + it('Computes floor', () => { + assert.strictEqual(math.floor(7), 7) + assert.strictEqual(math.floor(6.99), 6) + assert.strictEqual(math.floor(1-1e-13), 1) + }) + })