From 2854d1b47240deb853fc3d6939521e8fdfb9d768 Mon Sep 17 00:00:00 2001 From: Srishti Soni <92056170+shimmer12@users.noreply.github.com> Date: Sun, 12 Oct 2025 01:26:08 +0530 Subject: [PATCH 1/2] Add modular exponentiation function Implements modular exponentiation using fast binary exponentiation with optional modulus. Validates input parameters and handles negative bases correctly. --- mathematics/modular_exponentiation.r | 68 ++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 mathematics/modular_exponentiation.r diff --git a/mathematics/modular_exponentiation.r b/mathematics/modular_exponentiation.r new file mode 100644 index 00000000..5985ad8c --- /dev/null +++ b/mathematics/modular_exponentiation.r @@ -0,0 +1,68 @@ +#' Computes modular exponentiation using fast binary exponentiation. +#' +#' @param base Numeric or integer base. +#' @param exp Non-negative integer exponent. +#' @param mod Optional positive integer modulus. If `NULL`, computes +#' \eqn{base^{exp}} without modulus (may overflow for large values). +#' +#' @return If `mod` is provided, returns an integer in \[0, mod - 1\] equal to +#' \eqn{(base^{exp}) \bmod mod}. If `mod` is `NULL`, returns \eqn{base^{exp}}. +#' +#' @details +#' Implements **binary (fast) exponentiation** running in \eqn{O(\log exp)} time +#' and \eqn{O(1)} extra space. +#' - When `mod` is provided, intermediate values are reduced modulo `mod` to +#' avoid overflow and keep numbers bounded. +#' - Negative bases are handled correctly in modular mode by normalizing +#' \code{base <- (base \%\% mod + mod) \%\% mod}. +#' - Negative exponents are **not supported** (would require modular inverse). +#' +#' @examples +#' modular_exponentiation(2, 10, 1000) # 24 +#' modular_exponentiation(3, 0, 7) # 1 +#' modular_exponentiation(5, 3) # 125 (no modulus) +#' modular_exponentiation(-2, 5, 13) # 6 because (-2)^5 = -32 ≡ 6 (mod 13) +#' +#' @seealso \code{\link[base]{%%}} for modulus operator. +#' +#' @export +modular_exponentiation <- function(base, exp, mod = NULL) { + # validate exponent + if (length(exp) != 1 || is.na(exp) || exp < 0 || exp != as.integer(exp)) { + stop("`exp` must be a single non-negative integer.") + } + exp <- as.integer(exp) + + # no modulus: compute power with fast exponentiation (may overflow for large numbers) + if (is.null(mod)) { + result <- 1 + b <- base + e <- exp + while (e > 0) { + if (e %% 2L == 1L) result <- result * b + b <- b * b + e <- e %/% 2L + } + return(result) + } + + # validate modulus + if (length(mod) != 1 || is.na(mod) || mod <= 0 || mod != as.integer(mod)) { + stop("`mod` must be a single positive integer when provided.") + } + mod <- as.integer(mod) + + # normalize base into [0, mod-1] + b <- ((base %% mod) + mod) %% mod + result <- 1L + e <- exp + + while (e > 0L) { + if (e %% 2L == 1L) { + result <- (result * b) %% mod + } + b <- (b * b) %% mod + e <- e %/% 2L + } + result +} From fa247872a49951e0f0cbcf06303bd6baea17f719 Mon Sep 17 00:00:00 2001 From: Srishti Soni <92056170+shimmer12@users.noreply.github.com> Date: Sun, 12 Oct 2025 01:29:17 +0530 Subject: [PATCH 2/2] Enhance documentation for modular_exponentiation Updated example for modular_exponentiation function to include calculation explanation. --- mathematics/modular_exponentiation.r | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mathematics/modular_exponentiation.r b/mathematics/modular_exponentiation.r index 5985ad8c..49a0a417 100644 --- a/mathematics/modular_exponentiation.r +++ b/mathematics/modular_exponentiation.r @@ -18,7 +18,9 @@ #' - Negative exponents are **not supported** (would require modular inverse). #' #' @examples -#' modular_exponentiation(2, 10, 1000) # 24 +#' # 2^10 = 1024, and 1024 mod 1000 = 24 +#' modular_exponentiation(2, 10, 1000) +#' # [1] 24 #' modular_exponentiation(3, 0, 7) # 1 #' modular_exponentiation(5, 3) # 125 (no modulus) #' modular_exponentiation(-2, 5, 13) # 6 because (-2)^5 = -32 ≡ 6 (mod 13)