From f5cc53c15798336051e98cd391c69ae78426a3f8 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 3 Nov 2016 23:34:48 +0300 Subject: [PATCH] Provide ComparableRange specializations for Double and Float. #KT-4481 --- libraries/stdlib/src/kotlin/ranges/Ranges.kt | 26 ++++++++++++++++++-- libraries/stdlib/test/ranges/RangeTest.kt | 15 +++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/libraries/stdlib/src/kotlin/ranges/Ranges.kt b/libraries/stdlib/src/kotlin/ranges/Ranges.kt index a63f84bc52d..de5232de0ca 100644 --- a/libraries/stdlib/src/kotlin/ranges/Ranges.kt +++ b/libraries/stdlib/src/kotlin/ranges/Ranges.kt @@ -5,7 +5,7 @@ package kotlin.ranges /** * Represents a range of [Comparable] values. */ -private class ComparableRange> ( +private open class ComparableRange> ( override val start: T, override val endInclusive: T ): ClosedRange { @@ -22,11 +22,33 @@ private class ComparableRange> ( override fun toString(): String = "$start..$endInclusive" } +private class DoubleRange ( + start: Double, + endInclusive: Double +): ComparableRange(start, endInclusive) { + override fun contains(value: Double): Boolean = value >= start && value <= endInclusive + override fun isEmpty(): Boolean = start > endInclusive +} + +private class FloatRange ( + start: Float, + endInclusive: Float +): ComparableRange(start, endInclusive) { + override fun contains(value: Float): Boolean = value >= start && value <= endInclusive + override fun isEmpty(): Boolean = start > endInclusive +} + /** * Creates a range from this [Comparable] value to the specified [that] value. This value * needs to be smaller than [that] value, otherwise the returned range will be empty. */ -public operator fun > T.rangeTo(that: T): ClosedRange = ComparableRange(this, that) +public operator fun > T.rangeTo(that: T): ClosedRange = + @Suppress("UNCHECKED_CAST") + when { + this is Double && that is Double -> DoubleRange(this, that) as ClosedRange + this is Float && that is Float -> FloatRange(this, that) as ClosedRange + else -> ComparableRange(this, that) + } internal fun checkStepIsPositive(isPositive: Boolean, step: Number) { diff --git a/libraries/stdlib/test/ranges/RangeTest.kt b/libraries/stdlib/test/ranges/RangeTest.kt index a1ae1cbeabe..298cf3a8afe 100644 --- a/libraries/stdlib/test/ranges/RangeTest.kt +++ b/libraries/stdlib/test/ranges/RangeTest.kt @@ -196,6 +196,14 @@ public class RangeTest { assertTrue(1.toInt() in range) assertTrue(1.toLong() in range) assertTrue(1.toFloat() in range) + + val specialRange = 0.0..-0.0 + assertFalse(specialRange.isEmpty()) + assertTrue(-0.0 in specialRange) + // should it be or not: assertEquals(-0.0..0.0, specialRange) + val nanRange = 0.0..Double.NaN + assertFalse(Double.NaN in nanRange) + } @Test fun floatRange() { @@ -224,6 +232,13 @@ public class RangeTest { assertTrue(1.toDouble() in range) assertFalse(Double.MAX_VALUE in range) + + val specialRange = 0.0F..-0.0F + assertFalse(specialRange.isEmpty()) + assertTrue(-0.0F in specialRange) + // should it be or not: assertEquals(-0.0F..0.0F, specialRange) + val nanRange = 0.0F..Float.NaN + assertFalse(Float.NaN in nanRange) } @Test fun isEmpty() {