Various low-level optimizations

- In Draggable2D, use unaryMinus instead of times operator, it will be much
  more efficient since we don't need to unpack/pack x and y.
- In Offset, rewrite isValid() to avoid using a large constant which saves
  4 instructions (11 -> 7) on aarch64. Thanks to Jake Wharton for the idea.
- in Float16, rewrite toBits() and sign to save a bunch of instructions.

Also removes unused constants/methods in Draggable2D and Constraints.

Relnote: N/A
Test: OffsetTest
Change-Id: I5a1ef153b05a4dba6bc4c390d133a6a891642ead
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt
index 23f3458..6c148a0 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt
@@ -31,7 +31,6 @@
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.unit.Velocity
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.coroutineScope
 
 /**
@@ -303,9 +302,8 @@
         )
     }
 
-    private fun Velocity.reverseIfNeeded() = if (reverseDirection) this * -1f else this * 1f
-
-    private fun Offset.reverseIfNeeded() = if (reverseDirection) this * -1f else this * 1f
+    @Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
+    private inline fun Offset.reverseIfNeeded() = if (reverseDirection) -this else this
 }
 
 private class DefaultDraggable2DState(val onDelta: (Offset) -> Unit) : Draggable2DState {
@@ -326,7 +324,5 @@
     }
 }
 
-private val NoOpOnDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {}
 private val NoOpOnDragStart: (startedPosition: Offset) -> Unit = {}
-private val NoOpOnDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit = {}
 private val NoOpOnDragStop: (velocity: Velocity) -> Unit = {}
diff --git a/compose/ui/ui-geometry/api/restricted_current.txt b/compose/ui/ui-geometry/api/restricted_current.txt
index 13de29e..c1b24e8 100644
--- a/compose/ui/ui-geometry/api/restricted_current.txt
+++ b/compose/ui/ui-geometry/api/restricted_current.txt
@@ -36,6 +36,7 @@
     field @kotlin.PublishedApi internal static final long DualFirstNaN = 9187343246269874177L; // 0x7f8000017f800001L
     field @kotlin.PublishedApi internal static final long DualFloatInfinityBase = 9187343241974906880L; // 0x7f8000007f800000L
     field @kotlin.PublishedApi internal static final long DualFloatSignBit = -9223372034707292160L; // 0x8000000080000000L
+    field @kotlin.PublishedApi internal static final long DualLoadedSignificand = 36028792732385279L; // 0x7fffff007fffffL
     field @kotlin.PublishedApi internal static final long DualUnsignedFloatMask = 9223372034707292159L; // 0x7fffffff7fffffffL
     field @kotlin.PublishedApi internal static final int FloatInfinityBase = 2139095040; // 0x7f800000
     field @kotlin.PublishedApi internal static final long Uint64High32 = -9223372034707292160L; // 0x8000000080000000L
diff --git a/compose/ui/ui-geometry/src/androidUnitTest/kotlin/androidx/compose/ui/geometry/OffsetTest.kt b/compose/ui/ui-geometry/src/androidUnitTest/kotlin/androidx/compose/ui/geometry/OffsetTest.kt
index 6bcd179..cacc898 100644
--- a/compose/ui/ui-geometry/src/androidUnitTest/kotlin/androidx/compose/ui/geometry/OffsetTest.kt
+++ b/compose/ui/ui-geometry/src/androidUnitTest/kotlin/androidx/compose/ui/geometry/OffsetTest.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("RedundantSuppression")
+
 package androidx.compose.ui.geometry
 
 import androidx.compose.ui.util.floatFromBits
@@ -57,7 +59,7 @@
         try {
             Offset.Unspecified.x
             Assert.fail("Offset.Unspecified.x is not allowed")
-        } catch (t: Throwable) {
+        } catch (_: Throwable) {
             // no-op
         }
     }
@@ -67,7 +69,7 @@
         try {
             Offset.Unspecified.y
             Assert.fail("Offset.Unspecified.y is not allowed")
-        } catch (t: Throwable) {
+        } catch (_: Throwable) {
             // no-op
         }
     }
@@ -78,7 +80,7 @@
             Offset.Unspecified.copy(x = 100f)
             Offset.Unspecified.copy(y = 70f)
             Assert.fail("Offset.Unspecified.copy is not allowed")
-        } catch (t: Throwable) {
+        } catch (_: Throwable) {
             // no-op
         }
     }
@@ -88,7 +90,7 @@
         try {
             val (_, _) = Offset.Unspecified
             Assert.fail("Size.Unspecified component assignment is not allowed")
-        } catch (t: Throwable) {
+        } catch (_: Throwable) {
             // no-op
         }
     }
diff --git a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/InlineClassHelper.kt b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/InlineClassHelper.kt
index 8338bd2..55e3463 100644
--- a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/InlineClassHelper.kt
+++ b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/InlineClassHelper.kt
@@ -40,3 +40,6 @@
 
 // Encodes the first valid NaN in each of the 32 bit chunk of a 64 bit word
 @PublishedApi internal const val DualFirstNaN = 0x7f800001_7f800001L
+
+// Set all the significand bits for each 32 bit chunk in a 64 bit word
+@PublishedApi internal const val DualLoadedSignificand = 0x007fffff_007fffffL
diff --git a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt
index 100212d..5eca5f4 100644
--- a/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt
+++ b/compose/ui/ui-geometry/src/commonMain/kotlin/androidx/compose/ui/geometry/Offset.kt
@@ -107,9 +107,9 @@
      */
     @Stable
     inline fun isValid(): Boolean {
-        // Take the unsigned packed floats and see if they are < InfinityBase + 1 (first NaN)
+        // Take the unsigned packed floats and see if they are > InfinityBase (any NaN)
         val v = packedValue and DualUnsignedFloatMask
-        return (v - DualFirstNaN) and Uint64High32 == Uint64High32
+        return (v + DualLoadedSignificand) and Uint64High32 == 0L
     }
 
     /**
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Float16.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Float16.kt
index 24e2318..0914fba 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Float16.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/Float16.kt
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:Suppress("KotlinRedundantDiagnosticSuppress")
+
 package androidx.compose.ui.graphics
 
 import androidx.compose.ui.util.floatFromBits
@@ -153,7 +155,7 @@
      */
     fun toBits(): Int =
         if (isNaN()) {
-            NaN.halfValue.toInt()
+            Fp16TheNaN
         } else {
             halfValue.toInt() and 0xffff
         }
@@ -206,13 +208,16 @@
      * * `NaN.sign` is `NaN`
      */
     val sign: Float16
-        get() =
-            when {
-                isNaN() -> NaN
-                this < NegativeZero -> NegativeOne
-                this > PositiveZero -> One
-                else -> this // this is zero, either positive or negative
-            }
+        get() {
+            val v = halfValue.toInt() and Fp16Combined
+            val u =
+                if ((v > Fp16ExponentMax) or (v == 0)) { // 0.0 or NaN
+                    v
+                } else {
+                    (halfValue.toInt() and Fp16SignMask) or Fp16One
+                }
+            return Float16(u.toShort())
+        }
 
     /** Returns a [Float16] with the magnitude of this and the sign of [sign] */
     fun withSign(sign: Float16): Float16 =
@@ -394,8 +399,8 @@
      * @return True if the value is normalized, false otherwise
      */
     fun isNormalized(): Boolean {
-        return halfValue.toInt() and Fp16ExponentMax != 0 &&
-            halfValue.toInt() and Fp16ExponentMax != Fp16ExponentMax
+        val v = halfValue.toInt() and Fp16ExponentMax
+        return (v != 0) and (v != Fp16ExponentMax)
     }
 
     /**
@@ -491,9 +496,6 @@
     }
 }
 
-private val One = Float16(1f)
-private val NegativeOne = Float16(-1f)
-
 private const val Fp16SignShift = 15
 private const val Fp16SignMask = 0x8000
 private const val Fp16ExponentShift = 10
@@ -502,6 +504,8 @@
 private const val Fp16ExponentBias = 15
 private const val Fp16Combined = 0x7fff
 private const val Fp16ExponentMax = 0x7c00
+private const val Fp16One = 0x3c00
+private const val Fp16TheNaN = 0x7e00
 
 private const val Fp32SignShift = 31
 private const val Fp32ExponentShift = 23
diff --git a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Constraints.kt b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Constraints.kt
index e1b4315..79ba2da 100644
--- a/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Constraints.kt
+++ b/compose/ui/ui-unit/src/commonMain/kotlin/androidx/compose/ui/unit/Constraints.kt
@@ -20,7 +20,6 @@
 
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
-import androidx.compose.ui.unit.Constraints.Companion.Infinity
 import androidx.compose.ui.util.fastCoerceAtLeast
 import androidx.compose.ui.util.fastCoerceIn
 import kotlin.jvm.JvmInline
@@ -351,40 +350,17 @@
 private const val Infinity = Int.MAX_VALUE
 
 /**
- * The bit distribution when the focus of the bits should be on the width, but only a minimal
- * difference in focus.
- *
- * 16 bits assigned to width, 15 bits assigned to height.
- */
-private const val MinFocusWidth = 0x2
-
-/**
- * The bit distribution when the focus of the bits should be on the width, and a maximal number of
- * bits assigned to the width.
- *
- * 18 bits assigned to width, 13 bits assigned to height.
- */
-private const val MaxFocusWidth = 0x3
-
-/**
- * The bit distribution when the focus of the bits should be on the height, but only a minimal
- * difference in focus.
- *
- * 15 bits assigned to width, 16 bits assigned to height.
- */
-private const val MinFocusHeight = 0x1
-
-/**
- * The bit distribution when the focus of the bits should be on the height, and a a maximal number
- * of bits assigned to the height.
- *
- * 13 bits assigned to width, 18 bits assigned to height.
- */
-private const val MaxFocusHeight = 0x0
-
-/**
- * The mask to retrieve the focus ([MinFocusWidth], [MaxFocusWidth], [MinFocusHeight],
- * [MaxFocusHeight]).
+ * The mask to retrieve the focus:
+ * - MaxFocusHeight = 0x0. The bit distribution when the focus of the bits should be on the height,
+ *   and a a maximal number of bits assigned to the height. 13 bits assigned to width, 18 bits
+ *   assigned to height.
+ * - MinFocusHeight = 0x1. The bit distribution when the focus of the bits should be on the height,
+ *   but only a minimal difference in focus. 15 bits assigned to width, 16 bits assigned to height.
+ * - MinFocusWidth = 0x2. The bit distribution when the focus of the bits should be on the width,
+ *   but only a minimal difference in focus. 16 bits assigned to width, 15 bits assigned to height.
+ * - MaxFocusWidth = 0x3 .The bit distribution when the focus of the bits should be on the width,
+ *   and a maximal number of bits assigned to the width. 18 bits assigned to width, 13 bits assigned
+ *   to height.
  */
 private const val FocusMask = 0x3L