128 lines
3.4 KiB
D
128 lines
3.4 KiB
D
import std.stdio;
|
|
|
|
version(unittest) {
|
|
void assertEquals(T)(T actual, T expected) {
|
|
import core.exception;
|
|
import std.conv;
|
|
if (actual != expected) {
|
|
throw new AssertError("Actual [" ~ to!string(actual) ~ "]; Expected [" ~ to!string(expected) ~ "]");
|
|
}
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
auto input = ModularInteger(10,13);
|
|
auto output = f(input);
|
|
writeln("f(", input, ") = ", output);
|
|
}
|
|
|
|
V f(V)(const V x) {
|
|
return x^^100 + x + 1;
|
|
}
|
|
|
|
/// Integer tests on f
|
|
unittest {
|
|
assertEquals(f(1), 3);
|
|
assertEquals(f(0), 1);
|
|
}
|
|
|
|
/// Floating tests on f
|
|
unittest {
|
|
assertEquals(f(1.0), 3.0);
|
|
assertEquals(f(0.0), 1.0);
|
|
}
|
|
|
|
struct ModularInteger {
|
|
private:
|
|
int value;
|
|
int modulus;
|
|
|
|
public:
|
|
this(int value, int modulus) {
|
|
this.modulus = modulus;
|
|
this.value = value % modulus;
|
|
}
|
|
|
|
ModularInteger opBinary(string op : "+")(ModularInteger rhs) const in {
|
|
assert(this.modulus == rhs.modulus);
|
|
} body {
|
|
return ModularInteger((this.value + rhs.value) % this.modulus, this.modulus);
|
|
}
|
|
|
|
ModularInteger opBinary(string op : "+")(int rhs) const {
|
|
return ModularInteger((this.value + rhs) % this.modulus, this.modulus);
|
|
}
|
|
|
|
ModularInteger opBinary(string op : "*")(ModularInteger rhs) const in {
|
|
assert(this.modulus == rhs.modulus);
|
|
assert(this.value < this.modulus);
|
|
assert(rhs.value < this.modulus);
|
|
} body {
|
|
return ModularInteger((this.value * rhs.value) % this.modulus, this.modulus);
|
|
}
|
|
|
|
ModularInteger opBinary(string op : "^^")(int pow) const in {
|
|
assert(pow >= 0);
|
|
} body {
|
|
auto base = ModularInteger(1, this.modulus);
|
|
while (pow-- > 0) {
|
|
base = base * this;
|
|
}
|
|
return base;
|
|
}
|
|
|
|
string toString() {
|
|
import std.format;
|
|
return format("ModularInteger(%s, %s)", value, modulus);
|
|
}
|
|
}
|
|
|
|
/// Addition with same type of int
|
|
unittest {
|
|
auto a = ModularInteger(2,5);
|
|
auto b = ModularInteger(3,5);
|
|
assertEquals(a+b, ModularInteger(0,5));
|
|
}
|
|
|
|
/// Addition with differnt int types
|
|
unittest {
|
|
auto a = ModularInteger(2,5);
|
|
assertEquals(a+0, a);
|
|
assertEquals(a+1, ModularInteger(3,5));
|
|
}
|
|
|
|
/// Muliplication
|
|
unittest {
|
|
auto a = ModularInteger(2,5);
|
|
auto b = ModularInteger(3,5);
|
|
assertEquals(a*b, ModularInteger(1,5));
|
|
}
|
|
|
|
/// Power
|
|
unittest {
|
|
const a = ModularInteger(3,13);
|
|
assertEquals(a^^2, ModularInteger(9,13));
|
|
assertEquals(a^^3, ModularInteger(1,13));
|
|
|
|
const b = ModularInteger(10,13);
|
|
assertEquals(b^^1, ModularInteger(10,13));
|
|
assertEquals(b^^2, ModularInteger(9,13));
|
|
assertEquals(b^^3, ModularInteger(12,13));
|
|
assertEquals(b^^4, ModularInteger(3,13));
|
|
assertEquals(b^^5, ModularInteger(4,13));
|
|
assertEquals(b^^6, ModularInteger(1,13));
|
|
assertEquals(b^^7, ModularInteger(10,13));
|
|
assertEquals(b^^8, ModularInteger(9,13));
|
|
assertEquals(b^^10, ModularInteger(3,13));
|
|
assertEquals(b^^20, ModularInteger(9,13));
|
|
assertEquals(b^^30, ModularInteger(1,13));
|
|
assertEquals(b^^50, ModularInteger(9,13));
|
|
assertEquals(b^^75, ModularInteger(12,13));
|
|
assertEquals(b^^90, ModularInteger(1,13));
|
|
assertEquals(b^^95, ModularInteger(4,13));
|
|
assertEquals(b^^97, ModularInteger(10,13));
|
|
assertEquals(b^^98, ModularInteger(9,13));
|
|
assertEquals(b^^99, ModularInteger(12,13));
|
|
assertEquals(b^^100, ModularInteger(3,13));
|
|
}
|