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 11 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-3/spire/std/double.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 DoubleIsField extends Field[Double] {
override inline def minus(a: Double, b: Double): Double = a - b
inline def negate(a: Double): Double = -a
inline def one: Double = 1.0
inline def plus(a: Double, b: Double): Double = a + b
override inline def pow(a: Double, b: Int): Double = Math.pow(a, b)
override inline def times(a: Double, b: Double): Double = a * b
inline def zero: Double = 0.0
inline def div(a: Double, b: Double): Double = a / b

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

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

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

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

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

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

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

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

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

trait DoubleSigned extends Signed[Double] with DoubleOrder {
inline def order = this
override inline def signum(a: Double): Int = Math.signum(a).toInt
override inline 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]
inline def tquot(a: Double, b: Double): Double = (a - (a % b)) / b
inline def tmod(a: Double, b: Double): Double = a % b
}

trait DoubleIsReal extends IsRational[Double] with DoubleTruncatedDivision {
def toDouble(x: Double): Double = x
inline def ceil(a: Double): Double = Math.ceil(a)
inline def floor(a: Double): Double = Math.floor(a)
inline def round(a: Double): Double = spire.math.round(a)
inline def isWhole(a: Double): Boolean = a % 1.0 == 0.0
def toRational(a: Double): Rational = Rational(a)
}
2 changes: 1 addition & 1 deletion core/src/main/scala/spire/math/Numeric.scala
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ private[math] class DoubleIsNumeric
with ConvertableToDouble
with DoubleIsReal
with Serializable {
override def fromInt(n: Int): Double = n.toDouble
override def fromInt(n: Int): Double = n
override def fromDouble(n: Double): Double = n
override def fromBigInt(n: BigInt): Double = n.toDouble
override def toDouble(n: Double): Double = n.toDouble
Expand Down
Loading
Loading