summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala33
-rw-r--r--src/library/scala/collection/immutable/Range.scala21
2 files changed, 48 insertions, 6 deletions
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index 486c2b6c8f..249d76584d 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -175,9 +175,36 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
catch { case _: ClassCastException => false }
final override def sum[B >: T](implicit num: Numeric[B]): B = {
- if (isEmpty) this.num fromInt 0
- else if (numRangeElements == 1) head
- else ((this.num fromInt numRangeElements) * (head + last) / (this.num fromInt 2))
+ // arithmetic series formula can be used for regular addition
+ if ((num eq scala.math.Numeric.IntIsIntegral)||
+ (num eq scala.math.Numeric.BigIntIsIntegral)||
+ (num eq scala.math.Numeric.ShortIsIntegral)||
+ (num eq scala.math.Numeric.ByteIsIntegral)||
+ (num eq scala.math.Numeric.CharIsIntegral)||
+ (num eq scala.math.Numeric.LongIsIntegral)||
+ (num eq scala.math.Numeric.FloatAsIfIntegral)||
+ (num eq scala.math.Numeric.BigDecimalIsFractional)||
+ (num eq scala.math.Numeric.DoubleAsIfIntegral)) {
+ val numAsIntegral = num.asInstanceOf[Integral[B]]
+ import numAsIntegral._
+ if (isEmpty) num fromInt 0
+ else if (numRangeElements == 1) head
+ else ((num fromInt numRangeElements) * (head + last) / (num fromInt 2))
+ } else {
+ // user provided custom Numeric, we cannot rely on arithmetic series formula
+ if (isEmpty) num.zero
+ else {
+ var acc = num.zero
+ var i = head
+ var idx = 0
+ while(idx < length) {
+ acc = num.plus(acc, i)
+ i = i + step
+ idx = idx + 1
+ }
+ acc
+ }
+ }
}
override lazy val hashCode = super.hashCode()
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index 00f398a4b0..786b18cd21 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -259,9 +259,24 @@ extends scala.collection.AbstractSeq[Int]
final def contains(x: Int) = isWithinBoundaries(x) && ((x - start) % step == 0)
final override def sum[B >: Int](implicit num: Numeric[B]): Int = {
- if (isEmpty) 0
- else if (numRangeElements == 1) head
- else (numRangeElements.toLong * (head + last) / 2).toInt
+ if (num eq scala.math.Numeric.IntIsIntegral) {
+ // this is normal integer range with usual addition. arithmetic series formula can be used
+ if (isEmpty) 0
+ else if (numRangeElements == 1) head
+ else (numRangeElements.toLong * (head + last) / 2).toInt
+ } else {
+ // user provided custom Numeric, we cannot rely on arithmetic series formula
+ if (isEmpty) num.toInt(num.zero)
+ else {
+ var acc = num.zero
+ var i = head
+ while(i != terminalElement) {
+ acc = num.plus(acc, i)
+ i = i + step
+ }
+ num.toInt(acc)
+ }
+ }
}
override def toIterable = this