From 00d3f103b3db5530bfbf6b565843d0938a3cef48 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 29 Aug 2015 16:02:53 -0700 Subject: SI-9388 Fix Range behavior around Int.MaxValue terminalElement (the element _after_ the last one!) was used to terminate foreach loops and sums of non-standard instances of Numeric. Unfortunately, this could result in the end wrapping around and hitting the beginning again, making the first element bad. This patch fixes the behavior by altering the loop to end after the last element is encountered. The particular flavor was chosen out of a few possibilities because it gave the best microbenchmarks on both large and small ranges. Test written. While testing, a bug was also uncovered in NumericRange, and was also fixed. In brief, the logic around sum is rather complex since division is not unique when you have overflow. Floating point has its own complexities, too. Also updated incorrect test t4658 that insisted on incorrect answers (?!) and added logic to make sure it at least stays self-consistent, and fixed the range.scala test which used the same wrong (overflow-prone) formula that the Range collection did. --- test/files/scalacheck/range.scala | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'test/files/scalacheck') diff --git a/test/files/scalacheck/range.scala b/test/files/scalacheck/range.scala index 493083a51f..ac24b52f8d 100644 --- a/test/files/scalacheck/range.scala +++ b/test/files/scalacheck/range.scala @@ -134,7 +134,22 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) { val expected = r.length match { case 0 => 0 case 1 => r.head - case _ => ((r.head + r.last).toLong * r.length / 2).toInt + case x if x < 1000 => + // Explicit sum, to guard against having the same mistake in both the + // range implementation and test implementation of sum formula. + // (Yes, this happened before.) + var i = r.head + var s = 0L + var n = x + while (n > 0) { + s += i + i += r.step + n -= 1 + } + s.toInt + case _ => + // Make sure head + last doesn't overflow! + ((r.head.toLong + r.last) * r.length / 2).toInt } // println("size: " + r.length) // println("expected: " + expected) -- cgit v1.2.3