diff options
author | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2013-11-11 14:20:16 +0100 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2013-12-29 17:14:37 +0200 |
commit | 4b6a0a999e935a94501da272a12956c024141cb2 (patch) | |
tree | 5ca61d3ea3160baeab2dbf07b30cbb5e5eb1b3ba /src/library/scala/collection/immutable/Range.scala | |
parent | 6834cc2278ad522e49493b624da95bfa00af1604 (diff) | |
download | scala-4b6a0a999e935a94501da272a12956c024141cb2.tar.gz scala-4b6a0a999e935a94501da272a12956c024141cb2.tar.bz2 scala-4b6a0a999e935a94501da272a12956c024141cb2.zip |
SI-7443 Use typeclass instance for {Range,NumericRange}.sum
Previously both Range and NumeriRange used formula for sum of elements
of arithmetic series and thus always assumed that provided Numeric is
regular one.
Bug is now fixed by conservatively checking if Numeric is one of
default ones and the formula still holds.
Diffstat (limited to 'src/library/scala/collection/immutable/Range.scala')
-rw-r--r-- | src/library/scala/collection/immutable/Range.scala | 21 |
1 files changed, 18 insertions, 3 deletions
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 |