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() {