pocomath/tools/approx.mjs

47 lines
1.4 KiB
JavaScript

import assert from 'assert'
export const epsilon = 1e-12
const isNumber = entity => (typeof entity === 'number')
export function equal(a, b) {
if (isNumber(a) && isNumber(b)) {
if (a === b) return true
if (isNaN(a)) return assert.strictEqual(a.toString(), b.toString())
const message = `${a} ~= ${b} (to ${epsilon})`
if (a === 0) return assert.ok(Math.abs(b) < epsilon, message)
if (b === 0) return assert.ok(Math.abs(a) < epsilon, message)
const diff = Math.abs(a - b)
const maxDiff = Math.abs(epsilon * Math.max(Math.abs(a), Math.abs(b)))
return assert.ok(diff <= maxDiff, message)
}
return assert.strictEqual(a, b)
}
export function deepEqual(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
const alen = a.length
assert.strictEqual(alen, b.length, `${a} ~= ${b}`)
for (let i = 0; i < alen; ++i) deepEqual(a[i], b[i])
return true
}
if (typeof a === 'object' && typeof b === 'object') {
for (const prop in a) {
if (a.hasOwnProperty(prop)) {
assert.ok(
b.hasOwnProperty(prop), `a[${prop}] = ${a[prop]} ~= ${b[prop]}`)
deepEqual(a[prop], b[prop])
}
}
for (const prop in b) {
if (b.hasOwnProperty(prop)) {
assert.ok(
a.hasOwnProperty(prop), `${a[prop]} ~= ${b[prop]} = b[${prop}]`)
}
}
return true
}
return equal(a, b)
}