```On Oct 10, 2008, at 11:13 AM, Matthew Moss wrote:
> ## Modular Arithmetic (#179)
>
> [1]: http://mathworld.wolfram.com/ModularArithmetic.html
> [2]: http://en.wikipedia.org/wiki/Modular_arithmetic
> [3]: http://www.math.harvard.edu/~sarah/magic/topics/division

I agreed with Matthew's design choices regarding the type of "Integer
{op} Modulo" being Integer.  I'd intended to add some tests to show
that Modulo.new(0)-10 would give Modulo.new(16) and generally give an
integer value in the 0...modulus domain.  (Of course, if I were less
busy, I'd have taken a shot at division, too.)

-Rob

==> modulo.rb <==
class Modulo
include Comparable

# Returns a new object that behaves according to the rules of
# Modular Arithmetic, but otherwise responds like an Integer from
# the set of integers between 0 and modulus-1.
def initialize(value=0, modulus=26)
@modulus = modulus
@value = value % @modulus
end

def to_int
@value
end

def to_i
self.to_int
end

def <=>(other)
case other
when Modulo
@value <=> other.to_int
when Integer
@value <=> other
else
raise ArgumentError, "I don't know how to compare a
#{other.class.name}"
end
end

def coerce(other)
case other
when Integer
return other, self.to_int
else
super
end
end

[ :+, :-, :* ].each do |method|
define_method method do |other|
self.class.new(@value.__send__(method, other.to_int), @modulus)
end
end

end
__END__

==> test_modulo.rb <==
require 'test/unit'
require 'modulo'

class TestModulo < Test::Unit::TestCase
def test_modulo_equality
a = Modulo.new(23)
b = Modulo.new(23)
c = Modulo.new(179)
assert_equal(a, b)
assert_equal(a, c)
end

a = Modulo.new(15)
b = Modulo.new(0)
assert_equal(a, a + b)
end

a = Modulo.new(15)
b = Modulo.new(19)
c = Modulo.new(8)
assert_equal(c, a + b)
end

a = Modulo.new(15)
c = Modulo.new(10)
assert_equal(c, a + 21)
end

def test_sub
a = Modulo.new(15)
b = Modulo.new(19)
c = Modulo.new(22)
assert_equal(c, a - b)
end

def test_sub_int
a = Modulo.new(15)
c = Modulo.new(1)
assert_equal(c, a - 66)
end

def test_mul
a = Modulo.new(15)
b = Modulo.new(7)
c = Modulo.new(1)
assert_equal(c, a * b)
end

def test_mul_int
a = Modulo.new(15)
c = Modulo.new(9)
assert_equal(c, a * 11)
end

# from Ken Bloom
a = Modulo.new(15)
assert_equal(30, 15 + a)
end

# from Ken Bloom
def test_sub_reverse
a = Modulo.new(15)
assert_equal(-14, 1-a)
end

def test_mul_int_reverse
a = Modulo.new(15, 8)
assert_equal(77, 11 * a)
end

def test_non_default_modulo
a = Modulo.new(15, 11)
b = Modulo.new(9, 11)

assert_equal(2, a + b)
assert_equal(6, a - b)
assert_equal(3, a * b)
end

def test_compare
assert_equal(1, Modulo.new(15) <=> Modulo.new(30))
end

def test_compare_int
assert_equal(-1, Modulo.new(15) <=> 35)
end

def test_sort
x = [Modulo.new(15), Modulo.new(29), Modulo.new(-6), Modulo.new(57)]
y = [3, 5, 15, 20]
assert_equal(y, x.sort)
end

#   def test_value_range
#   end
end
__END__

Rob Biedenharn		http://agileconsultingllc.com
Rob / AgileConsultingLLC.com

```