Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ object NumericRange {

@SerialVersionUID(3L)
private final class NumericRangeIterator[T](self: NumericRange[T], num: Integral[T]) extends AbstractIterator[T] with Serializable {
import num.mkNumericOps
import num.*

private[this] var _hasNext = !self.isEmpty
private[this] var _next: T = self.start
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/collection/immutable/NumericRange.scala
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ object NumericRange {

@SerialVersionUID(3L)
private final class NumericRangeIterator[T](self: NumericRange[T], num: Integral[T]) extends AbstractIterator[T] with Serializable {
import num.mkNumericOps
import num.*

private var _hasNext = !self.isEmpty
private var _next: T = self.start
Expand Down
9 changes: 7 additions & 2 deletions library/src/scala/math/Fractional.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,23 @@ import scala.language.implicitConversions
trait Fractional[T] extends Numeric[T] {
def div(x: T, y: T): T

extension (lhs: T) def /(rhs: T): T = div(lhs, rhs)

@deprecated("use the extension methods available instead", since = "3.10.0")
class FractionalOps(lhs: T) extends NumericOps(lhs) {
def /(rhs: T) = div(lhs, rhs)
}
override implicit def mkNumericOps(lhs: T): FractionalOps =
@deprecated("use the extension methods available instead", since = "3.10.0")
override def mkNumericOps(lhs: T): FractionalOps =
new FractionalOps(lhs)
}

object Fractional {
@inline def apply[T](implicit frac: Fractional[T]): Fractional[T] = frac

trait ExtraImplicits {
implicit def infixFractionalOps[T](x: T)(implicit num: Fractional[T]): Fractional[T]#FractionalOps = new num.FractionalOps(x)
@deprecated("use the extension methods available instead", since = "3.10.0")
def infixFractionalOps[T](x: T)(implicit num: Fractional[T]): Fractional[T]#FractionalOps = new num.FractionalOps(x)
}
object Implicits extends ExtraImplicits
}
15 changes: 13 additions & 2 deletions library/src/scala/math/Integral.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,22 @@ trait Integral[T] extends Numeric[T] {
def quot(x: T, y: T): T
def rem(x: T, y: T): T

extension (lhs: T) {
def /(rhs: T): T = quot(lhs, rhs)

def %(rhs: T): T = rem(lhs, rhs)

def /%(rhs: T): (T, T) = (quot(lhs, rhs), rem(lhs, rhs))
}

@deprecated("use the extension methods available instead", since = "3.10.0")
class IntegralOps(lhs: T) extends NumericOps(lhs) {
def /(rhs: T) = quot(lhs, rhs)
def %(rhs: T) = rem(lhs, rhs)
def /%(rhs: T) = (quot(lhs, rhs), rem(lhs, rhs))
}
override implicit def mkNumericOps(lhs: T): IntegralOps = new IntegralOps(lhs)
@deprecated("use the extension methods available instead", since = "3.10.0")
override def mkNumericOps(lhs: T): IntegralOps = new IntegralOps(lhs)
}

object Integral {
Expand All @@ -41,7 +51,8 @@ object Integral {
* @param num the implicit `Integral` instance for type `T`
* @return an `IntegralOps` instance providing integral operators on `x`
*/
implicit def infixIntegralOps[T](x: T)(implicit num: Integral[T]): Integral[T]#IntegralOps = new num.IntegralOps(x)
@deprecated("use the extension methods available instead", since = "3.10.0")
def infixIntegralOps[T](x: T)(implicit num: Integral[T]): Integral[T]#IntegralOps = new num.IntegralOps(x)
}
object Implicits extends ExtraImplicits
}
127 changes: 79 additions & 48 deletions library/src/scala/math/Numeric.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ object Numeric {
*
* @return a `NumericOps` wrapper around `x` that exposes infix arithmetic operators and numeric conversion methods
*/
implicit def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#NumericOps = new num.NumericOps(x)
@deprecated("use the extension methods available instead", since = "3.10.0")
def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#NumericOps = new num.NumericOps(x)
}
object Implicits extends ExtraImplicits { }

Expand All @@ -49,10 +50,15 @@ object Numeric {
def negate(x: BigInt): BigInt = -x
def fromInt(x: Int): BigInt = BigInt(x)
def parseString(str: String): Option[BigInt] = Try(BigInt(str)).toOption
def toInt(x: BigInt): Int = x.intValue
def toLong(x: BigInt): Long = x.longValue
def toFloat(x: BigInt): Float = x.floatValue
def toDouble(x: BigInt): Double = x.doubleValue
extension (x: BigInt) {
override def toInt: Int = x.intValue

override def toLong: Long = x.longValue

override def toFloat: Float = x.floatValue

override def toDouble: Double = x.doubleValue
}
}
implicit object BigIntIsIntegral extends BigIntIsIntegral with Ordering.BigIntOrdering

Expand All @@ -65,10 +71,12 @@ object Numeric {
def negate(x: Int): Int = -x
def fromInt(x: Int): Int = x
def parseString(str: String): Option[Int] = StringParsers.parseInt(str)
def toInt(x: Int): Int = x
def toLong(x: Int): Long = x.toLong
def toFloat(x: Int): Float = x.toFloat
def toDouble(x: Int): Double = x.toDouble
extension (x: Int) {
override def toInt: Int = x
override def toLong: Long = x.toLong
override def toFloat: Float = x.toFloat
override def toDouble: Double = x.toDouble
}
override def signum(x: Int): Int = math.signum(x)
override def sign(x: Int): Int = math.signum(x)
}
Expand All @@ -83,10 +91,12 @@ object Numeric {
def negate(x: Short): Short = (-x).toShort
def fromInt(x: Int): Short = x.toShort
def parseString(str: String): Option[Short] = StringParsers.parseShort(str)
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
extension (x: Short) {
override def toInt: Int = x.toInt
override def toLong: Long = x.toLong
override def toFloat: Float = x.toFloat
override def toDouble: Double = x.toDouble
}
override def signum(x: Short): Int = math.signum(x.toInt)
override def sign(x: Short): Short = math.signum(x.toInt).toShort
}
Expand All @@ -101,10 +111,12 @@ object Numeric {
def negate(x: Byte): Byte = (-x).toByte
def fromInt(x: Int): Byte = x.toByte
def parseString(str: String): Option[Byte] = StringParsers.parseByte(str)
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
extension (x: Byte) {
override def toInt: Int = x.toInt
override def toLong: Long = x.toLong
override def toFloat: Float = x.toFloat
override def toDouble: Double = x.toDouble
}
override def signum(x: Byte): Int = math.signum(x.toInt)
override def sign(x: Byte): Byte = math.signum(x.toInt).toByte
}
Expand All @@ -119,10 +131,12 @@ object Numeric {
def negate(x: Char): Char = (-x).toChar
def fromInt(x: Int): Char = x.toChar
def parseString(str: String): Option[Char] = Try(str.toInt.toChar).toOption
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
extension (x: Char) {
override def toInt: Int = x.toInt
override def toLong: Long = x.toLong
override def toFloat: Float = x.toFloat
override def toDouble: Double = x.toDouble
}
override def signum(x: Char): Int = math.signum(x.toInt)
override def sign(x: Char): Char = math.signum(x.toInt).toChar
}
Expand All @@ -137,10 +151,12 @@ object Numeric {
def negate(x: Long): Long = -x
def fromInt(x: Int): Long = x.toLong
def parseString(str: String): Option[Long] = StringParsers.parseLong(str)
def toInt(x: Long): Int = x.toInt
def toLong(x: Long): Long = x
def toFloat(x: Long): Float = x.toFloat
def toDouble(x: Long): Double = x.toDouble
extension (x: Long) {
override def toInt: Int = x.toInt
override def toLong: Long = x
override def toFloat: Float = x.toFloat
override def toDouble: Double = x.toDouble
}
override def signum(x: Long): Int = math.signum(x).toInt
override def sign(x: Long): Long = math.signum(x)
}
Expand All @@ -153,13 +169,15 @@ object Numeric {
def negate(x: Float): Float = -x
def fromInt(x: Int): Float = x.toFloat
def parseString(str: String): Option[Float] = StringParsers.parseFloat(str)
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.toDouble
def div(x: Float, y: Float): Float = x / y
// logic in Numeric base trait mishandles abs(-0.0f)
override def abs(x: Float): Float = math.abs(x)
extension (x: Float) {
override def toInt: Int = x.toInt
override def toLong: Long = x.toLong
override def toFloat: Float = x
override def toDouble: Double = x.toDouble
// logic in Numeric base trait mishandles abs(-0.0f)
override def abs: Float = math.abs(x)
}
// logic in Numeric base trait mishandles sign(-0.0f) and sign(Float.NaN)
override def sign(x: Float): Float = math.signum(x)
}
Expand All @@ -172,13 +190,15 @@ object Numeric {
def negate(x: Double): Double = -x
def fromInt(x: Int): Double = x.toDouble
def parseString(str: String): Option[Double] = StringParsers.parseDouble(str)
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
def div(x: Double, y: Double): Double = x / y
// logic in Numeric base trait mishandles abs(-0.0)
override def abs(x: Double): Double = math.abs(x)
extension (x: Double) {
override def toInt: Int = x.toInt
override def toLong: Long = x.toLong
override def toFloat: Float = x.toFloat
override def toDouble: Double = x
// logic in Numeric base trait mishandles abs(-0.0)
override def abs: Double = math.abs(x)
}
// logic in Numeric base trait mishandles sign(-0.0) and sign(Double.NaN)
override def sign(x: Double): Double = math.signum(x)
}
Expand All @@ -202,10 +222,12 @@ object Numeric {
def negate(x: BigDecimal): BigDecimal = -x
def fromInt(x: Int): BigDecimal = BigDecimal(x)
def parseString(str: String): Option[BigDecimal] = Try(BigDecimal(str)).toOption
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
extension (x: BigDecimal) {
override def toInt: Int = x.intValue
override def toLong: Long = x.longValue
override def toFloat: Float = x.floatValue
override def toDouble: Double = x.doubleValue
}
}
private object BigDecimalIsConflicted {
private val _0 = BigDecimal(0) // cached zero is ordinarily cached for default math context
Expand Down Expand Up @@ -233,15 +255,10 @@ trait Numeric[T] extends Ordering[T] {
def negate(x: T): T
def fromInt(x: Int): T
def parseString(str: String): Option[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

@deprecated("use `sign` method instead", since = "2.13.0") def signum(x: T): Int =
if (lt(x, zero)) -1
Expand All @@ -252,6 +269,19 @@ trait Numeric[T] extends Ordering[T] {
else if (gt(x, zero)) one
else zero

extension (lhs: T) {
def +(rhs: T): T = plus(lhs, rhs)
def -(rhs: T): T = minus(lhs, rhs)
def *(rhs: T): T = times(lhs, rhs)
def unary_- : T = negate(lhs)
def abs: T = if (lt(lhs, zero)) negate(lhs) else lhs
def toInt: Int
def toLong: Long
def toFloat: Float
def toDouble: Double
}

@deprecated("use the extension methods available instead", since = "3.10.0")
class NumericOps(lhs: T) {
def +(rhs: T) = plus(lhs, rhs)
def -(rhs: T) = minus(lhs, rhs)
Expand All @@ -265,5 +295,6 @@ trait Numeric[T] extends Ordering[T] {
def toFloat: Float = Numeric.this.toFloat(lhs)
def toDouble: Double = Numeric.this.toDouble(lhs)
}
implicit def mkNumericOps(lhs: T): NumericOps = new NumericOps(lhs)
}
@deprecated("use the extension methods available instead", since = "3.10.0")
def mkNumericOps(lhs: T): NumericOps = new NumericOps(lhs)
}
23 changes: 19 additions & 4 deletions library/src/scala/math/Ordering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ package math

import scala.language.`2.13`
import java.util.Comparator

import scala.language.implicitConversions
import scala.annotation.migration
import scala.annotation.{migration, targetName}
import scala.annotation.unchecked.uncheckedOverride

/** Ordering is a trait whose instances each represent a strategy for sorting
Expand Down Expand Up @@ -247,13 +246,27 @@ trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializabl
if (res1 != 0) res1 else ord.compare(f(x), f(y))
}

extension (lhs: T) {
def <(rhs: T): Boolean = lt(lhs, rhs)
def <=(rhs: T): Boolean = lteq(lhs, rhs)
def >(rhs: T): Boolean = gt(lhs, rhs)
def >=(rhs: T): Boolean = gteq(lhs, rhs)
@targetName("equivInfix")
def equiv(rhs: T): Boolean = outer.equiv(lhs, rhs)
@targetName("maxInfix")
def max(rhs: T): T = outer.max(lhs, rhs)
@targetName("minInfix")
def min(rhs: T): T = outer.min(lhs, rhs)
}

/** This inner class defines comparison operators available for `T`.
*
* It can't extend `AnyVal` because it is not a top-level class
* or a member of a statically accessible object.
*
* @param lhs the left-hand side value for infix comparison operations
*/
@deprecated("use the extension methods available instead", since = "3.10.0")
class OrderingOps(lhs: T) {
def <(rhs: T): Boolean = lt(lhs, rhs)
def <=(rhs: T): Boolean = lteq(lhs, rhs)
Expand All @@ -270,7 +283,8 @@ trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializabl
* @param lhs the value to enrich with ordering operators
* @return an `OrderingOps` wrapping `lhs` and providing infix comparison operators
*/
implicit def mkOrderingOps(lhs: T): OrderingOps = new OrderingOps(lhs)
@deprecated("use the extension methods available instead", since = "3.10.0")
def mkOrderingOps(lhs: T): OrderingOps = new OrderingOps(lhs)
}

trait LowPriorityOrderingImplicits {
Expand Down Expand Up @@ -395,7 +409,8 @@ object Ordering extends LowPriorityOrderingImplicits {
* @param ord the implicit `Ordering` instance for type `T`
* @return an `OrderingOps` instance providing infix comparison operators
*/
implicit def infixOrderingOps[T](x: T)(implicit ord: Ordering[T]): Ordering[T]#OrderingOps = new ord.OrderingOps(x)
@deprecated("use the extension methods available instead", since = "3.10.0")
def infixOrderingOps[T](x: T)(implicit ord: Ordering[T]): Ordering[T]#OrderingOps = new ord.OrderingOps(x)
}

/** An object containing implicits which are not in the default scope. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -895,10 +895,12 @@ class LazyListLazinessTest {
override def negate(x: CustomLong) = I.negate(x.value)
override def fromInt(x: Int) = I.fromInt(x)
override def parseString(str: String) = I.parseString(str).map(CustomLong.apply)
override def toInt(x: CustomLong) = I.toInt(x.value)
override def toLong(x: CustomLong) = I.toLong(x.value)
override def toFloat(x: CustomLong) = I.toFloat(x.value)
override def toDouble(x: CustomLong) = I.toDouble(x.value)
extension (x: CustomLong) {
override def toInt: Int = I.toInt(x.value)
override def toLong: Long = I.toLong(x.value)
override def toFloat: Float = I.toFloat(x.value)
override def toDouble: Double = I.toDouble(x.value)
}
override def compare(x: CustomLong, y: CustomLong) = I.compare(x.value, y.value)
}
}
Expand Down
Loading
Loading