Improve min/max specialization for longs and 3-arg overloads in JS

This commit is contained in:
Ilya Gorbunov
2017-11-10 08:38:18 +03:00
parent 2da9f12bc5
commit 233376eef0
3 changed files with 64 additions and 29 deletions
@@ -26,7 +26,7 @@ public fun <T: Comparable<T>> maxOf(a: T, b: T): T {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun maxOf(a: Byte, b: Byte): Byte {
return Math.max(a.toInt(), b.toInt()).toByte()
return Math.max(a.toInt(), b.toInt()).unsafeCast<Byte>()
}
/**
@@ -35,7 +35,7 @@ public inline fun maxOf(a: Byte, b: Byte): Byte {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun maxOf(a: Short, b: Short): Short {
return Math.max(a.toInt(), b.toInt()).toShort()
return Math.max(a.toInt(), b.toInt()).unsafeCast<Short>()
}
/**
@@ -51,9 +51,9 @@ public inline fun maxOf(a: Int, b: Int): Int {
* Returns the greater of two values.
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
@Suppress("NOTHING_TO_INLINE")
public inline fun maxOf(a: Long, b: Long): Long {
return Math.max(a, b)
return if (a >= b) a else b
}
/**
@@ -88,7 +88,7 @@ public fun <T: Comparable<T>> maxOf(a: T, b: T, c: T): T {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte {
return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).toByte()
return Math.max(a.toInt(), b.toInt(), c.toInt()).unsafeCast<Byte>()
}
/**
@@ -97,7 +97,7 @@ public inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun maxOf(a: Short, b: Short, c: Short): Short {
return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).toShort()
return Math.max(a.toInt(), b.toInt(), c.toInt()).unsafeCast<Short>()
}
/**
@@ -106,7 +106,7 @@ public inline fun maxOf(a: Short, b: Short, c: Short): Short {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun maxOf(a: Int, b: Int, c: Int): Int {
return maxOf(a, maxOf(b, c))
return Math.max(a, b, c)
}
/**
@@ -124,7 +124,7 @@ public inline fun maxOf(a: Long, b: Long, c: Long): Long {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun maxOf(a: Float, b: Float, c: Float): Float {
return maxOf(a, maxOf(b, c))
return Math.max(a, b, c)
}
/**
@@ -133,7 +133,7 @@ public inline fun maxOf(a: Float, b: Float, c: Float): Float {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun maxOf(a: Double, b: Double, c: Double): Double {
return maxOf(a, maxOf(b, c))
return Math.max(a, b, c)
}
/**
@@ -168,7 +168,7 @@ public fun <T: Comparable<T>> minOf(a: T, b: T): T {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun minOf(a: Byte, b: Byte): Byte {
return Math.min(a.toInt(), b.toInt()).toByte()
return Math.min(a.toInt(), b.toInt()).unsafeCast<Byte>()
}
/**
@@ -177,7 +177,7 @@ public inline fun minOf(a: Byte, b: Byte): Byte {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun minOf(a: Short, b: Short): Short {
return Math.min(a.toInt(), b.toInt()).toShort()
return Math.min(a.toInt(), b.toInt()).unsafeCast<Short>()
}
/**
@@ -193,9 +193,9 @@ public inline fun minOf(a: Int, b: Int): Int {
* Returns the smaller of two values.
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
@Suppress("NOTHING_TO_INLINE")
public inline fun minOf(a: Long, b: Long): Long {
return Math.min(a, b)
return if (a <= b) a else b
}
/**
@@ -230,7 +230,7 @@ public fun <T: Comparable<T>> minOf(a: T, b: T, c: T): T {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun minOf(a: Byte, b: Byte, c: Byte): Byte {
return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).toByte()
return Math.min(a.toInt(), b.toInt(), c.toInt()).unsafeCast<Byte>()
}
/**
@@ -239,7 +239,7 @@ public inline fun minOf(a: Byte, b: Byte, c: Byte): Byte {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun minOf(a: Short, b: Short, c: Short): Short {
return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).toShort()
return Math.min(a.toInt(), b.toInt(), c.toInt()).unsafeCast<Short>()
}
/**
@@ -248,7 +248,7 @@ public inline fun minOf(a: Short, b: Short, c: Short): Short {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun minOf(a: Int, b: Int, c: Int): Int {
return minOf(a, minOf(b, c))
return Math.min(a, b, c)
}
/**
@@ -266,7 +266,7 @@ public inline fun minOf(a: Long, b: Long, c: Long): Long {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun minOf(a: Float, b: Float, c: Float): Float {
return minOf(a, minOf(b, c))
return Math.min(a, b, c)
}
/**
@@ -275,7 +275,7 @@ public inline fun minOf(a: Float, b: Float, c: Float): Float {
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun minOf(a: Double, b: Double, c: Double): Double {
return minOf(a, minOf(b, c))
return Math.min(a, b, c)
}
/**
+6 -6
View File
@@ -1045,14 +1045,14 @@ public fun abs(n: Int): Int = if (n < 0) (-n or 0) else n
*/
@SinceKotlin("1.2")
@InlineOnly
public inline fun min(a: Int, b: Int): Int = minOf(a, b)
public inline fun min(a: Int, b: Int): Int = nativeMath.min(a, b)
/**
* Returns the greater of two values.
*/
@SinceKotlin("1.2")
@InlineOnly
public inline fun max(a: Int, b: Int): Int = maxOf(a, b)
public inline fun max(a: Int, b: Int): Int = nativeMath.max(a, b)
/**
* Returns the absolute value of this value.
@@ -1096,15 +1096,15 @@ public fun abs(n: Long): Long = if (n < 0) -n else n
* Returns the smaller of two values.
*/
@SinceKotlin("1.2")
@InlineOnly
public inline fun min(a: Long, b: Long): Long = minOf(a, b)
@Suppress("NOTHING_TO_INLINE")
public inline fun min(a: Long, b: Long): Long = if (a <= b) a else b
/**
* Returns the greater of two values.
*/
@SinceKotlin("1.2")
@InlineOnly
public inline fun max(a: Long, b: Long): Long = maxOf(a, b)
@Suppress("NOTHING_TO_INLINE")
public inline fun max(a: Long, b: Long): Long = if (a >= b) a else b
/**
* Returns the absolute value of this value.
@@ -150,7 +150,6 @@ object ComparableOps : TemplateGroupBase() {
typeParam("T: Comparable<T>")
returns("T")
receiver("")
specialFor(Primitives) { inlineOnly() }
doc {
"""
Returns the smaller of two values.
@@ -159,15 +158,25 @@ object ComparableOps : TemplateGroupBase() {
}
// TODO: Add a note about NaN propagation for floats.
specialFor(Primitives) {
inlineOnly()
doc {
"""Returns the smaller of two values."""
}
// TODO: custom body for JS minOf(Long, Long)
var convertBack = "to$primitive()"
on(Platform.JS) {
convertBack = "unsafeCast<$primitive>()"
}
body {
"return Math.min(a, b)"
}
if (primitive in shortIntPrimitives) {
body { "return Math.min(a.toInt(), b.toInt()).to$primitive()" }
body { "return Math.min(a.toInt(), b.toInt()).$convertBack" }
}
on(Platform.JS) {
if (primitive == PrimitiveType.Long) {
inline(suppressWarning = true)
body { "return if (a <= b) a else b" }
}
}
}
body(Generic) {
@@ -197,6 +206,14 @@ object ComparableOps : TemplateGroupBase() {
specialFor(Primitives) {
if (primitive in shortIntPrimitives) {
body { "return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).to$primitive()" }
on(Platform.JS) {
body { "return Math.min(a.toInt(), b.toInt(), c.toInt()).unsafeCast<$primitive>()" }
}
}
else if (primitive != PrimitiveType.Long) {
on(Platform.JS) {
body { "return Math.min(a, b, c)" }
}
}
}
}
@@ -245,7 +262,6 @@ object ComparableOps : TemplateGroupBase() {
typeParam("T: Comparable<T>")
returns("T")
receiver("")
specialFor(Primitives) { inlineOnly() }
doc {
"""
Returns the greater of two values.
@@ -254,14 +270,25 @@ object ComparableOps : TemplateGroupBase() {
}
// TODO: Add a note about NaN propagation for floats.
specialFor(Primitives) {
inlineOnly()
doc {
"""Returns the greater of two values."""
}
var convertBack = "to$primitive()"
on(Platform.JS) {
convertBack = "unsafeCast<$primitive>()"
}
body {
"return Math.max(a, b)"
}
if (primitive in shortIntPrimitives) {
body { "return Math.max(a.toInt(), b.toInt()).to$primitive()" }
body { "return Math.max(a.toInt(), b.toInt()).$convertBack" }
}
on(Platform.JS) {
if (primitive == PrimitiveType.Long) {
inline(suppressWarning = true)
body { "return if (a >= b) a else b" }
}
}
}
body(Generic) {
@@ -291,6 +318,14 @@ object ComparableOps : TemplateGroupBase() {
specialFor(Primitives) {
if (primitive in shortIntPrimitives) {
body { "return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).to$primitive()" }
on(Platform.JS) {
body { "return Math.max(a.toInt(), b.toInt(), c.toInt()).unsafeCast<$primitive>()" }
}
}
else if (primitive != PrimitiveType.Long) {
on(Platform.JS) {
body { "return Math.max(a, b, c)" }
}
}
}
}