From 5341547455f8aeee1d0d588bb09113bcce080e51 Mon Sep 17 00:00:00 2001 From: svr8 <shikhar.vaish90@gmail.com> Date: Mon, 3 Sep 2018 23:09:28 +0530 Subject: [PATCH] Added fast-exponentiation algorithm --- README.md | 4 ++- package-lock.json | 36 ++++++++++++++----- .../math/fast-exponentiation/README.md | 10 ++++++ .../__test__/fastExponent.test.js | 16 +++++++++ .../__test__/modularExponent.test.js | 16 +++++++++ .../math/fast-exponentiation/fastExponent.js | 20 +++++++++++ .../fast-exponentiation/modularExponent.js | 23 ++++++++++++ 7 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 src/algorithms/math/fast-exponentiation/README.md create mode 100644 src/algorithms/math/fast-exponentiation/__test__/fastExponent.test.js create mode 100644 src/algorithms/math/fast-exponentiation/__test__/modularExponent.test.js create mode 100644 src/algorithms/math/fast-exponentiation/fastExponent.js create mode 100644 src/algorithms/math/fast-exponentiation/modularExponent.js diff --git a/README.md b/README.md index 915b3fb38e..26c3b5234e 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,9 @@ a set of rules that precisely define a sequence of operations. * `B` [Factorial](src/algorithms/math/factorial) * `B` [Fibonacci Number](src/algorithms/math/fibonacci) * `B` [Primality Test](src/algorithms/math/primality-test) (trial division method) - * `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) + * `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest + Common Divisor (GCD) + * `B` [Fast Exponentiation](src/algorithms/math/fast-exponentiation) * `B` [Least Common Multiple](src/algorithms/math/least-common-multiple) (LCM) * `B` [Sieve of Eratosthenes](src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit * `B` [Is Power of Two](src/algorithms/math/is-power-of-two) - check if the number is power of two (naive and bitwise algorithms) diff --git a/package-lock.json b/package-lock.json index 7fd3e2e127..11cfc72b28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2478,12 +2478,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2498,17 +2500,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2625,7 +2630,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2637,6 +2643,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2651,6 +2658,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2658,12 +2666,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -2682,6 +2692,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -2762,7 +2773,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2774,6 +2786,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2895,6 +2908,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7360,12 +7374,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7385,7 +7401,8 @@ "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", @@ -7533,6 +7550,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } diff --git a/src/algorithms/math/fast-exponentiation/README.md b/src/algorithms/math/fast-exponentiation/README.md new file mode 100644 index 0000000000..771ec39057 --- /dev/null +++ b/src/algorithms/math/fast-exponentiation/README.md @@ -0,0 +1,10 @@ +# Fast Exponentiation Algorithm +The operation of modular exponentiation calculates the remainder when an integer `b` (the base) raised to the eth power (the exponent), be, is divided by a positive integer m (the modulus). In symbols, given base `b`, exponent e, and modulus m, the modular exponentiation `c` is: `c ≡ b^e (mod m)`. + +# Modular Arithmetic +- `(a + b) % m` = `( a%m + b%m ) % m` +- `(a * b) % m` = `( a%m * b%m ) % m` + + +## References +- [Wikipedia](https://en.wikipedia.org/wiki/Modular_exponentiation) \ No newline at end of file diff --git a/src/algorithms/math/fast-exponentiation/__test__/fastExponent.test.js b/src/algorithms/math/fast-exponentiation/__test__/fastExponent.test.js new file mode 100644 index 0000000000..ed09a47881 --- /dev/null +++ b/src/algorithms/math/fast-exponentiation/__test__/fastExponent.test.js @@ -0,0 +1,16 @@ +import fastExponent from '../fastExponent'; + +describe('fastExponent', () => { + it('should calculate power using fast exponentiation algorithm', () => { + expect(fastExponent(5, 5)).toBe(3125); + }); + it('should calculate power using fast exponentiation algorithm', () => { + expect(fastExponent(123, 4)).toBe(228886641); + }); + it('should calculate power using fast exponentiation algorithm', () => { + expect(fastExponent(2, 15)).toBe(32768); + }); + it('should calculate power using fast exponentiation algorithm', () => { + expect(fastExponent(43, 3)).toBe(79507); + }); +}); diff --git a/src/algorithms/math/fast-exponentiation/__test__/modularExponent.test.js b/src/algorithms/math/fast-exponentiation/__test__/modularExponent.test.js new file mode 100644 index 0000000000..d9885a7f1d --- /dev/null +++ b/src/algorithms/math/fast-exponentiation/__test__/modularExponent.test.js @@ -0,0 +1,16 @@ +import modularExponent from '../modularExponent'; + +describe('modularExponent', () => { + it('should calculate power using fast exponentiation algorithm', () => { + expect(modularExponent(5, 5, 23)).toBe(20); + }); + it('should calculate power using fast exponentiation algorithm', () => { + expect(modularExponent(123, 4, 10001)).toBe(3755); + }); + it('should calculate power using fast exponentiation algorithm', () => { + expect(modularExponent(2, 15, 13)).toBe(8); + }); + it('should calculate power using fast exponentiation algorithm', () => { + expect(modularExponent(43, 3, 1000000007)).toBe(79507); + }); +}); diff --git a/src/algorithms/math/fast-exponentiation/fastExponent.js b/src/algorithms/math/fast-exponentiation/fastExponent.js new file mode 100644 index 0000000000..4f22ad9346 --- /dev/null +++ b/src/algorithms/math/fast-exponentiation/fastExponent.js @@ -0,0 +1,20 @@ +/** + * @param {number} base + * @param {number} exponent + * @return {number} + */ + +export default function fastExponent(base, exponent) { + let x = base; + let y = exponent; + let res = 1; + + + while (y > 0) { + if (y & 1) res *= x; + y >>= 1; + x *= x; + } + + return res; +} diff --git a/src/algorithms/math/fast-exponentiation/modularExponent.js b/src/algorithms/math/fast-exponentiation/modularExponent.js new file mode 100644 index 0000000000..51c7272181 --- /dev/null +++ b/src/algorithms/math/fast-exponentiation/modularExponent.js @@ -0,0 +1,23 @@ +/** + * @param {number} base + * @param {number} exponent + * @param {number} m + * @return {number} + */ + +export default function modularExponent(base, exponent, m) { + let x = base; + let y = exponent; + let res = 1; + const p = m; + + x %= p; + + while (y > 0) { + if (y & 1) res = (res * x) % p; + y >>= 1; + x = (x * x) % p; + } + + return res; +}