package scala.math
object Numeric {
trait ExtraImplicits {
implicit def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#Ops = new num.Ops(x)
}
object Implicits extends ExtraImplicits { }
trait BigIntIsIntegral extends Integral[BigInt] {
def plus(x: BigInt, y: BigInt): BigInt = x + y
def minus(x: BigInt, y: BigInt): BigInt = x - y
def times(x: BigInt, y: BigInt): BigInt = x * y
def quot(x: BigInt, y: BigInt): BigInt = x / y
def rem(x: BigInt, y: BigInt): BigInt = x % y
def negate(x: BigInt): BigInt = -x
def fromInt(x: Int): BigInt = BigInt(x)
def toInt(x: BigInt): Int = x.intValue
def toLong(x: BigInt): Long = x.longValue
def toFloat(x: BigInt): Float = x.longValue.toFloat
def toDouble(x: BigInt): Double = x.longValue.toDouble
}
implicit object BigIntIsIntegral extends BigIntIsIntegral with Ordering.BigIntOrdering
trait IntIsIntegral extends Integral[Int] {
def plus(x: Int, y: Int): Int = x + y
def minus(x: Int, y: Int): Int = x - y
def times(x: Int, y: Int): Int = x * y
def quot(x: Int, y: Int): Int = x / y
def rem(x: Int, y: Int): Int = x % y
def negate(x: Int): Int = -x
def fromInt(x: Int): Int = x
def toInt(x: Int): Int = x
def toLong(x: Int): Long = x
def toFloat(x: Int): Float = x
def toDouble(x: Int): Double = x
}
implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering
trait ShortIsIntegral extends Integral[Short] {
def plus(x: Short, y: Short): Short = (x + y).toShort
def minus(x: Short, y: Short): Short = (x - y).toShort
def times(x: Short, y: Short): Short = (x * y).toShort
def quot(x: Short, y: Short): Short = (x / y).toShort
def rem(x: Short, y: Short): Short = (x % y).toShort
def negate(x: Short): Short = (-x).toShort
def fromInt(x: Int): Short = x.toShort
def toInt(x: Short): Int = x.toInt
def toLong(x: Short): Long = x.toLong
def toFloat(x: Short): Float = x.toFloat
def toDouble(x: Short): Double = x.toDouble
}
implicit object ShortIsIntegral extends ShortIsIntegral with Ordering.ShortOrdering
trait ByteIsIntegral extends Integral[Byte] {
def plus(x: Byte, y: Byte): Byte = (x + y).toByte
def minus(x: Byte, y: Byte): Byte = (x - y).toByte
def times(x: Byte, y: Byte): Byte = (x * y).toByte
def quot(x: Byte, y: Byte): Byte = (x / y).toByte
def rem(x: Byte, y: Byte): Byte = (x % y).toByte
def negate(x: Byte): Byte = (-x).toByte
def fromInt(x: Int): Byte = x.toByte
def toInt(x: Byte): Int = x.toInt
def toLong(x: Byte): Long = x.toLong
def toFloat(x: Byte): Float = x.toFloat
def toDouble(x: Byte): Double = x.toDouble
}
implicit object ByteIsIntegral extends ByteIsIntegral with Ordering.ByteOrdering
trait CharIsIntegral extends Integral[Char] {
def plus(x: Char, y: Char): Char = (x + y).toChar
def minus(x: Char, y: Char): Char = (x - y).toChar
def times(x: Char, y: Char): Char = (x * y).toChar
def quot(x: Char, y: Char): Char = (x / y).toChar
def rem(x: Char, y: Char): Char = (x % y).toChar
def negate(x: Char): Char = (-x).toChar
def fromInt(x: Int): Char = x.toChar
def toInt(x: Char): Int = x.toInt
def toLong(x: Char): Long = x.toLong
def toFloat(x: Char): Float = x.toFloat
def toDouble(x: Char): Double = x.toDouble
}
implicit object CharIsIntegral extends CharIsIntegral with Ordering.CharOrdering
trait LongIsIntegral extends Integral[Long] {
def plus(x: Long, y: Long): Long = x + y
def minus(x: Long, y: Long): Long = x - y
def times(x: Long, y: Long): Long = x * y
def quot(x: Long, y: Long): Long = x / y
def rem(x: Long, y: Long): Long = x % y
def negate(x: Long): Long = -x
def fromInt(x: Int): Long = x
def toInt(x: Long): Int = x.toInt
def toLong(x: Long): Long = x
def toFloat(x: Long): Float = x
def toDouble(x: Long): Double = x
}
implicit object LongIsIntegral extends LongIsIntegral with Ordering.LongOrdering
trait FloatIsConflicted extends Numeric[Float] {
def plus(x: Float, y: Float): Float = x + y
def minus(x: Float, y: Float): Float = x - y
def times(x: Float, y: Float): Float = x * y
def negate(x: Float): Float = -x
def fromInt(x: Int): Float = x
def toInt(x: Float): Int = x.toInt
def toLong(x: Float): Long = x.toLong
def toFloat(x: Float): Float = x
def toDouble(x: Float): Double = x
}
trait FloatIsFractional extends FloatIsConflicted with Fractional[Float] {
def div(x: Float, y: Float): Float = x / y
}
trait FloatAsIfIntegral extends FloatIsConflicted with Integral[Float] {
def quot(x: Float, y: Float): Float = (BigDecimal(x) / BigDecimal(y)).floatValue
def rem(x: Float, y: Float): Float = (BigDecimal(x) remainder BigDecimal(y)).floatValue
}
implicit object FloatIsFractional extends FloatIsFractional with Ordering.FloatOrdering
object FloatAsIfIntegral extends FloatAsIfIntegral with Ordering.FloatOrdering {
}
trait DoubleIsConflicted extends Numeric[Double] {
def plus(x: Double, y: Double): Double = x + y
def minus(x: Double, y: Double): Double = x - y
def times(x: Double, y: Double): Double = x * y
def negate(x: Double): Double = -x
def fromInt(x: Int): Double = x
def toInt(x: Double): Int = x.toInt
def toLong(x: Double): Long = x.toLong
def toFloat(x: Double): Float = x.toFloat
def toDouble(x: Double): Double = x
}
trait DoubleIsFractional extends DoubleIsConflicted with Fractional[Double] {
def div(x: Double, y: Double): Double = x / y
}
trait DoubleAsIfIntegral extends DoubleIsConflicted with Integral[Double] {
def quot(x: Double, y: Double): Double = (BigDecimal(x) / BigDecimal(y)).doubleValue
def rem(x: Double, y: Double): Double = (BigDecimal(x) remainder BigDecimal(y)).doubleValue
}
trait BigDecimalIsConflicted extends Numeric[BigDecimal] {
def plus(x: BigDecimal, y: BigDecimal): BigDecimal = x + y
def minus(x: BigDecimal, y: BigDecimal): BigDecimal = x - y
def times(x: BigDecimal, y: BigDecimal): BigDecimal = x * y
def negate(x: BigDecimal): BigDecimal = -x
def fromInt(x: Int): BigDecimal = BigDecimal(x)
def toInt(x: BigDecimal): Int = x.intValue
def toLong(x: BigDecimal): Long = x.longValue
def toFloat(x: BigDecimal): Float = x.floatValue
def toDouble(x: BigDecimal): Double = x.doubleValue
}
trait BigDecimalIsFractional extends BigDecimalIsConflicted with Fractional[BigDecimal] {
def div(x: BigDecimal, y: BigDecimal): BigDecimal = x / y
}
trait BigDecimalAsIfIntegral extends BigDecimalIsConflicted with Integral[BigDecimal] {
def quot(x: BigDecimal, y: BigDecimal): BigDecimal = x / y
def rem(x: BigDecimal, y: BigDecimal): BigDecimal = x remainder y
}
implicit object BigDecimalIsFractional extends BigDecimalIsFractional with Ordering.BigDecimalOrdering
object BigDecimalAsIfIntegral extends BigDecimalAsIfIntegral with Ordering.BigDecimalOrdering
implicit object DoubleIsFractional extends DoubleIsFractional with Ordering.DoubleOrdering
object DoubleAsIfIntegral extends DoubleAsIfIntegral with Ordering.DoubleOrdering
}
trait Numeric[T] extends Ordering[T] {
def plus(x: T, y: T): T
def minus(x: T, y: T): T
def times(x: T, y: T): T
def negate(x: T): T
def fromInt(x: Int): T
def toInt(x: T): Int
def toLong(x: T): Long
def toFloat(x: T): Float
def toDouble(x: T): Double
def zero = fromInt(0)
def one = fromInt(1)
def abs(x: T): T = if (lt(x, zero)) negate(x) else x
def signum(x: T): Int =
if (lt(x, zero)) -1
else if (gt(x, zero)) 1
else 0
class Ops(lhs: T) {
def +(rhs: T) = plus(lhs, rhs)
def -(rhs: T) = minus(lhs, rhs)
def *(rhs: T) = times(lhs, rhs)
def unary_-() = negate(lhs)
def abs(): T = Numeric.this.abs(lhs)
def signum(): Int = Numeric.this.signum(lhs)
def toInt(): Int = Numeric.this.toInt(lhs)
def toLong(): Long = Numeric.this.toLong(lhs)
def toFloat(): Float = Numeric.this.toFloat(lhs)
def toDouble(): Double = Numeric.this.toDouble(lhs)
}
implicit def mkNumericOps(lhs: T): Ops = new Ops(lhs)
}