From f9ec821107b46c60a9ba9dfef623fa7dda23871b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Apr 2026 19:42:47 +0000 Subject: [PATCH] docs+cleanup: inline hot-path functions, fix stale comments - Add `inline` to hot-path tiny functions: U256.isZero, U256.testBit, FieldP.reduceSelf, FieldP.neg, MutablePoint.isInfinity. These are called thousands of times per EC operation; inline eliminates virtual call overhead (mostly helps Kotlin/Native; JVM JIT already inlines). - Fix stale comment: G_TABLE_SIZE is 1024 for w=12 (was "64 for w=8") https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg --- .../com/vitorpamplona/quartz/utils/secp256k1/FieldP.kt | 4 ++-- .../com/vitorpamplona/quartz/utils/secp256k1/Point.kt | 4 ++-- .../kotlin/com/vitorpamplona/quartz/utils/secp256k1/U256.kt | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/FieldP.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/FieldP.kt index f41205672..19ad7bd9e 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/FieldP.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/FieldP.kt @@ -132,7 +132,7 @@ internal object FieldP { reduceWide(out, w) } - fun neg( + inline fun neg( out: LongArray, a: LongArray, ) { @@ -298,7 +298,7 @@ internal object FieldP { // ==================== Reduction ==================== - fun reduceSelf(a: LongArray) { + inline fun reduceSelf(a: LongArray) { // Exploit P's structure: P = [P0, -1, -1, -1] where P[1..3] = 0xFFFFFFFFFFFFFFFF. // a >= P only if a[3]==a[2]==a[1]==-1 AND a[0] >= P[0]. The first check (a[3]==-1) // fails >99.99% of the time for random field elements, making this a single branch. diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Point.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Point.kt index 64151794f..b2654303d 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Point.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Point.kt @@ -93,7 +93,7 @@ internal class MutablePoint( val y: LongArray = LongArray(4), val z: LongArray = LongArray(4), ) { - fun isInfinity(): Boolean = U256.isZero(z) + inline fun isInfinity(): Boolean = U256.isZero(z) fun setInfinity() { for (i in 0 until 4) { @@ -163,7 +163,7 @@ internal object ECPoint { * w=12 is a good tradeoff for runtime-computed tables on JVM. */ private const val WINDOW_G = 12 - private val G_TABLE_SIZE = 1 shl (WINDOW_G - 2) // 64 for w=8 + private val G_TABLE_SIZE = 1 shl (WINDOW_G - 2) // 1024 for w=12 /** * Precomputed G odd-multiples for wNAF: gOddTable[i] = (2i+1)·G as affine, for i in 0..G_TABLE_SIZE-1. diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/U256.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/U256.kt index ecd80cbd1..76fa73420 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/U256.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/U256.kt @@ -51,7 +51,7 @@ package com.vitorpamplona.quartz.utils.secp256k1 internal object U256 { val ZERO = LongArray(4) - fun isZero(a: LongArray): Boolean = (a[0] or a[1] or a[2] or a[3]) == 0L + inline fun isZero(a: LongArray): Boolean = (a[0] or a[1] or a[2] or a[3]) == 0L /** Unsigned comparison. Returns -1 if a < b, 0 if equal, 1 if a > b. */ fun cmp( @@ -253,8 +253,8 @@ internal object U256 { return ((a[limb] ushr shift) and 0xF).toInt() } - /** Test if bit at position pos is set. */ - fun testBit( + /** Test if bit at position pos is set. Called ~2,800× per mulG (comb table lookup). */ + inline fun testBit( a: LongArray, pos: Int, ): Boolean = (a[pos / 64] ushr (pos % 64)) and 1L == 1L