pocomath/test/complex/_all.mjs

97 lines
3.4 KiB
JavaScript
Raw Normal View History

import assert from 'assert'
import math from '../../src/pocomath.mjs'
import PocomathInstance from '../../src/core/PocomathInstance.mjs'
import * as complexSqrt from '../../src/complex/sqrt.mjs'
describe('complex', () => {
2022-07-31 18:08:07 +00:00
it('supports division', () => {
assert.deepStrictEqual(
math.divide(math.complex(3,2), math.complex(0,1)),
math.complex(2,-3))
const reciprocal = math.divide(1, math.complex(1,3))
assert.strictEqual(reciprocal.re, 0.1)
assert.ok(Math.abs(reciprocal.im + 0.3) < 1e-13)
})
it('supports sqrt', () => {
assert.deepStrictEqual(math.sqrt(math.complex(1,0)), 1)
assert.deepStrictEqual(
math.sqrt(math.complex(0,1)),
math.complex(math.sqrt(0.5), math.sqrt(0.5)))
assert.deepStrictEqual(
math.sqrt(math.complex(5, 12)),
math.complex(3, 2))
math.config.predictable = true
assert.deepStrictEqual(math.sqrt(math.complex(1,0)), math.complex(1,0))
assert.deepStrictEqual(
math.sqrt(math.complex(0,1)),
math.complex(math.sqrt(0.5), math.sqrt(0.5)))
math.config.predictable = false
})
it('can bundle sqrt', async function () {
const ms = new PocomathInstance('Minimal Sqrt')
ms.install(complexSqrt)
await ms.importDependencies(['number', 'complex'])
assert.deepStrictEqual(
ms.sqrt(math.complex(0, -1)),
math.complex(ms.negate(ms.sqrt(0.5)), ms.sqrt(0.5)))
})
it('checks for equality', () => {
assert.ok(math.equal(math.complex(3, 0), 3))
assert.ok(math.equal(math.complex(3, 2), math.complex(3, 2)))
assert.ok(!(math.equal(math.complex(45n, 3n), math.complex(45n, -3n))))
assert.ok(!(math.equal(math.complex(45n, 3n), 45n)))
})
it('tests for reality', () => {
assert.ok(math.isReal(math.complex(3, 0)))
assert.ok(!(math.isReal(math.complex(3, 2))))
})
it('computes gcd', () => {
assert.deepStrictEqual(
math.gcd(math.complex(53n, 56n), math.complex(47n, -13n)),
math.complex(4n, 5n))
refactor(Complex): Now a template type! This means that the real and imaginary parts of a Complex must now be the same type. This seems like a real benefit: a Complex with a number real part and a bigint imaginary part does not seem sensible. Note that this is now straining typed-function in (at least) the following ways: (1) In this change, it was necessary to remove the logic that the square root of a negative number calls complex square root, which then calls back to the number square root in its algorithm. (This was creating a circular reference in the typed-function which the old implementation of Complex was somehow sidestepping.) (2) typed-function could not follow conversions that would be allowed by uninstantiated templates (e.g. number => Complex<number> if the latter template has not been instantiated) and so the facility for instantiating a template was surfaced (and for example is called explicitly in the demo loader `extendToComplex`. Similarly, this necessitated making the unary signature of the `complex` conversion function explicit, rather than just via implicit conversion to Complex. (3) I find the order of implementations is mattering more in typed-function definitions, implying that typed-function's sorting algorithm is having trouble distinguishing alternatives. But otherwise, the conversion went quite smoothly and I think is a good demo of the power of this approach. And I expect that it will work even more smoothly if some of the underlying facilities (subtypes, template types) are integrated into typed-function.
2022-08-06 15:27:44 +00:00
// And now works for NumInt, too!
assert.deepStrictEqual(
math.gcd(math.complex(53,56), math.complex(47, -13)),
math.complex(4, 5))
// But properly fails for general complex
assert.throws(
() => math.gcd(math.complex(5.3,5.6), math.complex(4.7, -1.3)),
TypeError
)
})
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
})
2022-08-07 03:13:50 +00:00
it('performs rudimentary quaternion calculations', () => {
const q0 = math.quaternion(1, 0, 1, 0)
const q1 = math.quaternion(1, 0.5, 0.5, 0.75)
assert.deepStrictEqual(
q1,
math.complex(math.complex(1, 0.5), math.complex(0.5, 0.75)))
assert.deepStrictEqual(
math.add(q0,q1),
math.quaternion(2, 0.5, 1.5, 0.75))
assert.deepStrictEqual(
math.multiply(q0, q1),
math.quaternion(0.5, 1.25, 1.5, 0.25))
assert.deepStrictEqual(
math.multiply(q0, math.quaternion(2, 1, 0.1, 0.1)),
math.quaternion(1.9, 1.1, 2.1, -0.9))
math.absquare(math.complex(1.25, 2.5)) //HACK: need absquare(Complex<number>)
2022-08-07 03:13:50 +00:00
assert.strictEqual(math.abs(q0), Math.sqrt(2))
assert.strictEqual(math.abs(q1), Math.sqrt(33)/4)
})
})