diff --git a/C++/README.md b/C++/README.md index 0c840b4..276cde7 100644 --- a/C++/README.md +++ b/C++/README.md @@ -15,6 +15,7 @@ * GCD _(Euclidean Algorithm)_ * GCD and Coefficients of Bézout's identity _(Extended Euclidean Algorithm)_ * LCM +* Modular Exponantiation * Prime Numbers [1 → N] _(Sieve of Eratosthenes)_ * Prime Factorization _(Trial Division)_ * Prime Factorization _(Precomputed Primes)_ diff --git a/C++/mathematics/number_theory/CMakeLists.txt b/C++/mathematics/number_theory/CMakeLists.txt index 8c57c50..462e891 100644 --- a/C++/mathematics/number_theory/CMakeLists.txt +++ b/C++/mathematics/number_theory/CMakeLists.txt @@ -1,6 +1,6 @@ target_sources(programming PRIVATE - binary_exponentiation.h + exponentiation.h factorization.h gcd.h lcm.h diff --git a/C++/mathematics/number_theory/binary_exponentiation.h b/C++/mathematics/number_theory/binary_exponentiation.h deleted file mode 100644 index 22abe06..0000000 --- a/C++/mathematics/number_theory/binary_exponentiation.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2021 Aman Mehara -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef MEHARA_BINARY_EXPONENTIATION_H_ -#define MEHARA_BINARY_EXPONENTIATION_H_ - -#include -#include - -namespace mehara::mathematics { - -template -requires std::integral -T binary_exponentiation_recursive(T a, T b) -{ - if (b == 0) { - return 1; - } - auto power = binary_exponentiation_recursive(a, b / 2); - return (b & 1) ? power * power * a : power * power; -} - -template -requires std::integral -T binary_exponentiation_iterative(T a, T b) -{ - T power = 1; - while (b > 0) { - if (b & 1) { - power *= a; - } - a *= a; - b >>= 1; - } - return power; -} - -} // namespace mehara::mathematics - -#endif // MEHARA_BINARY_EXPONENTIATION_H_ diff --git a/C++/mathematics/number_theory/exponentiation.h b/C++/mathematics/number_theory/exponentiation.h new file mode 100644 index 0000000..ded5216 --- /dev/null +++ b/C++/mathematics/number_theory/exponentiation.h @@ -0,0 +1,101 @@ +// Copyright 2021 Aman Mehara +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef MEHARA_EXPONENTIATION_H_ +#define MEHARA_EXPONENTIATION_H_ + +#include +#include + +namespace mehara::mathematics { + +template +requires std::integral +T binary_exponentiation_recursive(T a, T b) +{ + if (b == 0) { + return 1; + } + auto power = binary_exponentiation_recursive(a, b / 2); + return (b & 1) ? power * power * a : power * power; +} + +template +requires std::integral +T binary_exponentiation_iterative(T a, T b) +{ + T power = 1; + while (b > 0) { + if (b & 1) { + power = power * a; + } + a = a * a; + b >>= 1; + } + return power; +} + +template +requires std::integral +T binary_exponentiation(T a, T b, bool is_recursive = false) +{ + if (is_recursive) { + return binary_exponentiation_recursive(a, b); + } + else { + return binary_exponentiation_iterative(a, b); + } +} + +template +requires std::integral +T modular_exponentiation_recursive(T a, T b, T m) +{ + if (b == 0) { + return 1; + } + auto power = modular_exponentiation_recursive(a, b / 2, m); + return (b & 1) ? (power * power % m) * a % m : power * power % m; +} + +template +requires std::integral +T modular_exponentiation_iterative(T a, T b, T m) +{ + T power = 1; + while (b > 0) { + if (b & 1) { + power = power * a % m; + } + a = a * a % m; + b >>= 1; + } + return power; +} + +template +requires std::integral +T modular_exponentiation(T a, T b, T m, bool is_recursive = false) +{ + if (is_recursive) { + return modular_exponentiation_recursive(a, b, m); + } + else { + return modular_exponentiation_iterative(a, b, m); + } +} + +} // namespace mehara::mathematics + +#endif // MEHARA_EXPONENTIATION_H_ diff --git a/C++/test/mathematics_test.cpp b/C++/test/mathematics_test.cpp index 6e3e6b6..09c9663 100644 --- a/C++/test/mathematics_test.cpp +++ b/C++/test/mathematics_test.cpp @@ -2,7 +2,7 @@ #include "../mathematics/linear_algebra/determinant.h" #include "../mathematics/linear_algebra/gauss_jordan_elimination.h" -#include "../mathematics/number_theory/binary_exponentiation.h" +#include "../mathematics/number_theory/exponentiation.h" #include "../mathematics/number_theory/factorization.h" #include "../mathematics/number_theory/gcd.h" #include "../mathematics/number_theory/lcm.h" @@ -50,6 +50,18 @@ TEST(mathematics, binary_exponentiation) ASSERT_EQ(243, binary_exponentiation_recursive(3, 5)); ASSERT_EQ(256, binary_exponentiation_iterative(2, 8)); ASSERT_EQ(243, binary_exponentiation_iterative(3, 5)); + ASSERT_EQ(256, binary_exponentiation(2, 8)); + ASSERT_EQ(243, binary_exponentiation(3, 5)); +} + +TEST(mathematics, modular_exponentiation) +{ + ASSERT_EQ(4, modular_exponentiation_recursive(2, 8, 7)); + ASSERT_EQ(1, modular_exponentiation_recursive(3, 5, 11)); + ASSERT_EQ(4, modular_exponentiation_iterative(2, 8, 7)); + ASSERT_EQ(1, modular_exponentiation_iterative(3, 5, 11)); + ASSERT_EQ(4, modular_exponentiation(2, 8, 7)); + ASSERT_EQ(1, modular_exponentiation(3, 5, 11)); } TEST(mathematics, factorization_trial_division)