95 lines
2.4 KiB
Zig
95 lines
2.4 KiB
Zig
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 });
|
|
}
|