diff --git a/src/complex/__test__/arithmetic.spec.js b/src/complex/__test__/arithmetic.spec.js index d72b335..966843b 100644 --- a/src/complex/__test__/arithmetic.spec.js +++ b/src/complex/__test__/arithmetic.spec.js @@ -32,6 +32,21 @@ describe('complex arithmetic operations', () => { assert.deepStrictEqual(conj(z), cplx(3, -4)) assert.deepStrictEqual(conj(cplx(z,z)), cplx(cplx(3, -4), cplx(-3, -4))) }) + it('divides complex numbers', () => { + const div = math.divide + const z = cplx(3, 4) + assert.deepStrictEqual(div(z, cplx(0, 1)), cplx(4, -3)) + assert(math.equal(div(z, z), 1)) + // should probably have a quaternion example, but it's intricate + }) + it('inverts complex numbers', () => { + const inv = math.invert + assert.deepStrictEqual(inv(cplx(0, 1)), cplx(0, -1)) + assert.deepStrictEqual(inv(cplx(3, 4)), cplx(3/25, -4/25)) + assert.deepStrictEqual( + inv(cplx(cplx(1, 2), cplx(4, 2))), + cplx(cplx(1/25, -2/25), cplx(-4/25, -2/25))) + }) it('multiplies complex numbers', () => { const mult = math.multiply const z = cplx(3, 4) diff --git a/src/complex/arithmetic.js b/src/complex/arithmetic.js index 70fafae..d50b993 100644 --- a/src/complex/arithmetic.js +++ b/src/complex/arithmetic.js @@ -20,6 +20,31 @@ export const conj = match(Complex, (math, C) => { return ReturnsAs(cplx, z => cplx(compConj(z.re), neg(z.im))) }) +export const divide = [ + match([Complex, T => !T.complex], (math, [C, R]) => { + const div = math.divide.resolve([C.Component, R]) + const cplx = math.complex.resolve([div.returns, div.returns]) + return ReturnsAs(cplx, (z, r) => cplx(div(z.re, r), div(z.im, r))) + }), + match([Complex, Complex], (math, [W, Z]) => { + const inv = math.invert.resolve(Z) + const mult = math.multiply.resolve([W, inv.returns]) + return ReturnsAs(mult, (w, z) => mult(w, inv(z))) + }) +] + +export const invert = match(Complex, (math, C) => { + const conj = math.conj.resolve(C) + const norm = math.absquare.resolve(C) + const div = math.divide.resolve([C.Component, norm.returns]) + const cplx = math.complex.resolve([div.returns, div.returns]) + return ReturnsAs(cplx, z => { + const c = conj(z) + const d = norm(z) + return cplx(div(c.re, d), div(c.im, d)) + }) +}) + // We want this to work for complex numbers, quaternions, octonions, etc // See https://math.ucr.edu/home/baez/octonions/node5.html export const multiply = match([Complex, Complex], (math, [W, Z]) => { diff --git a/src/core/TypePatterns.js b/src/core/TypePatterns.js index a19cb2b..14f41c0 100644 --- a/src/core/TypePatterns.js +++ b/src/core/TypePatterns.js @@ -72,6 +72,7 @@ class PredicatePattern extends TypePattern { } match(typeSequence, options={}) { const position = options.position ?? 0 + if (position >= typeSequence.length) return [-1, undefined] const actual = typeSequence[position] if (this.predicate(actual)) return [position + 1, actual] return [-1, Undefined]