Hi Nicolas,
We don't have something that does this in Spire already (yet). There
are two basic ways I can think of to do this.
The first is the simplest: we would store the modulus as a field in
the number. Then during operations like addition or multiplication, we
would check to ensure that the operands have the same modulus. This
could look something like this:
case class Mod(residue: Long, modulus: Long) { lhs =>
def +(rhs: Mod): Mod = {
require(lhs.modulus == rhs.modulus)
val r = lhs.residue + rhs.residue
if (r >= 0) Mod(r, modulus) else Mod(r + modulus, modulus)
}
// and so on for multiplication, etc.
}
This would work pretty well, and I've considered adding it to
Spire. But what I'd *really* like is for the modulus to be checked at
compile time. You could imagine something like this:
case class Mod[N <: Nat](residue: Long) {
def modulus: N = ???
def +(rhs: Mod[N]): Mod[N] = {
val r = lhs.residue + rhs.residue
if (r >= 0) Mod[N](r) else Mod[N](r + modulus)
}
// and so on...
}
Often in these situations I know the base I am working against (or
it's a fixed parameter). In these cases it would be really nice to
ensure that Mod[3](x) + Mod[5](y) fails at compile-time. Or more
generally, if you have Mod[M](x) + Mod[N](y) then you have to prove
(at compile-time) that M and N are the same literal value.
I've been waiting on SIP-23 [1] to work on this, since without that I
think the syntax and machinery will be a bit too painful to use in
Spire. But I'm definitely open to the first variant (especially since
in some cases it will be difficult or impossible to know what the base
will be at compile-time).
-- Erik
[1]
http://docs.scala-lang.org/sips/pending/42.type.html