import { assert } from 'chai'; import { EPSILON, FACTOR, DOUBLE_EPSILON, DOUBLE_FACTOR, fuzzyIsNull, fuzzyCompare, fuzzyRound, fuzzyCompare2, isMinusZero, convertFloat64ToUint32, fuzzyConvertFloat64ToUint32 } from '../../../lib/math/float'; describe('math.float', () => { describe('fuzzyIsNull', () => { test.each([ [0.0, true, undefined], [-0.0, true, undefined], [NaN, false, undefined], [Infinity, false, undefined], [-Infinity, false, undefined], [Number.MAX_VALUE, false, undefined], [Number.MIN_VALUE, true, undefined], [0.0001, false, undefined], [0.000001, true, undefined], [-0.000001, true, undefined], [0.000001, false, DOUBLE_EPSILON], [-0.000001, false, DOUBLE_EPSILON], [0.0001, false, EPSILON], [0.000001, true, EPSILON], ])('fuzzyIsNull#%#', (x: number, result: boolean, epsilon: number | undefined) => { assert.strictEqual(fuzzyIsNull(x, epsilon), result); }); }); describe('fuzzyCompare', () => { test.each([ [0.0, 0.0, true, undefined], [-0.0, -0.0, true, undefined], [0.0, -0, true, undefined], [-0.0, 0.0, true, undefined], [Number.MIN_VALUE, Number.MIN_VALUE, true, undefined], [Number.MAX_VALUE, Number.MAX_VALUE, true, undefined], [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, true, undefined], [Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, true, undefined], [NaN, 0, false, undefined], [0, NaN, false, undefined], [NaN, NaN, false, undefined], [Infinity, Infinity, false, undefined], [1, 1.0001, false, undefined], [1, 1.000001, true, undefined], [1, 0.999999, true, undefined], [1, 1.000001, true, EPSILON], [1, 1.000001, false, DOUBLE_EPSILON], [1, 0.999999, false, DOUBLE_EPSILON], [1.005, 1.01, false, undefined], [1.005, 1.005, true, undefined], ])('fuzzyCompare#%#', (x: number, y: number, result: boolean, epsilon: number | undefined) => { assert.strictEqual(fuzzyCompare(x, y, epsilon), result); }); }); describe('fuzzyCompare2', () => { test.each([ [0.0, 0.0, true, undefined], [-0.0, -0.0, true, undefined], [0.0, -0, true, undefined], [-0.0, 0.0, true, undefined], [Number.MIN_VALUE, Number.MIN_VALUE, true, undefined], [Number.MAX_VALUE, Number.MAX_VALUE, true, undefined], [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, true, undefined], [Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, true, undefined], [NaN, 0, false, undefined], [0, NaN, false, undefined], [NaN, NaN, false, undefined], [Infinity, Infinity, false, undefined], [1, 1.0001, false, undefined], [1, 1.000001, true, undefined], [1, 0.999999, true, undefined], [1, 1.000001, true, FACTOR], [1, 1.000001, false, DOUBLE_FACTOR], [1, 0.999999, false, DOUBLE_FACTOR], [1.005, 1.01, false, undefined], [1.005, 1.005, true, undefined], ])('fuzzyCompare2#%#', (x: number, y: number, result: boolean, factor: number | undefined) => { assert.strictEqual(fuzzyCompare2(x, y, factor), result); }); }); // describe('fuzzyRound', () => { // test.each([ // [1.23456789012345, 1.23457, undefined], // [1.23456789012345, 1.23, 0.01], // [1.005, 1, 0.01], // ])('fuzzyRound#%#', (x: number, result: number, epsilon: number | undefined) => { // assert.isTrue(fuzzyCompare(fuzzyRound(x, epsilon), result, DOUBLE_EPSILON)); // }); // }); describe('fuzzyRound2', () => { test.each([ [1.23456789012345, 1.23457, undefined], [1.23456789012345, 1.23, 100], [1.005, 1, 100], ])('fuzzyRound2#%#', (x: number, result: number, factor: number | undefined) => { assert.isTrue(fuzzyCompare(fuzzyRound(x, factor), result, DOUBLE_EPSILON)); }); }); describe('isMinusZero', () => { test.each([ [0, false], [-0, true], [1, false], [Number.MIN_VALUE, false], [-Number.MIN_VALUE, false], [NaN, false], ])('isMinusZero#%#', (x: number, result: boolean) => { assert.strictEqual(isMinusZero(x), result); }); }); describe('convertFloat64ToUint32', () => { test.each([ // default (big-endian) [0, [0, 0], undefined], [-0.0, [0x80000000, 0], undefined], [NaN, [0x7ff80000, 0], undefined], [Infinity, [0x7ff00000, 0], undefined], [-Infinity, [0xfff00000, 0], undefined], [1, [0x3ff00000, 0], undefined], [-1, [0xbff00000, 0], undefined], [0.5, [0x3fe00000, 0], undefined], [-0.5, [0xbfe00000, 0], undefined], [100, [0x40590000, 0], undefined], [-100, [0xc0590000, 0], undefined], [1.005, [0x3ff0147a, 0xe147ae14], undefined], [-1.005, [0xbff0147a, 0xe147ae14], undefined], [3.14159265358979323846, [0x400921fb, 0x54442d18], undefined], [-3.14159265358979323846, [0xc00921fb, 0x54442d18], undefined], [Number.MAX_SAFE_INTEGER, [0x433fffff, 0xffffffff], undefined], [Number.MIN_SAFE_INTEGER, [0xc33fffff, 0xffffffff], undefined], [Number.EPSILON, [0x3cb00000, 0], undefined], [Number.MAX_VALUE, [0x7fefffff, 0xffffffff], undefined], [Number.MIN_VALUE, [0, 1], undefined], // little-endian [0, [0, 0], true], [-0.0, [0, 0x80000000], true], [NaN, [0, 0x7ff80000], true], [Infinity, [0, 0x7ff00000], true], [-Infinity, [0, 0xfff00000], true], [1, [0, 0x3ff00000], true], [-1, [0, 0xbff00000], true], [0.5, [0, 0x3fe00000], true], [-0.5, [0, 0xbfe00000], true], [100, [0, 0x40590000], true], [-100, [0, 0xc0590000], true], [1.005, [0xe147ae14, 0x3ff0147a], true], [-1.005, [0xe147ae14, 0xbff0147a], true], [3.14159265358979323846, [0x54442d18, 0x400921fb], true], [-3.14159265358979323846, [0x54442d18, 0xc00921fb], true], [Number.MAX_SAFE_INTEGER, [0xffffffff, 0x433fffff], true], [Number.MIN_SAFE_INTEGER, [0xffffffff, 0xc33fffff], true], [Number.EPSILON, [0, 0x3cb00000], true], [Number.MAX_VALUE, [0xffffffff, 0x7fefffff], true], [Number.MIN_VALUE, [1, 0], true], ])('convertFloat64ToUint32#%#', (x: number, result: number[], littleEndian: boolean | undefined) => { assert.deepEqual(convertFloat64ToUint32(x, littleEndian), result); }); }); describe('fuzzyConvertFloat64ToUint32', () => { test.each([ // default (big-endian) [0, [0, 0], undefined], [-0.0, [0x80000000, 0], undefined], [NaN, [0x7ff80000, 0], undefined], [Infinity, [0x7ff00000, 0], undefined], [-Infinity, [0xfff00000, 0], undefined], [1, [0x3ff00000, 0], undefined], [-1, [0xbff00000, 0], undefined], [0.5, [0x3fe00000, 0], undefined], [-0.5, [0xbfe00000, 0], undefined], [100, [0x40590000, 0], undefined], [-100, [0xc0590000, 0], undefined], [1.005, [0x3ff0147a, 0xe147ae14], undefined], [-1.005, [0xbff0147a, 0xe147ae14], undefined], [3.14159265358979323846, [0x400921fb, 0x54442d18], undefined], [-3.14159265358979323846, [0xc00921fb, 0x54442d18], undefined], [Number.MAX_SAFE_INTEGER, [/* 0x433fffff */ 0x434fffff, 0xffffffff], undefined], [Number.MIN_SAFE_INTEGER, [/* 0xc33fffff */ 0xc34fffff, 0xffffffff], undefined], [Number.EPSILON, [0x3cb00000, 0], undefined], [Number.MAX_VALUE, [/* 0x7fefffff */ 0x7ff00000, /* 0xffffffff */ 0], undefined], [Number.MIN_VALUE, [0, /* 1 */ 0], undefined], // little-endian [0, [0, 0], true], [-0.0, [0, 0x80000000], true], [NaN, [0, 0x7ff80000], true], [Infinity, [0, 0x7ff00000], true], [-Infinity, [0, 0xfff00000], true], [1, [0, 0x3ff00000], true], [-1, [0, 0xbff00000], true], [0.5, [0, 0x3fe00000], true], [-0.5, [0, 0xbfe00000], true], [100, [0, 0x40590000], true], [-100, [0, 0xc0590000], true], [1.005, [0xe147ae14, 0x3ff0147a], true], [-1.005, [0xe147ae14, 0xbff0147a], true], [3.14159265358979323846, [0x54442d18, 0x400921fb], true], [-3.14159265358979323846, [0x54442d18, 0xc00921fb], true], // [Number.MAX_SAFE_INTEGER, [0xffffffff, 0x433fffff], true], // [Number.MIN_SAFE_INTEGER, [0xffffffff, 0xc33fffff], true], [Number.EPSILON, [0, 0x3cb00000], true], // [Number.MAX_VALUE, [0xffffffff, 0x7fefffff], true], // [Number.MIN_VALUE, [1, 0], true], ])('fuzzyConvertFloat64ToUint32#%#', (x: number, result: number[], littleEndian: boolean | undefined) => { const expected = convertFloat64ToUint32(x, littleEndian); const actual = fuzzyConvertFloat64ToUint32(x, littleEndian); if (expected[0] !== actual[0] || expected[1] !== actual[1]) console.warn(`fuzzyConvertFloat64ToUint32(${x}, ${littleEndian}): expected [ 0x${actual[0].toString(16)}, 0x${actual[1].toString(16)} ] to be equal [ 0x${expected[0].toString(16)}, 0x${expected[1].toString(16)} ]`); assert.deepEqual(actual, result); }); }); });