Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inline algebra typeclass methods #1310

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions core/src/main/scala-2/spire/std/double.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* **********************************************************************\
* * Project **
* * ______ ______ __ ______ ____ **
* * / ____/ / __ / / / / __ / / __/ (c) 2011-2021 **
* * / /__ / /_/ / / / / /_/ / / /_ **
* * /___ / / ____/ / / / __ / / __/ Erik Osheim, Tom Switzer **
* * ____/ / / / / / / / | | / /__ **
* * /_____/ /_/ /_/ /_/ |_| /____/ All rights reserved. **
* * **
* * Redistribution and use permitted under the MIT license. **
* * **
* \***********************************************************************
*/

package spire
package std

import spire.algebra.{Field, IsRational, NRoot, Order, Signed, Trig, TruncatedDivisionCRing}
import spire.math.Rational
import spire.util.Opt

import java.lang.Math

trait DoubleIsField extends Field[Double] {
override def minus(a: Double, b: Double): Double = a - b
def negate(a: Double): Double = -a
def one: Double = 1.0
erikerlandson marked this conversation as resolved.
Show resolved Hide resolved
def plus(a: Double, b: Double): Double = a + b
override def pow(a: Double, b: Int): Double = Math.pow(a, b)
override def times(a: Double, b: Double): Double = a * b
def zero: Double = 0.0

override def fromInt(n: Int): Double = n

override def fromDouble(n: Double): Double = n
def div(a: Double, b: Double): Double = a / b
}

/* TODO: move to TruncatedDivision or remove
trait DoubleIsGcd extends Gcd[Double] {
def lcm(a:Double, b:Double):Double = (a / gcd(a, b)) * b

def gcd(a:Double, b:Double):Double = {
def value(bits: Long): Long = bits & 0x000FFFFFFFFFFFFFL | 0x0010000000000000L

def exp(bits: Long): Int = ((bits >> 52) & 0x7FF).toInt

// Computes the GCD of 2 fp values. Here, we are guaranteed that exp0 < exp1.
def gcd0(val0: Long, exp0: Int, val1: Long, exp1: Int): Double = {
val tz0 = numberOfTrailingZeros(val0)
val tz1 = numberOfTrailingZeros(val1)
val tzShared = spire.math.min(tz0, tz1 + exp1 - exp0)
// We trim of the power of 2s, then add back the shared portion.
val n = spire.math.gcd(val0 >>> tz0, val1 >>> tz1) << tzShared
// Number of bits to move the leading 1 to bit position 23.
val shift = numberOfLeadingZeros(n) - 11 // Number of bits to move 1 to bit 52
val exp = (exp0 - shift).toLong
// If exp is 0, then the value is actually just the mantissa * 2^−126,
// so we need to adjust the *shift* accordingly.
val shift0 = if (exp == 0) shift - 1 else shift
val mantissa = (n << shift0) & 0x000FFFFFFFFFFFFFL
// If exp < 0, then we have underflowed; not much we can do but return 0.
if (exp < 0) 0.0
else longBitsToDouble((exp << 52) | mantissa)
}

if (a == 0D) b
else if (b == 0D) a
else {
val aBits = doubleToLongBits(a)
val aVal = value(aBits)
val aExp = exp(aBits)

val bBits = doubleToLongBits(b)
val bVal = value(bBits)
val bExp = exp(bBits)

if (aExp < bExp) gcd0(aVal, aExp, bVal, bExp)
else gcd0(bVal, bExp, aVal, aExp)
}
}
}
*/
trait DoubleIsNRoot extends NRoot[Double] {
def nroot(a: Double, k: Int): Double = Math.pow(a, 1 / k.toDouble)
override def sqrt(a: Double): Double = Math.sqrt(a)
def fpow(a: Double, b: Double): Double = Math.pow(a, b)
}

trait DoubleIsTrig extends Trig[Double] {
def e: Double = Math.E
def pi: Double = Math.PI

def exp(a: Double): Double = Math.exp(a)
def expm1(a: Double): Double = Math.expm1(a)
def log(a: Double): Double = Math.log(a)
def log1p(a: Double): Double = Math.log1p(a)

def sin(a: Double): Double = Math.sin(a)
def cos(a: Double): Double = Math.cos(a)
def tan(a: Double): Double = Math.tan(a)

def asin(a: Double): Double = Math.asin(a)
def acos(a: Double): Double = Math.acos(a)
def atan(a: Double): Double = Math.atan(a)
def atan2(y: Double, x: Double): Double = Math.atan2(y, x)

def sinh(x: Double): Double = Math.sinh(x)
def cosh(x: Double): Double = Math.cosh(x)
def tanh(x: Double): Double = Math.tanh(x)

def toRadians(a: Double): Double = (a * 2 * pi) / 360
def toDegrees(a: Double): Double = (a * 360) / (2 * pi)
}

trait DoubleOrder extends Order[Double] {
override def eqv(x: Double, y: Double): Boolean = x == y
override def neqv(x: Double, y: Double): Boolean = x != y
override def gt(x: Double, y: Double): Boolean = x > y
override def gteqv(x: Double, y: Double): Boolean = x >= y
override def lt(x: Double, y: Double): Boolean = x < y
override def lteqv(x: Double, y: Double): Boolean = x <= y
override def min(x: Double, y: Double): Double = Math.min(x, y)
override def max(x: Double, y: Double): Double = Math.max(x, y)
def compare(x: Double, y: Double): Int = java.lang.Double.compare(x, y)
}

trait DoubleSigned extends Signed[Double] with DoubleOrder {
def order = this
override def signum(a: Double): Int = Math.signum(a).toInt
override def abs(a: Double): Double = if (a < 0.0) -a else a
}

trait DoubleTruncatedDivision extends TruncatedDivisionCRing[Double] with DoubleSigned {
def toBigIntOpt(a: Double): Opt[BigInt] = if (a.isWhole) Opt(BigDecimal(a).toBigInt) else Opt.empty[BigInt]
def tquot(a: Double, b: Double): Double = (a - (a % b)) / b
def tmod(a: Double, b: Double): Double = a % b
}

trait DoubleIsReal extends IsRational[Double] with DoubleTruncatedDivision {
def toDouble(x: Double): Double = x
def ceil(a: Double): Double = Math.ceil(a)
def floor(a: Double): Double = Math.floor(a)
def round(a: Double): Double = spire.math.round(a)
def isWhole(a: Double): Boolean = a % 1.0 == 0.0
def toRational(a: Double): Rational = Rational(a)
}
102 changes: 102 additions & 0 deletions core/src/main/scala-2/spire/std/float.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* **********************************************************************\
* * Project **
* * ______ ______ __ ______ ____ **
* * / ____/ / __ / / / / __ / / __/ (c) 2011-2021 **
* * / /__ / /_/ / / / / /_/ / / /_ **
* * /___ / / ____/ / / / __ / / __/ Erik Osheim, Tom Switzer **
* * ____/ / / / / / / / | | / /__ **
* * /_____/ /_/ /_/ /_/ |_| /____/ All rights reserved. **
* * **
* * Redistribution and use permitted under the MIT license. **
* * **
* \***********************************************************************
*/

package spire
package std

import spire.algebra.{Field, IsRational, NRoot, Order, Signed, Trig, TruncatedDivisionCRing}
import spire.math.Rational
import spire.util.Opt

import java.lang.Math

trait FloatIsField extends Field[Float] {
override def minus(a: Float, b: Float): Float = a - b
def negate(a: Float): Float = -a
def one: Float = 1.0f
def plus(a: Float, b: Float): Float = a + b
override def pow(a: Float, b: Int): Float = Math.pow(a, b).toFloat
override def times(a: Float, b: Float): Float = a * b
def zero: Float = 0.0f
def div(a: Float, b: Float): Float = a / b

override def fromInt(n: Int): Float = n.toFloat
override def fromDouble(n: Double): Float = n.toFloat
}

trait FloatIsNRoot extends NRoot[Float] {
def nroot(a: Float, k: Int): Float = Math.pow(a, 1 / k.toDouble).toFloat
override def sqrt(a: Float): Float = Math.sqrt(a).toFloat
def fpow(a: Float, b: Float): Float = Math.pow(a, b).toFloat
}

trait FloatIsTrig extends Trig[Float] {
def e: Float = Math.E.toFloat
def pi: Float = Math.PI.toFloat

def exp(a: Float): Float = Math.exp(a).toFloat
def expm1(a: Float): Float = Math.expm1(a).toFloat
def log(a: Float): Float = Math.log(a).toFloat
def log1p(a: Float): Float = Math.log1p(a).toFloat

def sin(a: Float): Float = Math.sin(a.toDouble).toFloat
def cos(a: Float): Float = Math.cos(a.toDouble).toFloat
def tan(a: Float): Float = Math.tan(a.toDouble).toFloat

def asin(a: Float): Float = Math.asin(a.toDouble).toFloat
def acos(a: Float): Float = Math.acos(a.toDouble).toFloat
def atan(a: Float): Float = Math.atan(a.toDouble).toFloat
def atan2(y: Float, x: Float): Float = Math.atan2(y.toDouble, x.toDouble).toFloat

def sinh(x: Float): Float = Math.sinh(x.toDouble).toFloat
def cosh(x: Float): Float = Math.cosh(x.toDouble).toFloat
def tanh(x: Float): Float = Math.tanh(x.toDouble).toFloat

def toRadians(a: Float): Float = (a * 2 * pi) / 360
def toDegrees(a: Float): Float = (a * 360) / (2 * pi)
}

trait FloatOrder extends Order[Float] {
override def eqv(x: Float, y: Float): Boolean = x == y
override def neqv(x: Float, y: Float): Boolean = x != y
override def gt(x: Float, y: Float): Boolean = x > y
override def gteqv(x: Float, y: Float): Boolean = x >= y
override def lt(x: Float, y: Float): Boolean = x < y
override def lteqv(x: Float, y: Float): Boolean = x <= y
override def min(x: Float, y: Float): Float = Math.min(x, y)
override def max(x: Float, y: Float): Float = Math.max(x, y)
def compare(x: Float, y: Float): Int = java.lang.Float.compare(x, y)
}

trait FloatSigned extends Signed[Float] with FloatOrder {
override def signum(a: Float): Int = Math.signum(a).toInt
override def abs(a: Float): Float = if (a < 0.0f) -a else a
}

trait FloatTruncatedDivision extends TruncatedDivisionCRing[Float] with FloatSigned {
def order = this
def toBigIntOpt(a: Float): Opt[BigInt] = if (a.isWhole) Opt(BigDecimal(a.toDouble).toBigInt) else Opt.empty[BigInt]
def tquot(a: Float, b: Float): Float = (a - (a % b)) / b
def tmod(a: Float, b: Float): Float = a % b
}

trait FloatIsReal extends IsRational[Float] with FloatTruncatedDivision {
def toDouble(x: Float): Double = x.toDouble
def ceil(a: Float): Float = Math.ceil(a).toFloat
def floor(a: Float): Float = Math.floor(a).toFloat
def round(a: Float): Float = spire.math.round(a)
def isWhole(a: Float): Boolean = a % 1.0 == 0.0
def toRational(a: Float): Rational = Rational(a)
}
118 changes: 118 additions & 0 deletions core/src/main/scala-2/spire/std/int.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* **********************************************************************\
* * Project **
* * ______ ______ __ ______ ____ **
* * / ____/ / __ / / / / __ / / __/ (c) 2011-2021 **
* * / /__ / /_/ / / / / /_/ / / /_ **
* * /___ / / ____/ / / / __ / / __/ Erik Osheim, Tom Switzer **
* * ____/ / / / / / / / | | / /__ **
* * /_____/ /_/ /_/ /_/ |_| /____/ All rights reserved. **
* * **
* * Redistribution and use permitted under the MIT license. **
* * **
* \***********************************************************************
*/

package spire
package std

import spire.algebra.{Eq, EuclideanRing, IsIntegral, NRoot, Order, Signed, TruncatedDivisionCRing}
import spire.math.BitString
import spire.util.Opt

import java.lang.Math
import java.lang.Integer

trait IntIsEuclideanRing extends EuclideanRing[Int] {
override def minus(a: Int, b: Int): Int = a - b
def negate(a: Int): Int = -a
def one: Int = 1
def plus(a: Int, b: Int): Int = a + b
override def pow(a: Int, b: Int): Int = spire.math.pow(a, b).toInt
override def times(a: Int, b: Int): Int = a * b
def zero: Int = 0

override def fromInt(n: Int): Int = n

def euclideanFunction(a: Int): BigInt = BigInt(a).abs
override def equotmod(a: Int, b: Int): (Int, Int) = spire.math.equotmod(a, b)
def equot(a: Int, b: Int): Int = spire.math.equot(a, b)
def emod(a: Int, b: Int): Int = spire.math.emod(a, b)
override def gcd(a: Int, b: Int)(implicit ev: Eq[Int]): Int = spire.math.gcd(a, b).toInt
override def lcm(a: Int, b: Int)(implicit ev: Eq[Int]): Int = spire.math.lcm(a, b).toInt
}

// Not included in Instances trait.
trait IntIsNRoot extends NRoot[Int] {
def nroot(x: Int, n: Int): Int = {
def findnroot(prev: Int, add: Int): Int = {
val next = prev | add
val e = Math.pow(next, n)

if (e == x || add == 0) {
next
} else if (e <= 0 || e > x) {
findnroot(prev, add >> 1)
} else {
findnroot(next, add >> 1)
}
}

findnroot(0, 1 << ((33 - n) / n))
}

def log(a: Int): Int = Math.log(a.toDouble).toInt
def fpow(a: Int, b: Int): Int = Math.pow(a, b).toInt
}

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

trait IntSigned extends Signed[Int] with IntOrder {
override def signum(a: Int): Int = java.lang.Integer.signum(a)
override def abs(a: Int): Int = if (a < 0) -a else a
}

trait IntTruncatedDivision extends TruncatedDivisionCRing[Int] with IntSigned {
def toBigIntOpt(x: Int): Opt[BigInt] = Opt(BigInt(x))
def tquot(x: Int, y: Int): Int = x / y
def tmod(x: Int, y: Int): Int = x % y
}

trait IntIsReal extends IsIntegral[Int] with IntTruncatedDivision {
def order = this
def toDouble(n: Int): Double = n.toDouble
def toBigInt(n: Int): BigInt = BigInt(n)
}

@SerialVersionUID(0L)
class IntIsBitString extends BitString[Int] with Serializable {
def one: Int = -1
def zero: Int = 0
def and(a: Int, b: Int): Int = a & b
def or(a: Int, b: Int): Int = a | b
def complement(a: Int): Int = ~a

def signed: Boolean = true
def width: Int = 32
def toHexString(n: Int): String = Integer.toHexString(n)

def bitCount(n: Int): Int = Integer.bitCount(n)
def highestOneBit(n: Int): Int = Integer.highestOneBit(n)
def lowestOneBit(n: Int): Int = Integer.lowestOneBit(n)
def numberOfLeadingZeros(n: Int): Int = Integer.numberOfLeadingZeros(n)
def numberOfTrailingZeros(n: Int): Int = Integer.numberOfTrailingZeros(n)

def leftShift(n: Int, i: Int): Int = n << i
def rightShift(n: Int, i: Int): Int = n >>> i
def signedRightShift(n: Int, i: Int): Int = n >> i
def rotateLeft(n: Int, i: Int): Int = Integer.rotateLeft(n, i)
def rotateRight(n: Int, i: Int): Int = Integer.rotateRight(n, i)
}
Loading