All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spire.example.finitefield.scala Maven / Gradle / Ivy

The newest version!
package spire.example

import shapeless.{ Field => _, _ }
import spire.algebra._
import spire.math._


trait Div[A <: Nat, B <: Nat] {
  type Out <: Nat
}

trait DivAux[A <: Nat, B <: Nat, C <: Nat]

object Div {
  implicit def div[A <: Nat, B <: Nat, C <: Nat]
    (implicit div: DivAux[A, B, C]) = new Div[A, B] {
      type Out = C
    }
}

object DivAux {
  import Nat._
  import LT._

  // (a + 1) / b => (a + 1 - b + b) / b => (a + 1 -b ) / b + 1

  implicit def div1[A <: Nat] = new DivAux[_0, A, _0] {}

  implicit def div2[A <: Nat, B <: Nat](implicit e: A < B) =
    new DivAux[A, B, _0] {}

  implicit def div3[A <: Nat, B <: Nat, C <: Nat, D <: Nat]
    (implicit diff: DiffAux[Succ[A], B, C], div: DivAux[C, B, D]) =
      new DivAux[Succ[A], B, Succ[D]] {}
}


/** Typeclass witnessing that `B` divides `A`. */
trait Divisible[A <: Nat, B <: Nat]

object Divisible {
  implicit def divisible[A <: Nat, B <: Nat, C <: Nat]
    (implicit div: DivAux[A, B, C], prod: ProdAux[C, B, A]) =
      new Divisible[A, B] {}
}


/** Does something like this already exist somewhere? */
trait Not[A]

object Not {
  implicit def notAmbig[A](implicit a: A) = new Not[A] {}
  implicit def not[A] = new Not[A] {}
}


/**
 * Typeclass witnessing that `N` is prime.
 */
trait IsPrime[N <: Nat]

/**
 * Typeclass witnessing that `A` has no divisors between _2
 * and `B` inclusive. A number `A` is prime if an
 * `IsPrimeAux[A, A / _2]` exists.
 */
trait IsPrimeAux[A <: Nat, B <: Nat]

object IsPrime {
  import Nat._

  implicit def prime[A <: Nat, B <: Nat]
    (implicit div: DivAux[A, _2, B], p: IsPrimeAux[A, B]) = new IsPrime[A] {}

  implicit def apply[A <: Nat: ToInt: IsPrime] = Nat.toInt[A]
}

object IsPrimeAux {
  import Nat._
  import LT._

  implicit def prime1[A <: Nat](implicit lt: _1 < A) = new IsPrimeAux[A, _1] {}

  implicit def primeN[A <: Nat, B <: Nat]
    (implicit p: IsPrimeAux[A, B], e: Not[Divisible[A, Succ[B]]]) =
      new IsPrimeAux[A, Succ[B]] {}
}


/**
 * A simple class for representing integers mod `N`.
 */
final class Z[N <: Nat] private (val n: Int) /*extends AnyVal*/ {

  // Remove if extending AnyVal.
  override def equals(obj: Any) = obj match {
    case that: Z[_] => that.n == n
    case _ => false
  }

  override def toString = "Z(%d)" format n
}


object Z {

  def unapply(n: Z[_]) = Some(n.n)

  def apply[A <: Nat](n: Int)(implicit toInt: ToInt[A]): Z[A] = {
    val k = (if (n < 0) -n else n) % toInt()
    new Z[A](k)
  }

  implicit def eq[N <: Nat] = new Eq[Z[N]] {
    def eqv(a: Z[N], b: Z[N]) = a.n == b.n
  }

  // TODO: Move field to lower priority for Rings.

   implicit def ring[N <: Nat](implicit ord: ToInt[N]): Ring[Z[N]] = new FiniteRing[N] {
    val toInt: ToInt[N] = ord
  }

  implicit def field[N <: Nat]
    (implicit ord: ToInt[N], p: IsPrime[N]): Field[Z[N]] = new FiniteField[N] {
      val toInt: ToInt[N] = implicitly
    }
}

trait FiniteRing[N <: Nat] extends Ring[Z[N]] {
  implicit def toInt: ToInt[N]

  def order: Int = toInt()

  lazy val zero = Z[N](0)
  lazy val one = Z[N](1)
  def negate(a: Z[N]) = Z[N](order - a.n)
  def plus(a: Z[N], b: Z[N]) = Z[N](a.n + b.n)
  def times(a: Z[N], b: Z[N]) = Z[N](a.n * b.n)
}

trait FiniteField[N <: Nat] extends FiniteRing[N] with Field[Z[N]] {
  import spire.implicits._

  def quot(a: Z[N], b: Z[N]) = Z[N](a.n / b.n)
  def mod(a: Z[N], b: Z[N]) = Z[N](a.n % b.n)
  def gcd(a: Z[N], b: Z[N]) = Z[N](EuclideanRing[Int].gcd(a.n, b.n))

  def ceil(a: Z[N]) = a
  def floor(a: Z[N]) = a
  def round(a: Z[N]) = a

  override def reciprocal(a: Z[N]): Z[N] = if (a === zero) {
    throw new ArithmeticException("Divide by zero.")
  } else (1 until order) map (Z[N](_)) find { b =>
    times(a, b) === one
  } getOrElse {
    // If this is had through Z.field, then this won't happen.
    throw new ArithmeticException("Order isn't prime.")
  }

  def div(a: Z[N], b: Z[N]) = times(a, reciprocal(b))
  def isWhole(a: Z[N]) = true
}


/**
 * An example of type safe finite fields.
 */
object FiniteFieldExample extends App {
  import spire.implicits._
  import Nat._

  // Some examples of primes. Primality testing is currently rather slow.

  implicitly[IsPrime[_2]]
  implicitly[IsPrime[_3]]
  implicitly[IsPrime[_5]]
  implicitly[IsPrime[_13]]
  implicitly[Not[IsPrime[_9]]]
  implicitly[Not[IsPrime[_1]]]


  // If the order is not prime, then we only have a Ring available.

  implicitly[Ring[Z[_9]]]
  implicitly[Not[Field[Z[_9]]]]

  val a = Z[_9](3)
  val b = Z[_9](5)

  assert((a + b) === Z[_9](8))
  assert((a * b) === Z[_9](6))
  // assert((z / b) == Z[_9](6))
  // ^ Compile time error, because _9 is not prime.


  // If the order is prime, then we have a Field and can use division.

  implicitly[Field[Z[_11]]]
  implicitly[Field[Z[_3]]]

  val c = Z[_11](8)
  val d = Z[_11](9)
  
  assert((c + d) === Z[_11](6))
  assert((c * d) === Z[_11](6))
  assert((c / d) === Z[_11](7))

  val e = Z[_3](1)
  val f = Z[_3](2)
  
  assert((e + f) === Z[_3](0))
  assert((e * f) === Z[_3](2))
  assert((e / f) === Z[_3](2))
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy