Data update
This commit is contained in:
parent
4d5544505c
commit
4924dd0264
3073 changed files with 55820 additions and 4408 deletions
|
|
@ -1,10 +1,10 @@
|
|||
'''[[wp:Modular arithmetic|Modular arithmetic]]''' is a form of arithmetic (a calculation technique involving the concepts of addition and multiplication) which is done on numbers with a defined [[wp:equivalence relation|equivalence relation]] called ''congruence''.
|
||||
|
||||
For any positive integer <math>p</math> called the ''congruence modulus'',
|
||||
two numbers <math>a</math> and <math>b</math> are said to be ''congruent modulo p'' whenever there exists an integer <math>k</math> such that:
|
||||
:<math>a = b + k\,p</math>
|
||||
For any positive integer <math>m</math> called the ''congruence modulus'',
|
||||
two numbers <math>a</math> and <math>b</math> are said to be ''congruent modulo m'' whenever there exists an integer <math>k</math> such that:
|
||||
:<math>a = b + k\,m</math>
|
||||
|
||||
The corresponding set of [[wp:equivalence class|equivalence class]]es forms a [[wp:ring (mathematics)|ring]] denoted <math>\frac{\Z}{p\Z}</math>. When p is a prime number, this ring becomes a [[wp:field (mathematics)|field]] denoted <math>\mathbb{F}_p</math>, but you won't have to implement the [[wp:multiplicative inverse|multiplicative inverse]] for this task.
|
||||
The corresponding set of [[wp:equivalence class|equivalence class]]es forms a [[wp:ring (mathematics)|ring]] denoted <math>\Z/m\Z</math>. When <math>q=p^k \,(k>0)</math> is a prime power, the ring <math>\Z/q\Z</math> becomes a [[wp:Finite field|finite field]], usually denoted <math>\mathbb{F}_q</math> or <math>\mathrm{GF}(q)</math>, but you won't have to implement the [[wp:multiplicative inverse|multiplicative inverse]] for this task.
|
||||
|
||||
Addition and multiplication on this ring have the same algebraic structure as in usual arithmetic, so that a function such as a polynomial expression could receive a ring element as argument and give a consistent result.
|
||||
|
||||
|
|
@ -22,3 +22,4 @@ In other words, the function is an algebraic expression that could be used with
|
|||
;Related tasks:
|
||||
[[Modular exponentiation]]
|
||||
<br><br>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
(defpackage :rosetta-code/modular-arithmetic
|
||||
(:use :cl))
|
||||
|
||||
(in-package :rosetta-code/modular-arithmetic)
|
||||
|
||||
(defparameter *modulus* nil)
|
||||
|
||||
(defun make-modular (op)
|
||||
(lambda (&rest args)
|
||||
(let ((result (apply op args)))
|
||||
(if *modulus*
|
||||
(mod result *modulus*)
|
||||
result))))
|
||||
|
||||
(let ((ops '(+ expt))) ; add more operators as you need
|
||||
(shadow ops)
|
||||
(dolist (op ops)
|
||||
(setf (symbol-function (find-symbol (symbol-name op)))
|
||||
(make-modular (symbol-function (find-symbol (symbol-name op) :cl))))))
|
||||
|
||||
(defun f (x)
|
||||
(+ (expt x 100) x 1))
|
||||
|
||||
(format t "No modulus: f(~a) = ~a~%" 10 (f 10))
|
||||
(format t "Modulus 13: f(~a) = ~a~%" 10 (let ((*modulus* 13)) (f 10)))
|
||||
177
Task/Modular-arithmetic/Rust/modular-arithmetic.rs
Normal file
177
Task/Modular-arithmetic/Rust/modular-arithmetic.rs
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
use std::fmt;
|
||||
use std::ops::{Add, Mul};
|
||||
|
||||
// Generic function f that works with any type T that implements the required traits
|
||||
fn f<T>(x: T) -> T
|
||||
where
|
||||
T: Copy + Add<Output = T> + From<i32>,
|
||||
ModularInteger: From<T>,
|
||||
T: From<ModularInteger>,
|
||||
{
|
||||
// Convert to ModularInteger to use the pow function, then convert back
|
||||
let mod_int = ModularInteger::from(x);
|
||||
let powered = mod_int.pow(100);
|
||||
T::from(powered + ModularInteger::from(x) + ModularInteger::from(T::from(1)))
|
||||
}
|
||||
|
||||
// For the specific case of ModularInteger, we implement f directly
|
||||
impl ModularInteger {
|
||||
fn f_specific(self) -> Self {
|
||||
self.pow(100) + self + ModularInteger::new(1, self.modulus)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
struct ModularInteger {
|
||||
value: i32,
|
||||
modulus: i32,
|
||||
}
|
||||
|
||||
impl ModularInteger {
|
||||
fn new(v: i32, m: i32) -> Self {
|
||||
ModularInteger {
|
||||
value: v.rem_euclid(m), // Use rem_euclid for proper modular arithmetic
|
||||
modulus: m,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_value(&self) -> i32 {
|
||||
self.value
|
||||
}
|
||||
|
||||
fn get_modulus(&self) -> i32 {
|
||||
self.modulus
|
||||
}
|
||||
|
||||
fn validate_op(&self, rhs: &ModularInteger) -> Result<(), String> {
|
||||
if self.modulus != rhs.modulus {
|
||||
Err("Left-hand modulus does not match right-hand modulus.".to_string())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn pow(&self, mut exp: i32) -> Self {
|
||||
if exp < 0 {
|
||||
panic!("Power must not be negative.");
|
||||
}
|
||||
|
||||
let mut base = ModularInteger::new(1, self.modulus);
|
||||
let mut current = *self;
|
||||
|
||||
// Use fast exponentiation algorithm
|
||||
while exp > 0 {
|
||||
if exp % 2 == 1 {
|
||||
base = base * current;
|
||||
}
|
||||
current = current * current;
|
||||
exp /= 2;
|
||||
}
|
||||
base
|
||||
}
|
||||
}
|
||||
|
||||
// Implement Add trait for ModularInteger + ModularInteger
|
||||
impl Add<ModularInteger> for ModularInteger {
|
||||
type Output = ModularInteger;
|
||||
|
||||
fn add(self, rhs: ModularInteger) -> ModularInteger {
|
||||
self.validate_op(&rhs).expect("Modulus mismatch");
|
||||
ModularInteger::new(self.value + rhs.value, self.modulus)
|
||||
}
|
||||
}
|
||||
|
||||
// Implement Add trait for ModularInteger + i32
|
||||
impl Add<i32> for ModularInteger {
|
||||
type Output = ModularInteger;
|
||||
|
||||
fn add(self, rhs: i32) -> ModularInteger {
|
||||
ModularInteger::new(self.value + rhs, self.modulus)
|
||||
}
|
||||
}
|
||||
|
||||
// Implement Mul trait for ModularInteger * ModularInteger
|
||||
impl Mul<ModularInteger> for ModularInteger {
|
||||
type Output = ModularInteger;
|
||||
|
||||
fn mul(self, rhs: ModularInteger) -> ModularInteger {
|
||||
self.validate_op(&rhs).expect("Modulus mismatch");
|
||||
ModularInteger::new(self.value * rhs.value, self.modulus)
|
||||
}
|
||||
}
|
||||
|
||||
// Implement Display trait for pretty printing
|
||||
impl fmt::Display for ModularInteger {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ModularInteger({}, {})", self.value, self.modulus)
|
||||
}
|
||||
}
|
||||
|
||||
// Conversion traits for the generic function
|
||||
impl From<i32> for ModularInteger {
|
||||
fn from(value: i32) -> Self {
|
||||
ModularInteger::new(value, 13) // Default modulus for demonstration
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ModularInteger> for i32 {
|
||||
fn from(mod_int: ModularInteger) -> Self {
|
||||
mod_int.value
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = ModularInteger::new(10, 13);
|
||||
let output = input.f_specific(); // Using the specific implementation for ModularInteger
|
||||
println!("f({}) = {}", input, output);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_modular_integer_creation() {
|
||||
let mi = ModularInteger::new(15, 13);
|
||||
assert_eq!(mi.get_value(), 2);
|
||||
assert_eq!(mi.get_modulus(), 13);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_addition() {
|
||||
let mi1 = ModularInteger::new(10, 13);
|
||||
let mi2 = ModularInteger::new(5, 13);
|
||||
let result = mi1 + mi2;
|
||||
assert_eq!(result.get_value(), 2); // (10 + 5) % 13 = 2
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiplication() {
|
||||
let mi1 = ModularInteger::new(10, 13);
|
||||
let mi2 = ModularInteger::new(5, 13);
|
||||
let result = mi1 * mi2;
|
||||
assert_eq!(result.get_value(), 11); // (10 * 5) % 13 = 11
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_power() {
|
||||
let mi = ModularInteger::new(2, 13);
|
||||
let result = mi.pow(3);
|
||||
assert_eq!(result.get_value(), 8); // 2^3 = 8
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Modulus mismatch")]
|
||||
fn test_mismatched_modulus() {
|
||||
let mi1 = ModularInteger::new(10, 13);
|
||||
let mi2 = ModularInteger::new(5, 17);
|
||||
let _ = mi1 + mi2;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Power must not be negative")]
|
||||
fn test_negative_power() {
|
||||
let mi = ModularInteger::new(2, 13);
|
||||
mi.pow(-1);
|
||||
}
|
||||
}
|
||||
94
Task/Modular-arithmetic/Zig/modular-arithmetic.zig
Normal file
94
Task/Modular-arithmetic/Zig/modular-arithmetic.zig
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
const std = @import("std");
|
||||
const print = std.debug.print;
|
||||
|
||||
// Generic function f that works with any type T
|
||||
fn f(comptime T: type, x: T) T {
|
||||
const pow_result = pow(T, x, 100);
|
||||
const temp = pow_result.add(x) catch unreachable; // Same modulus, won't error
|
||||
return temp.addInt(1);
|
||||
}
|
||||
|
||||
// ModularInteger struct
|
||||
const ModularInteger = struct {
|
||||
value: i32,
|
||||
modulus: i32,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
// Constructor
|
||||
pub fn init(v: i32, m: i32) Self {
|
||||
return Self{
|
||||
.value = @mod(v, m),
|
||||
.modulus = m,
|
||||
};
|
||||
}
|
||||
|
||||
// Getter methods
|
||||
pub fn getValue(self: Self) i32 {
|
||||
return self.value;
|
||||
}
|
||||
|
||||
pub fn getModulus(self: Self) i32 {
|
||||
return self.modulus;
|
||||
}
|
||||
|
||||
// Validation helper
|
||||
fn validateOp(self: Self, rhs: Self) !void {
|
||||
if (self.modulus != rhs.modulus) {
|
||||
return error.ModulusMismatch;
|
||||
}
|
||||
}
|
||||
|
||||
// Addition with another ModularInteger
|
||||
pub fn add(self: Self, rhs: Self) !Self {
|
||||
try self.validateOp(rhs);
|
||||
return Self.init(self.value + rhs.value, self.modulus);
|
||||
}
|
||||
|
||||
// Addition with integer
|
||||
pub fn addInt(self: Self, rhs: i32) Self {
|
||||
return Self.init(self.value + rhs, self.modulus);
|
||||
}
|
||||
|
||||
// Multiplication with another ModularInteger
|
||||
pub fn mul(self: Self, rhs: Self) !Self {
|
||||
try self.validateOp(rhs);
|
||||
return Self.init(self.value * rhs.value, self.modulus);
|
||||
}
|
||||
|
||||
// Format for printing
|
||||
pub fn format(
|
||||
self: Self,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
writer: anytype,
|
||||
) !void {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
try writer.print("ModularInteger({}, {})", .{ self.value, self.modulus });
|
||||
}
|
||||
};
|
||||
|
||||
// Power function for ModularInteger
|
||||
fn pow(comptime T: type, base: T, power: i32) T {
|
||||
if (power < 0) {
|
||||
@panic("Power must not be negative.");
|
||||
}
|
||||
|
||||
var result = T.init(1, base.getModulus());
|
||||
var p = power;
|
||||
while (p > 0) : (p -= 1) {
|
||||
result = result.mul(base) catch unreachable; // Same modulus, won't error
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Operator overloading using + syntax (though Zig doesn't have true operator overloading)
|
||||
// We use methods instead, but you could create wrapper functions if desired
|
||||
|
||||
pub fn main() !void {
|
||||
const input = ModularInteger.init(10, 13);
|
||||
const output = f(ModularInteger, input);
|
||||
|
||||
print("f({}) = {}\n", .{ input, output });
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue