Glen Whitney
e26df5f4fc
Even in the setup just prior to this commit, a quaternion with entries of type `number` is simply a `Complex<Complex<number>>` So if we provide a convenience wrapper to create sucha thing, we instantly have a quaternion data type. All of the operations come for "free" if they were properly defined for the `Complex` template. Multiplication already was, `abs` needed a little tweak, but there is absolutely no "extra" code to support quaternions. (This commit does not go through and check all arithmetic functions for proper operation and tweak those that still need some generalization.) Note that with the recursive template instantiation, a limit had to be placed on template instantiation depth. The limit moves deeper as actual arguments that are deeper nested instantiations are seen, so as long as one doesn't immediately invoke a triply-nested template, for example, the limit will never prevent an actual computation. It just prevents a runaway in the types that Pocomath thinks it needs to know about. (Basically before, using the quaternion creator would produce `Complex<Complex<number>>`. Then when you called it again, Pocomath would think "Maybe I will need `Complex<Complex<Complex<number>>>`?!" and create that, even though it had never seen that, and then another level next time, and so on. The limit just stops this progression one level beyond any nesting depth that's actually been observed.
91 lines
3.2 KiB
JavaScript
91 lines
3.2 KiB
JavaScript
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', () => {
|
|
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('computes gcd', () => {
|
|
assert.deepStrictEqual(
|
|
math.gcd(math.complex(53n, 56n), math.complex(47n, -13n)),
|
|
math.complex(4n, 5n))
|
|
// 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
|
|
})
|
|
|
|
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))
|
|
assert.strictEqual(math.abs(q0), Math.sqrt(2))
|
|
assert.strictEqual(math.abs(q1), Math.sqrt(33)/4)
|
|
})
|
|
|
|
})
|