2022-07-25 11:20:13 +00:00
|
|
|
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)
|
|
|
|
})
|
|
|
|
|
2022-07-25 11:20:13 +00:00
|
|
|
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)))
|
2022-07-25 18:56:12 +00:00
|
|
|
assert.deepStrictEqual(
|
|
|
|
math.sqrt(math.complex(5, 12)),
|
|
|
|
math.complex(3, 2))
|
2022-07-25 11:20:13 +00:00
|
|
|
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)))
|
|
|
|
})
|
|
|
|
|
2022-08-01 10:09:32 +00:00
|
|
|
it('checks for equality', () => {
|
2022-08-30 19:36:44 +00:00
|
|
|
assert.ok(math.equal(math.complex(3, 0), 3))
|
|
|
|
assert.ok(math.equal(math.complex(3, 2), math.complex(3, 2)))
|
2022-08-01 10:09:32 +00:00
|
|
|
assert.ok(!(math.equal(math.complex(45n, 3n), math.complex(45n, -3n))))
|
|
|
|
assert.ok(!(math.equal(math.complex(45n, 3n), 45n)))
|
|
|
|
})
|
|
|
|
|
2022-11-26 22:28:19 +00:00
|
|
|
it('tests for reality', () => {
|
|
|
|
assert.ok(math.isReal(math.complex(3, 0)))
|
|
|
|
assert.ok(!(math.isReal(math.complex(3, 2))))
|
|
|
|
})
|
|
|
|
|
2022-07-30 11:59:04 +00:00
|
|
|
it('computes gcd', () => {
|
|
|
|
assert.deepStrictEqual(
|
|
|
|
math.gcd(math.complex(53n, 56n), math.complex(47n, -13n)),
|
|
|
|
math.complex(4n, 5n))
|
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
|
|
|
|
)
|
2022-07-30 11:59:04 +00:00
|
|
|
})
|
|
|
|
|
2022-08-01 15:28:21 +00:00
|
|
|
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
|
|
|
|
})
|
|
|
|
|
feat(quaternion): Add convenience quaternion creator function
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.
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))
|
2022-08-30 19:36:44 +00:00
|
|
|
math.absquare(math.complex(1.25, 2.5)) //HACK: need absquare(Complex<number>)
|
feat(quaternion): Add convenience quaternion creator function
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.
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)
|
|
|
|
})
|
|
|
|
|
2022-07-25 11:20:13 +00:00
|
|
|
})
|