diff --git a/complex/Complex.mjs b/complex/Complex.mjs new file mode 100644 index 0000000..b4b34fe --- /dev/null +++ b/complex/Complex.mjs @@ -0,0 +1,14 @@ +import typed from 'typed-function' + +/* Use a plain object with keys re and im for a complex */ +typed.addType({ + name: 'Complex', + test: z => z && typeof z === 'object' && 're' in z && 'im' in z +}) + +typed.addConversion({ + from: 'number', + to: 'Complex', + convert: x => ({re: x, im: 0}) +}) + diff --git a/complex/add.mjs b/complex/add.mjs new file mode 100644 index 0000000..cefc410 --- /dev/null +++ b/complex/add.mjs @@ -0,0 +1,12 @@ +import './Complex.mjs' + +export const add = { + '...Complex': [[], addends => { + const sum = {re: 0, im: 0} + addends.forEach(addend => { + sum.re += addend.re + sum.im += addend.im + }) + return sum + }] +} diff --git a/complex/all.mjs b/complex/all.mjs new file mode 100644 index 0000000..6f7e3d0 --- /dev/null +++ b/complex/all.mjs @@ -0,0 +1,2 @@ +export {complex} from './complex.mjs' +export {add} from './add.mjs' diff --git a/complex/complex.mjs b/complex/complex.mjs new file mode 100644 index 0000000..4404b80 --- /dev/null +++ b/complex/complex.mjs @@ -0,0 +1,6 @@ +import './Complex.mjs' + +export const complex = { + 'number, number': [[], (x, y) => ({re: x, im: y})], + Complex: [[], z => z] +} diff --git a/pocomath.mjs b/pocomath.mjs index 3c04c11..c58ef45 100644 --- a/pocomath.mjs +++ b/pocomath.mjs @@ -1,8 +1,10 @@ /* Core of pocomath: generates the default instance */ import PocomathInstance from './PocomathInstance.mjs' import * as numbers from './number/all.mjs' +import * as complex from './complex/all.mjs' const math = new PocomathInstance('math') math.install(numbers) +math.install(complex) export default math diff --git a/test/_pocomath.mjs b/test/_pocomath.mjs index 2f2a0f2..b816844 100644 --- a/test/_pocomath.mjs +++ b/test/_pocomath.mjs @@ -16,4 +16,18 @@ describe('The default full pocomath instance "math"', () => { assert.strictEqual(math.negate(-1), 1) assert.strictEqual(math.add(10, math.negate(3)), 7) }) + + it('can be extended', () => { + math.install({'add': { + '...string': [[], addends => addends.reduce((x,y) => x+y, '')] + }}) + assert.strictEqual(math.add('Kilroy',' is here'), 'Kilroy is here') + }) + + it('handles complex numbers', () => { + const norm13 = {re: 2, im: 3} + assert.deepStrictEqual(math.complex(2,3), norm13) + assert.deepStrictEqual(math.complex(2), math.complex(2,0)) + assert.deepStrictEqual(math.add(2, math.complex(0,3)), norm13) + }) }) diff --git a/test/custom.mjs b/test/custom.mjs new file mode 100644 index 0000000..ed8d7cc --- /dev/null +++ b/test/custom.mjs @@ -0,0 +1,21 @@ +import assert from 'assert' +import typed from 'typed-function' +import PocomathInstance from '../PocomathInstance.mjs' +import * as numbers from '../number/all.mjs' +import * as complex from '../complex/all.mjs' + +const bw = new PocomathInstance('backwards') +describe('A custom instance', () => { + it("works when partially assembled", () => { + bw.install(complex) + assert.deepStrictEqual(bw.add(2, bw.complex(0, 3)), {re: 2, im: 3}) + }) + + it("can be assembled in any order", () => { + bw.install(numbers) + typed.addConversion({from: 'string', to: 'number', convert: x => +x}) + assert.strictEqual(bw.subtract(16, bw.add(3,4,2)), 7) + assert.strictEqual(bw.negate('8'), -8) + assert.deepStrictEqual(bw.add(bw.complex(1,3), 1), {re: 2, im: 3}) + }) +})