UNPKG

@hashgraph/solo

Version:

An opinionated CLI tool to deploy and manage private Hedera Networks.

150 lines 6.51 kB
// SPDX-License-Identifier: Apache-2.0 import { describe, it } from 'mocha'; import { expect } from 'chai'; import { MathEx } from '../../../../src/core/util/math-ex.js'; import { ArithmeticError } from '../../../../src/core/util/arithmetic-error.js'; describe('MathEx', () => { it('testLongExact', () => { testLongExactTwice(0, 0); testLongExactTwice(1, 1); testLongExactTwice(1, -1); testLongExactTwice(1000, 2000); testLongExactTwice(Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER); testLongExactTwice(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); testLongExactTwice(Number.MIN_SAFE_INTEGER, 1); testLongExactTwice(Number.MAX_SAFE_INTEGER, 1); testLongExactTwice(Number.MIN_SAFE_INTEGER, 2); testLongExactTwice(Number.MAX_SAFE_INTEGER, 2); testLongExactTwice(Number.MIN_SAFE_INTEGER, -1); testLongExactTwice(Number.MAX_SAFE_INTEGER, -1); testLongExactTwice(Number.MIN_SAFE_INTEGER, -2); testLongExactTwice(Number.MAX_SAFE_INTEGER, -2); testLongExactTwice(Math.trunc(Number.MIN_SAFE_INTEGER / 2), 2); testLongExactTwice(Math.trunc(Number.MAX_SAFE_INTEGER / 2), 2); }); it('testLongFloorDivMod', () => { testLongFloorDivModulo(4, 0, 0, 0, true, true); testLongFloorDivModulo(4, 3, 1, 1, false, false); testLongFloorDivModulo(3, 3, 1, 0, false, false); testLongFloorDivModulo(2, 3, 0, 2, false, false); testLongFloorDivModulo(1, 3, 0, 1, false, false); testLongFloorDivModulo(0, 3, 0, 0, false, false); testLongFloorDivModulo(4, -3, -2, -2, false, false); testLongFloorDivModulo(3, -3, -1, 0, false, false); testLongFloorDivModulo(2, -3, -1, -1, false, false); testLongFloorDivModulo(1, -3, -1, -2, false, false); testLongFloorDivModulo(0, -3, 0, 0, false, false); testLongFloorDivModulo(-1, 3, -1, 2, false, false); testLongFloorDivModulo(-2, 3, -1, 1, false, false); testLongFloorDivModulo(-3, 3, -1, 0, false, false); testLongFloorDivModulo(-4, 3, -2, 2, false, false); testLongFloorDivModulo(-1, -3, 0, -1, false, false); testLongFloorDivModulo(-2, -3, 0, -2, false, false); testLongFloorDivModulo(-3, -3, 1, 0, false, false); testLongFloorDivModulo(-4, -3, 1, -1, false, false); testLongFloorDivModulo(Number.MAX_SAFE_INTEGER, 1, Number.MAX_SAFE_INTEGER, 0, false, false); testLongFloorDivModulo(Number.MAX_SAFE_INTEGER, -1, -Number.MAX_SAFE_INTEGER, 0, false, false); testLongFloorDivModulo(Number.MAX_SAFE_INTEGER, 3, Math.floor(Number.MAX_SAFE_INTEGER / 3), 1, false, false); testLongFloorDivModulo(Number.MAX_SAFE_INTEGER - 1, 3, Math.floor(Number.MAX_SAFE_INTEGER - 1) / 3, 0, false, false); testLongFloorDivModulo(Number.MIN_SAFE_INTEGER, 3, Math.floor(Number.MIN_SAFE_INTEGER / 3), 1, false, false); testLongFloorDivModulo(Number.MIN_SAFE_INTEGER + 1, 3, Math.floor(Number.MIN_SAFE_INTEGER / 3) + 1, 0, false, false); testLongFloorDivModulo(Number.MIN_SAFE_INTEGER + 1, -1, Number.MAX_SAFE_INTEGER - 1, 0, false, false); // Special case of integer overflow testLongFloorDivModulo(Number.MIN_SAFE_INTEGER, -1, Number.MAX_SAFE_INTEGER, 0, false, false); }); }); function testLongExact(x, y) { let resultBig; try { resultBig = BigInt(x) + BigInt(y); const sum = MathEx.addExact(x, y); checkResult('addExact', x, y, sum, resultBig); } catch (error) { checkError('addExact', x, y, resultBig, error); } try { resultBig = BigInt(x) - BigInt(y); const diff = MathEx.subtractExact(x, y); checkResult('subtractExact', x, y, diff, resultBig); } catch (error) { checkError('subtractExact', x, y, resultBig, error); } try { resultBig = BigInt(x) * BigInt(y); const product = MathEx.multiplyExact(x, y); checkResult('multiplyExact', x, y, product, resultBig); } catch (error) { checkError('multiplyExact', x, y, resultBig, error); } } function testLongExactTwice(x, y) { testLongExact(x, y); testLongExact(y, x); } function checkError(message, x, y, resultBig, error) { if (!(error instanceof ArithmeticError)) { throw error; } if (Number.isSafeInteger(Number(resultBig))) { expect.fail(`${message}(${x}, ${y}); Unexpected exception: ${error}`); } } function checkResult(message, x, y, result, expected) { const resultBig = BigInt(result); const finalMessage = `${message}(${x}, ${y}) = ${result}`; if (!Number.isSafeInteger(Number(resultBig))) { expect.fail(`${finalMessage}; expected an arithmetic error`); } else if (resultBig !== expected) { expect.fail(`${finalMessage}; expected ${expected}`); } } function testLongFloorDivModulo(x, y, divExpected, moduloExpected, divThrows, moduloThrows) { testLongFloorDiv(x, y, divExpected, divThrows); testLongFloorModulo(x, y, moduloExpected, moduloThrows); } function testLongFloorDiv(x, y, expected, shouldThrow) { try { const result = MathEx.floorDiv(x, y); if (result !== expected) { expect.fail(`floorDiv(${x}, ${y}) = ${result}; expected ${expected}`); } if (shouldThrow) { expect.fail(`floorDiv(${x}, ${y}); expected an arithmetic error`); } } catch (error) { if (!(error instanceof ArithmeticError)) { throw error; } if (!shouldThrow) { expect.fail(`floorDiv(${x}, ${y}); Unexpected exception: ${error}`); } } } function testLongFloorModulo(x, y, expected, shouldThrow) { try { const result = MathEx.floorModulo(x, y); if (result !== expected) { expect.fail(`floorMod(${x}, ${y}) = ${result}; expected ${expected}`); } if (shouldThrow) { expect.fail(`floorMod(${x}, ${y}); expected an arithmetic error`); } } catch (error) { if (!(error instanceof ArithmeticError)) { throw error; } if (error instanceof ArithmeticError && y !== 0) { expect.fail(`floorMod(${x}, ${y}); Unexpected arithmetic error: ${error}`); } if (!shouldThrow) { expect.fail(`floorMod(${x}, ${y}); Unexpected exception: ${error}`); } } } //# sourceMappingURL=math-ex.test.js.map