RosettaCodeData/Task/Modular-arithmetic/Zig/modular-arithmetic.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 });
}