Task: Modular arithmetic





Java: public class ModularArithmetic {
    private interface Ring<T> {
        Ring<T> plus(Ring<T> rhs);

        Ring<T> times(Ring<T> rhs);

        int value();

        Ring<T> one();

        default Ring<T> pow(int p) {
            if (p < 0) {
                throw new IllegalArgumentException("p must be zero or greater");
            }

            int pp = p;
            Ring<T> pwr = this.one();
            while (pp-- > 0) {
                pwr = pwr.times(this);
            }
            return pwr;
        }
    }

    private static class ModInt implements Ring<ModInt> {
        private int value;
        private int modulo;

        private ModInt(int value, int modulo) {
            this.value = value;
            this.modulo = modulo;
        }

        @Override
        public Ring<ModInt> plus(Ring<ModInt> other) {
            if (!(other instanceof ModInt)) {
                throw new IllegalArgumentException("Cannot add an unknown ring.");
            }
            ModInt rhs = (ModInt) other;
            if (modulo != rhs.modulo) {
                throw new IllegalArgumentException("Cannot add rings with different modulus");
            }
            return new ModInt((value + rhs.value) % modulo, modulo);
        }

        @Override
        public Ring<ModInt> times(Ring<ModInt> other) {
            if (!(other instanceof ModInt)) {
                throw new IllegalArgumentException("Cannot multiple an unknown ring.");
            }
            ModInt rhs = (ModInt) other;
            if (modulo != rhs.modulo) {
                throw new IllegalArgumentException("Cannot multiply rings with different modulus");
            }
            return new ModInt((value * rhs.value) % modulo, modulo);
        }

        @Override
        public int value() {
            return value;
        }

        @Override
        public Ring<ModInt> one() {
            return new ModInt(1, modulo);
        }

        @Override
        public String toString() {
            return String.format("ModInt(%d, %d)", value, modulo);
        }
    }

    private static <T> Ring<T> f(Ring<T> x) {
        return x.pow(100).plus(x).plus(x.one());
    }

    public static void main(String[] args) {
        ModInt x = new ModInt(10, 13);
        Ring<ModInt> y = f(x);
        System.out.print("x ^ 100 + x + 1 for x = ModInt(10, 13) is ");
        System.out.println(y);
        System.out.flush();
    }
}






Fortran: module modular_arithmetic
  implicit none

  type :: modular
     integer :: val
     integer :: modulus
  end type modular

  interface operator(+)
     module procedure modular_modular_add
     module procedure modular_integer_add
  end interface operator(+)

  interface operator(**)
     module procedure modular_integer_pow
  end interface operator(**)

contains

  function modular_modular_add (a, b) result (c)
    type(modular), intent(in) :: a
    type(modular), intent(in) :: b
    type(modular) :: c

    if (a%modulus /= b%modulus) error stop
    c%val = modulo (a%val + b%val, a%modulus)
    c%modulus = a%modulus
  end function modular_modular_add

  function modular_integer_add (a, i) result (c)
    type(modular), intent(in) :: a
    integer, intent(in) :: i
    type(modular) :: c

    c%val = modulo (a%val + i, a%modulus)
    c%modulus = a%modulus
  end function modular_integer_add

  function modular_integer_pow (a, i) result (c)
    type(modular), intent(in) :: a
    integer, intent(in) :: i
    type(modular) :: c

    
    
    
    

    integer :: modulus
    integer :: base
    integer :: exponent

    modulus = a%modulus
    exponent = i

    if (modulus < 1) error stop
    if (exponent < 0) error stop

    c%modulus = modulus
    if (modulus == 1) then
       c%val = 0
    else
       c%val = 1
       base = modulo (a%val, modulus)
       do while (exponent > 0)
          if (modulo (exponent, 2) /= 0) then
             c%val = modulo (c%val * base, modulus)
          end if
          exponent = exponent / 2
          base = modulo (base * base, modulus)
       end do
    end if
  end function modular_integer_pow

end module modular_arithmetic




#define f(x) ((x)**100 + (x) + 1)

program modular_arithmetic_task
  use, intrinsic :: iso_fortran_env
  use, non_intrinsic :: modular_arithmetic
  implicit none

  type(modular) :: x, y

  x = modular(10, 13)
  y = f(x)

  write (*, '("    modulus 13:  ", I0)') y%val
  write (*, '("floating point:  ", E55.50)') f(10.0_real64)

end program modular_arithmetic_task