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

scalaprops.F2Polynomial.scala Maven / Gradle / Ivy

package scalaprops

import java.math.BigInteger
import scala.annotation.tailrec

/** Polynomial over the field of two elements. F2[t]
  *
  * This class is immutable.
  *
  * Caution: This class is not efficient for large polynomial.
  *
  * @author M. Saito
  */
object F2Polynomial {
  /** Polynomial X1 + 0. */
  private[scalaprops] val X = new F2Polynomial("10")

  /**
    * If zero, this method returns -1, otherwise, returns the degree of
    * polynomial.
    *
    * @param pol
    * polynomial
    * @return degree of polynomial pol
    */
  private def degree(pol: BigInteger): Int = {
    if (pol == BigInteger.ZERO) {
      -1
    } else {
      pol.bitLength - 1
    }
  }

  /** Multiplication of BigIntegers which represents coefficient of polynomials.
    *
    * @param x
    * polynomial
    * @param y
    * polynomial
    * @return the result of multiplication
    */
  private def mul(x: BigInteger, y: BigInteger): BigInteger = {
    @tailrec def loop(z: BigInteger, v: BigInteger, w: BigInteger): BigInteger = {
      if(w != BigInteger.ZERO) {
        val z0 = if (w.and(BigInteger.ONE).testBit(0)) {
          z.xor(v)
        } else z
        loop(z0, v.shiftLeft(1), w.shiftRight(1))
      } else z
    }
    loop(BigInteger.ZERO, x, y)
  }

  /**
    * Calculate residue of polynomial y divided by that polynomial. Using means
    * return y % that if y and that were int.
    *
    * @param y dividee
    * @param that divider
    * @return residue
    */
  private def mod(y: BigInteger, that: BigInteger): BigInteger = {
    val deg = degree(that)
    val diff = degree(y) - deg
    if (diff < 0) {
      y
    } else if (diff == 0) {
      y.xor(that)
    } else {
      var z: BigInteger = y
      var x: BigInteger = that.shiftLeft(diff)
      z = z.xor(x)
      var zdeg: Int = z.bitLength - 1
      while (zdeg >= deg) {
        x = x.shiftRight(x.bitLength - 1 - zdeg)
        z = z.xor(x)
        zdeg = z.bitLength - 1
      }
      z
    }
  }

  /** returns xpow % mod.
    *
    * @param x polynomial
    * @param power exponent
    * @param mod polynomial
    * @return polynomial whose degree is less than mod polynomial
    */
  private def powerMod(x: BigInteger, power: BigInteger, mod: BigInteger): BigInteger = {
    var z: BigInteger = BigInteger.ONE
    var s: BigInteger = x
    var pow: BigInteger = power
    while (!(pow == BigInteger.ZERO)) {
      if (pow.and(BigInteger.ONE).testBit(0)) {
        z = mul(z, s)
        z = this.mod(z, mod)
      }
      s = mul(s, s)
      s = this.mod(s, mod)
      pow = pow.shiftRight(1)
    }
    z
  }
}

/** @param pol internal representation of polynomial. */
final class F2Polynomial private(private val pol: BigInteger) {

  /** constructor from string with radix.
    *
    * @param value
    * a string consists of numbers of radix
    * @param radix
    * radix of the number of val
    */
  def this(value: String, radix: Int) {
    this(new BigInteger(value, radix))
  }

  /** constructor from string of 0 and 1.
    *
    * @param value
    * a string consists of 0 and 1
    */
  def this(value: String) {
    this(new BigInteger(value, 2))
  }

  /** If zero, this method returns -1, otherwise, returns the degree of polynomial.
    *
    * @return degree of this polynomial
    */
  def degree: Int =
    F2Polynomial.degree(pol)

  /** Addition over F2[t].
    *
    * @param that Polynomial
    * @return result of addition
    */
  def add(that: F2Polynomial): F2Polynomial =
    new F2Polynomial(this.pol.xor(that.pol))

  /** Multiplication over F2[t].
    *
    * @param that Polynomial
    * @return result of multiplication
    */
  def mul(that: F2Polynomial): F2Polynomial =
    if (this.degree >= that.degree) {
      new F2Polynomial(F2Polynomial.mul(this.pol, that.pol))
    } else {
      new F2Polynomial(F2Polynomial.mul(that.pol, this.pol))
    }

  /** return coefficient of specified term, returned value is zero or one.
    *
    * @param index degree of term
    * @return coefficient of specified term
    */
  def getCoefficient(index: Int): Int =
    if (pol.testBit(index)) {
      1
    } else {
      0
    }

  /**
    * Calculate residue of this polynomial divided by that polynomial. Using
    * means return this % that if this and that were int.
    *
    * @param that divider
    * @return residue
    */
  def mod(that: F2Polynomial): F2Polynomial =
    new F2Polynomial(F2Polynomial.mod(this.pol, that.pol))

  /** power of this polynomial, thispow.
    *
    * @param pow exponent
    * @return thispow
    */
  def power(pow: BigInteger): F2Polynomial =
    new F2Polynomial(power(this.pol, pow))

  /** power of polynomial x, xpow.
    *
    * @param x polynomial
    * @param power exponent
    * @return the result of power
    */
  private def power(x: BigInteger, power: BigInteger): BigInteger = {
    var z: BigInteger = BigInteger.ONE
    var v: BigInteger = x
    var pow: BigInteger = power
    while (!(pow == BigInteger.ZERO)) {
      if (pow.and(BigInteger.ONE).testBit(0)) {
        z = F2Polynomial.mul(z, v)
      }
      v = F2Polynomial.mul(v, v)
      pow = pow.shiftRight(1)
    }
    z
  }

  /** returns thispow % mod.
    *
    * @param pow exponent
    * @param mod polynomial
    * @return polynomial whose degree is less than mod polynomial
    */
  def powerMod(pow: BigInteger, mod: F2Polynomial): F2Polynomial = {
    new F2Polynomial(F2Polynomial.powerMod(this.pol, pow, mod.pol))
  }

  /** return binary format representation of polynomial.
    *
    * @return binary format string
    */
  override def toString: String =
    toString(2)

  /** return base format representation of polynomial.
    *
    * @param base base of format
    * @return base format string
    */
  def toString(base: Int): String =
    pol.toString(base)

  override def equals(obj: Any): Boolean = {
    obj match {
      case that: F2Polynomial =>
        this.pol == that.pol
      case _ =>
        false
    }
  }

  override def hashCode: Int =
    pol.hashCode
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy