Document and test NaN propagation of maxOf/minOf

Also simplify minOf/maxOf implementations

#KT-38708
This commit is contained in:
Ilya Gorbunov
2020-05-21 23:42:57 +03:00
parent 7b68de38e1
commit b4ba00ca36
10 changed files with 514 additions and 1232 deletions
@@ -5,6 +5,8 @@
package test.collections
import test.assertIsNegativeZero
import test.assertIsPositiveZero
import test.assertStaticAndRuntimeTypeIs
import kotlin.test.*
import test.collections.behaviors.*
@@ -909,6 +911,9 @@ class CollectionTest {
assertEquals(Double.NaN, listOf(1, -1, 0).minOf { it.toDouble().pow(0.5) })
assertEquals(Float.NaN, listOf(1, -1, 0).minOf { it.toFloat().pow(0.5F) })
assertIsNegativeZero(listOf(1.0, -1.0).shuffled().minOf { it * 0.0 })
assertIsNegativeZero(listOf(1.0F, -1.0F).shuffled().minOf { it * 0.0F }.toDouble())
}
@Test fun minOfWith() {
@@ -934,6 +939,9 @@ class CollectionTest {
assertEquals(16.0, listOf(1, 2, 3, 4, 5).maxOf { (-2.0).pow(it) })
assertEquals(16.0F, listOf(1, 2, 3, 4, 5).maxOf { (-2.0F).pow(it) })
assertIsPositiveZero(listOf(1.0, -1.0).shuffled().maxOf { it * 0.0 })
assertIsPositiveZero(listOf(1.0F, -1.0F).shuffled().maxOf { it * 0.0F }.toDouble())
}
@Test fun maxOfWith() {
@@ -946,9 +954,6 @@ class CollectionTest {
assertEquals(null, emptyList<Int>().maxOfWithOrNull(naturalOrder()) { it })
// TODO: investigate why no unit-coercion happens here and an explicit 'Unit' is required
assertFailsWith<NoSuchElementException> { emptyList<Int>().maxOfWith(naturalOrder()) { it }; Unit }
assertEquals(Double.NaN, listOf(1, -1, 0).maxOf { it.toDouble().pow(0.5) })
assertEquals(Float.NaN, listOf(1, -1, 0).maxOf { it.toFloat().pow(0.5F) })
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -100,6 +100,24 @@ class NaNPropagationTest {
)
}
@Test
fun arrayMinOf() {
propagateOf3(
{ a, b, c -> arrayOf(a, b, c).minOf { it } },
{ a, b, c -> arrayOf(a, b, c).minOf { it } },
"arrayOf().minOf()"
)
}
@Test
fun arrayMaxOf() {
propagateOf3(
{ a, b, c -> arrayOf(a, b, c).maxOf { it } },
{ a, b, c -> arrayOf(a, b, c).maxOf { it } },
"arrayOf().maxOf()"
)
}
@Test
fun primitiveArrayMin() {
propagateOf2(
@@ -118,6 +136,34 @@ class NaNPropagationTest {
)
}
@Test
fun primitiveArrayMinOf() {
propagateOf3(
{ a, b, c -> doubleArrayOf(a, b, c).minOf { it } },
{ a, b, c -> floatArrayOf(a, b, c).minOf { it } },
"primitiveArrayOf().minOf()"
)
propagateOf3(
{ a, b, c -> val arr = doubleArrayOf(a, b, c); intArrayOf(0, 1, 2).minOf { arr[it] } },
{ a, b, c -> val arr = floatArrayOf(a, b, c); intArrayOf(0, 1, 2).minOf { arr[it] } },
"intArrayOf().minOf()"
)
}
@Test
fun primitiveArrayMaxOf() {
propagateOf3(
{ a, b, c -> doubleArrayOf(a, b, c).maxOf { it } },
{ a, b, c -> floatArrayOf(a, b, c).maxOf { it } },
"primitiveArrayOf().maxOf()"
)
propagateOf3(
{ a, b, c -> val arr = doubleArrayOf(a, b, c); intArrayOf(0, 1, 2).maxOf { arr[it] } },
{ a, b, c -> val arr = floatArrayOf(a, b, c); intArrayOf(0, 1, 2).maxOf { arr[it] } },
"intArrayOf().maxOf()"
)
}
@Test
fun listMin() {
propagateOf2(
@@ -136,6 +182,24 @@ class NaNPropagationTest {
)
}
@Test
fun listMinOf() {
propagateOf3(
{ a, b, c -> listOf(a, b, c).minOf { it } },
{ a, b, c -> listOf(a, b, c).minOf { it } },
"listOf().minOf()"
)
}
@Test
fun listMaxOf() {
propagateOf3(
{ a, b, c -> listOf(a, b, c).maxOf { it } },
{ a, b, c -> listOf(a, b, c).maxOf { it } },
"listOf().maxOf()"
)
}
@Test
fun sequenceMin() {
propagateOf2(
@@ -154,6 +218,23 @@ class NaNPropagationTest {
)
}
@Test
fun sequenceMinOf() {
propagateOf3(
{ a, b, c -> sequenceOf(a, b, c).minOf { it } },
{ a, b, c -> sequenceOf(a, b, c).minOf { it } },
"sequenceOf().minOf()"
)
}
@Test
fun sequenceMaxOf() {
propagateOf3(
{ a, b, c -> sequenceOf(a, b, c).maxOf { it } },
{ a, b, c -> sequenceOf(a, b, c).maxOf { it } },
"sequenceOf().maxOf()"
)
}
}
class NaNTotalOrderTest {
+13 -2
View File
@@ -1,10 +1,12 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package test
import kotlin.math.withSign
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
@@ -27,4 +29,13 @@ fun assertArrayContentEquals(expected: CharArray, actual: CharArray, message: St
fun assertArrayContentEquals(expected: UIntArray, actual: UIntArray, message: String? = null) = assertTrue(expected contentEquals actual, message)
fun assertArrayContentEquals(expected: ULongArray, actual: ULongArray, message: String? = null) = assertTrue(expected contentEquals actual, message)
fun assertArrayContentEquals(expected: UShortArray, actual: UShortArray, message: String? = null) = assertTrue(expected contentEquals actual, message)
fun assertArrayContentEquals(expected: UByteArray, actual: UByteArray, message: String? = null) = assertTrue(expected contentEquals actual, message)
fun assertArrayContentEquals(expected: UByteArray, actual: UByteArray, message: String? = null) = assertTrue(expected contentEquals actual, message)
fun assertIsNegativeZero(value: Double) {
assertEquals(-0.0, value)
assertEquals(-1.0, 1.0.withSign(value))
}
fun assertIsPositiveZero(value: Double) {
assertEquals(0.0, value)
assertEquals(1.0, 1.0.withSign(value))
}