Path: blob/main/foundations/01-modular-arithmetic-groups/rust/src/lib.rs
483 views
unlisted
//! # Module 01: Modular Arithmetic and Groups — Exercises1//!2//! Work through these after completing the SageMath notebooks.3//! Implement each function, then remove `#[ignore]` from its tests to verify.4//!5//! ## Progression6//! 1. `mod_exp` — Guided (loop structure provided)7//! 2. `gcd` — Guided (algorithm outline provided)8//! 3. `is_generator` — Scaffolded (signature + hints)9//! 4. `element_order` — Scaffolded (signature + hints)10//! 5. `find_all_generators` — Independent (just the signature)1112/// Compute `base^exp mod modulus` using repeated squaring.13///14/// # Example15/// ```16/// # use mod_arith_groups::mod_exp;17/// assert_eq!(mod_exp(2, 10, 1000), 24);18/// ```19pub fn mod_exp(base: u64, exp: u64, modulus: u64) -> u64 {20// Square-and-multiply algorithm:21// result = 1, base = base % modulus22// While exp > 0:23// if exp is odd: result = result * base mod modulus24// exp = exp / 225// base = base * base mod modulus26//27// Watch out for overflow: cast to u128 before multiplying.28let mut result: u64 = 1;29let mut base = base % modulus;30let mut exp = exp;31while exp > 0 {32if exp % 2 == 1 {33// TODO: multiply result by base (mod modulus)34todo!("result = result * base mod modulus")35}36exp /= 2;37// TODO: square base (mod modulus)38todo!("base = base * base mod modulus")39}40result41}4243/// Compute gcd(a, b) using the Euclidean algorithm.44///45/// # Example46/// ```47/// # use mod_arith_groups::gcd;48/// assert_eq!(gcd(48, 18), 6);49/// ```50pub fn gcd(a: u64, b: u64) -> u64 {51// Euclidean algorithm:52// while b != 0: (a, b) = (b, a % b)53// return a54let mut a = a;55let mut b = b;56loop {57if b == 0 {58return a;59}60// TODO: one step — set (a, b) = (b, a % b)61todo!("Update a and b")62}63}6465/// Check whether `g` is a generator of (Z/pZ)*.66///67/// `g` is a generator iff for every prime factor `q` of `p - 1`,68/// `g^((p-1)/q) ≢ 1 (mod p)`.69///70/// Assume `p` is prime.71pub fn is_generator(g: u64, p: u64) -> bool {72// Hint: first find the prime factors of p - 1.73// Then for each factor q, check that mod_exp(g, (p-1)/q, p) != 1.74todo!("Check if g generates (Z/pZ)*")75}7677/// Compute the multiplicative order of `a` in (Z/nZ)*.78///79/// Returns `None` if gcd(a, n) != 1 (a is not in the group).80///81/// Hint: try successive powers of `a` until you reach 1.82pub fn element_order(a: u64, n: u64) -> Option<u64> {83// Hint: if gcd(a, n) != 1, return None.84// Otherwise, compute a, a^2, a^3, ... mod n until you get 1.85todo!("Find the smallest k where a^k ≡ 1 (mod n)")86}8788/// Find all generators of (Z/pZ)*, returned as a sorted Vec.89///90/// Assume `p` is prime. There are exactly φ(p-1) generators.91pub fn find_all_generators(p: u64) -> Vec<u64> {92todo!("Return all generators of (Z/pZ)*")93}9495#[cfg(test)]96mod tests {97use super::*;9899// ── mod_exp ──100101#[test]102#[ignore]103fn test_mod_exp_basic() {104assert_eq!(mod_exp(2, 10, 1000), 24);105}106107#[test]108#[ignore]109fn test_mod_exp_large() {110assert_eq!(mod_exp(3, 100, 1_000_000_007), 981_147_432);111}112113#[test]114#[ignore]115fn test_mod_exp_edge_cases() {116assert_eq!(mod_exp(5, 0, 13), 1);117assert_eq!(mod_exp(0, 5, 13), 0);118}119120// ── gcd ──121122#[test]123#[ignore]124fn test_gcd_basic() {125assert_eq!(gcd(48, 18), 6);126assert_eq!(gcd(100, 75), 25);127}128129#[test]130#[ignore]131fn test_gcd_coprime() {132assert_eq!(gcd(17, 13), 1);133}134135#[test]136#[ignore]137fn test_gcd_with_zero() {138assert_eq!(gcd(42, 0), 42);139assert_eq!(gcd(0, 42), 42);140}141142// ── is_generator ──143144#[test]145#[ignore]146fn test_is_generator_true() {147assert!(is_generator(3, 7));148}149150#[test]151#[ignore]152fn test_is_generator_false() {153assert!(!is_generator(2, 7));154}155156// ── element_order ──157158#[test]159#[ignore]160fn test_element_order_generator() {161assert_eq!(element_order(3, 7), Some(6));162}163164#[test]165#[ignore]166fn test_element_order_non_generator() {167assert_eq!(element_order(2, 7), Some(3));168}169170#[test]171#[ignore]172fn test_element_order_not_in_group() {173assert_eq!(element_order(4, 8), None);174}175176// ── find_all_generators ──177178#[test]179#[ignore]180fn test_find_all_generators_7() {181assert_eq!(find_all_generators(7), vec![3, 5]);182}183184#[test]185#[ignore]186fn test_find_all_generators_13() {187assert_eq!(find_all_generators(13), vec![2, 6, 7, 11]);188}189}190191192