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

spire.math.ULong.scala Maven / Gradle / Ivy

package spire.math

import scala.annotation.tailrec

import spire.algebra.{IsIntegral, Order, Rig, Signed}

object ULong extends ULongInstances {
  @inline final def apply(n: Long): ULong = new ULong(n)

  final def apply(s: String): ULong = fromBigInt(BigInt(s))

  final def fromInt(n: Int): ULong = new ULong(n & 0xffffffffL)
  final def fromLong(n: Long): ULong = new ULong(n)

  final def fromBigInt(n: BigInt): ULong =
    if (n < 0) throw new IllegalArgumentException(s"$n < 0")
    else new ULong(n.toLong)

  implicit def ulongToBigInt(n: ULong): BigInt = n.toBigInt

  @inline final val MinValue = ULong(0L)
  @inline final val MaxValue = ULong(-1L)

  @tailrec final private[math] def pow(t:Long, b:Long, e:Long): ULong = {
    if (e == 0L) new ULong(t)
    else if ((e & 1L) == 1L) pow(t * b, b * b, e >>> 1L)
    else pow(t, b * b, e >>> 1L)
  }

  @tailrec final private[math] def gcd(a:ULong, b:ULong): ULong = {
    if (b == new ULong(0L)) a else gcd(b, a % b)
  }

  private[spire] final val LimitAsDouble: Double =
    spire.math.pow(2.0, 64)

  private[spire] final val LimitAsBigInt: BigInt =
    BigInt(1) << 64
}

class ULong(val signed: Long) extends AnyVal {
  final def toByte: Byte = signed.toByte
  final def toChar: Char = signed.toChar
  final def toShort: Short = signed.toShort
  final def toInt: Int = signed.toInt
  final def toLong: Long = signed

  final def toFloat: Float = {
    if (signed < 0) (ULong.LimitAsDouble + signed.toDouble).toFloat
    else signed.toFloat
  }

  // FIXME: it would be nice to write some "real" floating-point code
  // to correctly find the nearest Double.
  final def toDouble: Double =
    toBigInt.toDouble

  final def toBigInt: BigInt =
    if (signed < 0) ULong.LimitAsBigInt + signed
    else BigInt(signed)

  // FIXME: it would be nice to avoid converting to BigInt here
  override final def toString: String =
    if (signed >= 0L) signed.toString
    else (ULong.LimitAsBigInt + signed).toString

  // TODO: replace these with `===` and `=!=`? Don't we get `==` and `!=` for free with value classes?
  final def == (that: ULong): Boolean = this.signed == that.signed
  final def != (that: ULong): Boolean = this.signed != that.signed

  final def === (that: ULong): Boolean = this.signed == that.signed
  final def =!= (that: ULong): Boolean = this.signed != that.signed

  final def <= (that: ULong): Boolean = if (this.signed >= 0L)
    this.signed <= that.signed || that.signed < 0L
  else
    that.signed >= this.signed && that.signed < 0L

  final def < (that: ULong): Boolean = if (this.signed >= 0L)
    this.signed < that.signed || that.signed < 0L
  else
    that.signed > this.signed && that.signed < 0L

  @inline final def >= (that: ULong): Boolean = that <= this
  @inline final def > (that: ULong): Boolean = that < this

  final def unary_- : ULong = ULong(-this.signed)

  final def + (that: ULong): ULong = ULong(this.signed + that.signed)
  final def - (that: ULong): ULong = ULong(this.signed - that.signed)
  final def * (that: ULong): ULong = ULong(this.signed * that.signed)

  final def / (that: ULong): ULong = {
    val n: Long = this.signed
    val d: Long = that.signed

    if (d == 0) {
      throw new java.lang.ArithmeticException("/ by zero")
    } else if (d < 0) {
      ULong(if (n >= 0 || n < d) 0 else 1)
    } else if (n >= 0) {
      ULong(n / d)
    } else {
      val half = n >>> 1
      if (half < d) {
        ULong(1L)
      } else {
        ULong(((half / d) << 1) + (((half % d) << 1) + (n & 1)) / d)
      }
    }
  }

  final def % (that: ULong): ULong = this - (this / that) * that

  final def /% (that: ULong): (ULong, ULong) = {
    val q = this / that
    (q, this - q * that)
  }

  final def unary_~ : ULong = ULong(~this.signed)

  final def << (shift: Int): ULong = ULong(signed << shift)
  final def >> (shift: Int): ULong = ULong(signed >>> shift)
  final def >>> (shift: Int): ULong = ULong(signed >>> shift)
  final def & (that: ULong): ULong = ULong(this.signed & that.signed)
  final def | (that: ULong): ULong = ULong(this.signed | that.signed)
  final def ^ (that: ULong): ULong = ULong(this.signed ^ that.signed)

  final def ** (that: ULong): ULong = ULong.pow(1L, this.signed, that.signed)

  final def gcd (that: ULong): ULong = ULong.gcd(this, that)
}

trait ULongInstances {
  implicit final val ULongAlgebra = new ULongAlgebra
  implicit final val ULongBitString = new ULongBitString
  import spire.math.NumberTag._
  implicit final val ULongTag = new UnsignedIntTag[ULong](ULong.MinValue, ULong.MaxValue)
}

private[math] trait ULongIsRig extends Rig[ULong] {
  def one: ULong = ULong(1)
  def plus(a:ULong, b:ULong): ULong = a + b
  override def pow(a:ULong, b:Int): ULong = {
    if (b < 0)
      throw new IllegalArgumentException("negative exponent: %s" format b)
    a ** ULong(b)
  }
  override def times(a:ULong, b:ULong): ULong = a * b
  def zero: ULong = ULong(0)
}

private[math] trait ULongOrder extends Order[ULong] {
  override def eqv(x:ULong, y:ULong): Boolean = x == y
  override def neqv(x:ULong, y:ULong): Boolean = x != y
  override def gt(x: ULong, y: ULong): Boolean = x > y
  override def gteqv(x: ULong, y: ULong): Boolean = x >= y
  override def lt(x: ULong, y: ULong): Boolean = x < y
  override def lteqv(x: ULong, y: ULong): Boolean = x <= y
  def compare(x: ULong, y: ULong): Int = if (x < y) -1 else if (x > y) 1 else 0
}

@SerialVersionUID(0L)
private[math] class ULongBitString extends BitString[ULong] with Serializable {
  def one: ULong = ULong(-1L)
  def zero: ULong = ULong(0L)
  def and(a: ULong, b: ULong): ULong = a & b
  def or(a: ULong, b: ULong): ULong = a | b
  def complement(a: ULong): ULong = ~a
  override def xor(a: ULong, b: ULong): ULong = a ^ b

  def signed: Boolean = false
  def width: Int = 64
  def toHexString(n: ULong): String = java.lang.Long.toHexString(n.signed)

  def bitCount(n: ULong): Int = java.lang.Long.bitCount(n.signed)
  def highestOneBit(n: ULong): ULong = ULong(java.lang.Long.highestOneBit(n.signed))
  def lowestOneBit(n: ULong): ULong = ULong(java.lang.Long.lowestOneBit(n.signed))
  def numberOfLeadingZeros(n: ULong): Int = java.lang.Long.numberOfLeadingZeros(n.signed)
  def numberOfTrailingZeros(n: ULong): Int = java.lang.Long.numberOfTrailingZeros(n.signed)

  def leftShift(n: ULong, i: Int): ULong = n << i
  def rightShift(n: ULong, i: Int): ULong = n >> i
  def signedRightShift(n: ULong, i: Int): ULong = n >>> i
  def rotateLeft(n: ULong, i: Int): ULong = ULong(java.lang.Long.rotateLeft(n.signed, i))
  def rotateRight(n: ULong, i: Int): ULong = ULong(java.lang.Long.rotateRight(n.signed, i))
}

private[math] trait ULongIsSigned extends Signed[ULong] {
  def signum(a: ULong): Int = java.lang.Long.signum(a.signed) & 1
  def abs(a: ULong): ULong = a
}

private[math] trait ULongIsReal extends IsIntegral[ULong] with ULongOrder with ULongIsSigned {
  def toDouble(n: ULong): Double = n.toDouble
  def toBigInt(n: ULong): BigInt = n.toBigInt
}

@SerialVersionUID(0L)
private[math] class ULongAlgebra extends ULongIsRig with ULongIsReal with Serializable




© 2015 - 2025 Weber Informatics LLC | Privacy Policy