feat: config and approximate equality (#19)
All checks were successful
/ test (push) Successful in 17s
All checks were successful
/ test (push) Successful in 17s
Establishes a global config object for a TypeDispatcher instance, so far with just properties representing comparison tolerances. Begins a "relational" group of functions with basic approximate equality, and an initial primitive ordering comparison. Ensures that methods that depend on properties of `config` will be properly updated when those properties change. Reviewed-on: #19 Co-authored-by: Glen Whitney <glen@studioinfinity.org> Co-committed-by: Glen Whitney <glen@studioinfinity.org>
This commit is contained in:
parent
27fa4b0193
commit
70ce01d12b
27 changed files with 788 additions and 218 deletions
82
src/generic/__test__/relational.spec.js
Normal file
82
src/generic/__test__/relational.spec.js
Normal file
|
@ -0,0 +1,82 @@
|
|||
import assert from 'assert'
|
||||
import math from '#nanomath'
|
||||
import * as numbers from '#number/all.js'
|
||||
import * as generics from '#generic/all.js'
|
||||
import {ResolutionError} from '#core/helpers.js'
|
||||
import {TypeDispatcher} from '#core/TypeDispatcher.js'
|
||||
|
||||
describe('generic relational functions', () => {
|
||||
it('tests equality for anything, approx on numbers', () => {
|
||||
const {equal} = math
|
||||
assert(equal(undefined, undefined))
|
||||
assert(equal(math.types.NumberT, math.types.NumberT))
|
||||
assert(!equal(math.types.NumberT, math.types.BooleanT))
|
||||
assert(!equal(undefined, math.types.NumberT))
|
||||
assert(equal(1, 1))
|
||||
assert(equal(true, 1)) // questionable but same as mathjs
|
||||
assert(!equal(undefined, true))
|
||||
assert(equal(1, 1 + 0.9e-12))
|
||||
assert(equal(0, 1e-16))
|
||||
assert(!equal(1, 1 + 1.1e-12))
|
||||
assert(!equal(0, 1.1e-15))
|
||||
})
|
||||
it('adjusts equality when config changes', () => {
|
||||
const jn = new TypeDispatcher(generics, numbers)
|
||||
const {equal} = jn
|
||||
assert.strictEqual(equal(1, 1 + 0.9e-12), 1)
|
||||
assert.strictEqual(equal(0, 1e-16), 1)
|
||||
assert.strictEqual(equal(1, 1 + 1.1e-12), 0)
|
||||
assert.strictEqual(equal(0, 1.1e-15), 0)
|
||||
|
||||
jn.config.relTol = 1e-10
|
||||
assert.strictEqual(equal(1, 1 + 1.1e-12), 1)
|
||||
assert.strictEqual(equal(1, 1 + 1.1e-10), 0)
|
||||
assert.strictEqual(equal(0, 1.1e-15), 0)
|
||||
|
||||
jn.config.absTol = 1e-13
|
||||
assert.strictEqual(equal(1, 1 + 1.1e-12), 1)
|
||||
assert.strictEqual(equal(1, 1 + 1.1e-10), 0)
|
||||
assert.strictEqual(equal(0, 1.1e-15), 1)
|
||||
assert.strictEqual(equal(0, 1.1e-13), 0)
|
||||
})
|
||||
it('performs three-way comparison', () => {
|
||||
const {compare} = math
|
||||
assert.strictEqual(compare(-0.4e-15, +0.4e-15), 0)
|
||||
assert.strictEqual(compare(2.2, true), 1)
|
||||
assert.strictEqual(compare(-Infinity, 7), -1)
|
||||
assert(isNaN(compare(NaN, 0)))
|
||||
assert.throws(() => compare(false, NaN), TypeError)
|
||||
assert(isNaN(compare(NaN, NaN)))
|
||||
assert.throws(() => compare(true, false), TypeError)
|
||||
assert.throws(() => compare(undefined, -1), ResolutionError)
|
||||
})
|
||||
it('determines the sign of numeric values', () => {
|
||||
const {sign} = math
|
||||
assert.strictEqual(sign(-8e-16), 0)
|
||||
assert.strictEqual(sign(Infinity), 1)
|
||||
assert.strictEqual(sign(-8e-14), -1)
|
||||
assert(isNaN(sign(NaN)))
|
||||
assert.throws(() => sign(false), TypeError)
|
||||
assert.throws(() => sign(undefined), ResolutionError)
|
||||
})
|
||||
it('computes inequalities', () => {
|
||||
const {unequal, larger, largerEq, smaller, smallerEq} = math
|
||||
assert(!unequal(undefined, undefined))
|
||||
assert(!unequal(math.types.NumberT, math.types.NumberT))
|
||||
assert(unequal(math.types.NumberT, math.types.BooleanT))
|
||||
assert(unequal(undefined, math.types.NumberT))
|
||||
assert(!unequal(1, 1))
|
||||
assert(!unequal(true, 1)) // questionable but same as mathjs
|
||||
assert(unequal(undefined, true))
|
||||
assert(!unequal(1, 1 + 0.9e-12))
|
||||
assert(!unequal(0, 1e-16))
|
||||
assert(unequal(1, 1 + 1.1e-12))
|
||||
assert(unequal(0, 1.1e-15))
|
||||
assert(larger(true, 0.5))
|
||||
assert(!larger(3 + 1e-16, 3))
|
||||
assert(largerEq(0.5, false))
|
||||
assert(largerEq(3 + 1e-16, 3))
|
||||
assert(smallerEq(3 + 1e-16, 3))
|
||||
assert(!smaller(3, 3 + 1e-16))
|
||||
})
|
||||
})
|
13
src/generic/__test__/utils.spec.js
Normal file
13
src/generic/__test__/utils.spec.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import assert from 'assert'
|
||||
import math from '#nanomath'
|
||||
|
||||
describe('generic utility functions', () => {
|
||||
it('tests whether an element is zero', () => {
|
||||
const {isZero} = math
|
||||
assert(!isZero(3))
|
||||
assert(isZero(3e-16))
|
||||
assert(isZero(false))
|
||||
assert(!isZero(true))
|
||||
assert(isZero(undefined))
|
||||
})
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue