summaryrefslogtreecommitdiff
path: root/test/files/scalacheck
diff options
context:
space:
mode:
authorSzabolcs Berecz <szabolcs.berecz@gmail.com>2011-12-25 01:37:02 +0100
committerSzabolcs Berecz <szabolcs.berecz@gmail.com>2011-12-25 01:39:49 +0100
commit460bbc1276fb4ba83b9bcbdc7f7ba475b352b7c6 (patch)
tree9be8bb2c66d46e9a19184986f66559a0efefe8f4 /test/files/scalacheck
parent5ee9a14a489c6e56c331914e9db258c0473d4d23 (diff)
downloadscala-460bbc1276fb4ba83b9bcbdc7f7ba475b352b7c6.tar.gz
scala-460bbc1276fb4ba83b9bcbdc7f7ba475b352b7c6.tar.bz2
scala-460bbc1276fb4ba83b9bcbdc7f7ba475b352b7c6.zip
fixes #5104 and related NaN ordering inconsistencies
The bug was caused by the inconsistency between j.l.Math.min() and j.l.Double.compareTo() wrt NaN (j.l.Math.min() considers NaN to be less than any other value while j.l.Double.compareTo() says it's greater...) The fix changes Ordering.{FloatOrdering,DoubleOrdering) to base it's results on primitive comparisons and math.{min,max} instead of j.l.{Float,Double}.compareTo()
Diffstat (limited to 'test/files/scalacheck')
-rw-r--r--test/files/scalacheck/nan-ordering.scala130
1 files changed, 130 insertions, 0 deletions
diff --git a/test/files/scalacheck/nan-ordering.scala b/test/files/scalacheck/nan-ordering.scala
new file mode 100644
index 0000000000..2094a46e37
--- /dev/null
+++ b/test/files/scalacheck/nan-ordering.scala
@@ -0,0 +1,130 @@
+import org.scalacheck._
+import Gen._
+import Prop._
+
+object Test extends Properties("NaN-Ordering") {
+
+ val specFloats: Gen[Float] = oneOf(
+ Float.MaxValue,
+ Float.MinPositiveValue,
+ Float.MinValue,
+ Float.NaN,
+ Float.NegativeInfinity,
+ Float.PositiveInfinity,
+ -0.0f,
+ +0.0f
+ )
+
+ property("Float min") = forAll(specFloats, specFloats) { (d1, d2) => {
+ val mathmin = math.min(d1, d2)
+ val numericmin = d1 min d2
+ mathmin == numericmin || mathmin.isNaN && numericmin.isNaN
+ }
+ }
+
+ property("Float max") = forAll(specFloats, specFloats) { (d1, d2) => {
+ val mathmax = math.max(d1, d2)
+ val numericmax = d1 max d2
+ mathmax == numericmax || mathmax.isNaN && numericmax.isNaN
+ }
+ }
+
+ val numFloat = implicitly[Numeric[Float]]
+
+ property("Float lt") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.lt(d1, d2) == d1 < d2 }
+
+ property("Float lteq") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.lteq(d1, d2) == d1 <= d2 }
+
+ property("Float gt") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.gt(d1, d2) == d1 > d2 }
+
+ property("Float gteq") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.gteq(d1, d2) == d1 >= d2 }
+
+ property("Float equiv") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.equiv(d1, d2) == (d1 == d2) }
+
+ property("Float reverse.min") = forAll(specFloats, specFloats) { (d1, d2) => {
+ val mathmin = math.min(d1, d2)
+ val numericmin = numFloat.reverse.min(d1, d2)
+ mathmin == numericmin || mathmin.isNaN && numericmin.isNaN
+ }
+ }
+
+ property("Float reverse.max") = forAll(specFloats, specFloats) { (d1, d2) => {
+ val mathmax = math.max(d1, d2)
+ val numericmax = numFloat.reverse.max(d1, d2)
+ mathmax == numericmax || mathmax.isNaN && numericmax.isNaN
+ }
+ }
+
+ property("Float reverse.lt") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.reverse.lt(d1, d2) == d2 < d1 }
+
+ property("Float reverse.lteq") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.reverse.lteq(d1, d2) == d2 <= d1 }
+
+ property("Float reverse.gt") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.reverse.gt(d1, d2) == d2 > d1 }
+
+ property("Float reverse.gteq") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.reverse.gteq(d1, d2) == d2 >= d1 }
+
+ property("Float reverse.equiv") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.reverse.equiv(d1, d2) == (d1 == d2) }
+
+
+ val specDoubles: Gen[Double] = oneOf(
+ Double.MaxValue,
+ Double.MinPositiveValue,
+ Double.MinValue,
+ Double.NaN,
+ Double.NegativeInfinity,
+ Double.PositiveInfinity,
+ -0.0,
+ +0.0
+ )
+
+ // ticket #5104
+ property("Double min") = forAll(specDoubles, specDoubles) { (d1, d2) => {
+ val mathmin = math.min(d1, d2)
+ val numericmin = d1 min d2
+ mathmin == numericmin || mathmin.isNaN && numericmin.isNaN
+ }
+ }
+
+ property("Double max") = forAll(specDoubles, specDoubles) { (d1, d2) => {
+ val mathmax = math.max(d1, d2)
+ val numericmax = d1 max d2
+ mathmax == numericmax || mathmax.isNaN && numericmax.isNaN
+ }
+ }
+
+ val numDouble = implicitly[Numeric[Double]]
+
+ property("Double lt") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.lt(d1, d2) == d1 < d2 }
+
+ property("Double lteq") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.lteq(d1, d2) == d1 <= d2 }
+
+ property("Double gt") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.gt(d1, d2) == d1 > d2 }
+
+ property("Double gteq") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.gteq(d1, d2) == d1 >= d2 }
+
+ property("Double equiv") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.equiv(d1, d2) == (d1 == d2) }
+
+ property("Double reverse.min") = forAll(specDoubles, specDoubles) { (d1, d2) => {
+ val mathmin = math.min(d1, d2)
+ val numericmin = numDouble.reverse.min(d1, d2)
+ mathmin == numericmin || mathmin.isNaN && numericmin.isNaN
+ }
+ }
+
+ property("Double reverse.max") = forAll(specDoubles, specDoubles) { (d1, d2) => {
+ val mathmax = math.max(d1, d2)
+ val numericmax = numDouble.reverse.max(d1, d2)
+ mathmax == numericmax || mathmax.isNaN && numericmax.isNaN
+ }
+ }
+
+ property("Double reverse.lt") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.reverse.lt(d1, d2) == d2 < d1 }
+
+ property("Double reverse.lteq") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.reverse.lteq(d1, d2) == d2 <= d1 }
+
+ property("Double reverse.gt") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.reverse.gt(d1, d2) == d2 > d1 }
+
+ property("Double reverse.gteq") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.reverse.gteq(d1, d2) == d2 >= d1 }
+
+ property("Double reverse.equiv") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.reverse.equiv(d1, d2) == (d1 == d2) }
+}