diff --git a/lib/utils/math-utils.js b/lib/utils/math-utils.js new file mode 100644 index 000000000..3a35c78a9 --- /dev/null +++ b/lib/utils/math-utils.js @@ -0,0 +1,13 @@ +// @flow + +function leastPositiveResidue(dividend: number, modulus: number): number { + // the smallest positive of x is integer k such that + // x is congruent to k (mod n) + // in our case we only consider n > 0 + if (modulus <= 0) { + throw new Error(`modulus must be greater than 0, but was ${modulus}`); + } + return dividend - Math.floor(dividend / modulus) * modulus; +} + +export { leastPositiveResidue }; diff --git a/lib/utils/math-utils.test.js b/lib/utils/math-utils.test.js new file mode 100644 index 000000000..8a9dbcc2c --- /dev/null +++ b/lib/utils/math-utils.test.js @@ -0,0 +1,23 @@ +// @flow + +import { leastPositiveResidue } from './math-utils'; + +describe('leastPositiveResidue', () => { + it('x should be equal to 2 for x ≡ 8 (mod 3)', () => { + expect(leastPositiveResidue(8, 3)).toEqual(2); + }); + + it('x should be equal to 5 for x ≡ 19 (mod 7)', () => { + expect(leastPositiveResidue(19, 7)).toEqual(5); + }); + + it('x should be equal to 7 for x ≡ -3 (mod 11)', () => { + expect(leastPositiveResidue(-3, 10)).toEqual(7); + }); + + it('function should throw error', () => { + expect(() => leastPositiveResidue(5, -1)).toThrow( + 'modulus must be greater than 0, but was -1', + ); + }); +});