perf: replace all uLt with uLtInline, inline isInfinity body

Replace every non-inline uLt() call with uLtInline() across FieldP.kt,
U256.kt, and ScalarN.kt. The expect/actual uLt() can't be inline
(KMP limitation), costing ~84ns per call on ART as a real function
dispatch. From the trace: 12,394 uLt calls × 84ns = 1.035ms per
verify (1.2% of total).

uLtInline uses the same XOR-with-MIN_VALUE trick but as a package-level
inline function — zero dispatch overhead.

Also inline isInfinity() body directly: was delegating to U256.isZero()
(double dispatch), now computes (z[0] or z[1] or z[2] or z[3]) == 0L
directly. 190 calls × 347ns = 66µs saved.

https://claude.ai/code/session_015CtM5k88rF7WFgX8o2AGNR
This commit is contained in:
Claude
2026-04-09 21:19:52 +00:00
parent 40cb0e270c
commit e148ff1ed7
4 changed files with 87 additions and 87 deletions
@@ -68,7 +68,7 @@ internal object FieldP {
if (carry != 0) {
// Overflow past 2^256: add 2^256 mod p = 2^32 + 977 = 0x1000003D1
val s1 = out[0] + 4294968273L
val c1 = if (uLt(s1, out[0])) 1L else 0L
val c1 = if (uLtInline(s1, out[0])) 1L else 0L
out[0] = s1
if (c1 != 0L) {
out[1]++
@@ -95,7 +95,7 @@ internal object FieldP {
if (borrow != 0) {
// Add P = [P0, -1, -1, -1].
val s0 = out[0] + P0
val c0 = if (uLt(s0, out[0])) 1L else 0L
val c0 = if (uLtInline(s0, out[0])) 1L else 0L
out[0] = s0
// For limbs 1-3: adding P[i]=-1 with carry c:
// c=1 → result unchanged, carry out=1 (identity propagation)
@@ -173,7 +173,7 @@ internal object FieldP {
}
// P - a: limb 0 is P0 - a[0], limbs 1-3 are (-1) - a[i] = ~a[i]
out[0] = P0 - a[0]
val borrow = if (uLt(P0, a[0])) 1L else 0L
val borrow = if (uLtInline(P0, a[0])) 1L else 0L
// ~a[i] - borrow. New borrow only if ~a[i] == 0 (i.e., a[i] == -1) and borrow == 1
out[1] = a[1].inv() - borrow
val b1 = if (a[1] == -1L && borrow != 0L) 1L else 0L
@@ -200,28 +200,28 @@ internal object FieldP {
// Conditional add: out = a + (P & mask), unrolled
// Limb 0
s1 = a[0] + p0
c1 = if (uLt(s1, a[0])) 1L else 0L
c1 = if (uLtInline(s1, a[0])) 1L else 0L
out[0] = s1
var carry = c1
// Limb 1
s1 = a[1] + mask
c1 = if (uLt(s1, a[1])) 1L else 0L
c1 = if (uLtInline(s1, a[1])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[1] = s2
carry = c1 + c2
// Limb 2
s1 = a[2] + mask
c1 = if (uLt(s1, a[2])) 1L else 0L
c1 = if (uLtInline(s1, a[2])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[2] = s2
carry = c1 + c2
// Limb 3
s1 = a[3] + mask
c1 = if (uLt(s1, a[3])) 1L else 0L
c1 = if (uLtInline(s1, a[3])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[3] = s2
carry = c1 + c2
@@ -405,7 +405,7 @@ internal object FieldP {
hcLo = w[4] * c
hcHi = unsignedMultiplyHigh(w[4], c)
s1 = w[0] + hcLo
c1 = if (uLt(s1, w[0])) 1L else 0L
c1 = if (uLtInline(s1, w[0])) 1L else 0L
out[0] = s1
var carry = hcHi + c1
@@ -413,9 +413,9 @@ internal object FieldP {
hcLo = w[5] * c
hcHi = unsignedMultiplyHigh(w[5], c)
s1 = w[1] + hcLo
c1 = if (uLt(s1, w[1])) 1L else 0L
c1 = if (uLtInline(s1, w[1])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[1] = s2
carry = hcHi + c1 + c2
@@ -423,9 +423,9 @@ internal object FieldP {
hcLo = w[6] * c
hcHi = unsignedMultiplyHigh(w[6], c)
s1 = w[2] + hcLo
c1 = if (uLt(s1, w[2])) 1L else 0L
c1 = if (uLtInline(s1, w[2])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[2] = s2
carry = hcHi + c1 + c2
@@ -433,9 +433,9 @@ internal object FieldP {
hcLo = w[7] * c
hcHi = unsignedMultiplyHigh(w[7], c)
s1 = w[3] + hcLo
c1 = if (uLt(s1, w[3])) 1L else 0L
c1 = if (uLtInline(s1, w[3])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[3] = s2
carry = hcHi + c1 + c2
@@ -444,21 +444,21 @@ internal object FieldP {
val ccLo = carry * c
val ccHi = unsignedMultiplyHigh(carry, c)
s1 = out[0] + ccLo
c1 = if (uLt(s1, out[0])) 1L else 0L
c1 = if (uLtInline(s1, out[0])) 1L else 0L
out[0] = s1
// Propagate carry (unrolled, with early exit)
var prop = ccHi + c1
if (prop != 0L) {
s1 = out[1] + prop
prop = if (uLt(s1, out[1])) 1L else 0L
prop = if (uLtInline(s1, out[1])) 1L else 0L
out[1] = s1
if (prop != 0L) {
s1 = out[2] + prop
prop = if (uLt(s1, out[2])) 1L else 0L
prop = if (uLtInline(s1, out[2])) 1L else 0L
out[2] = s1
if (prop != 0L) {
s1 = out[3] + prop
prop = if (uLt(s1, out[3])) 1L else 0L
prop = if (uLtInline(s1, out[3])) 1L else 0L
out[3] = s1
}
}
@@ -466,7 +466,7 @@ internal object FieldP {
// Overflow past 256 bits: 2^256 ≡ C (mod p)
if (prop != 0L) {
s1 = out[0] + c
c1 = if (uLt(s1, out[0])) 1L else 0L
c1 = if (uLtInline(s1, out[0])) 1L else 0L
out[0] = s1
if (c1 != 0L) {
out[1]++
@@ -46,7 +46,7 @@ internal class MutablePoint(
@JvmField val y: LongArray = LongArray(4),
@JvmField val z: LongArray = LongArray(4),
) {
fun isInfinity(): Boolean = U256.isZero(z)
fun isInfinity(): Boolean = (z[0] or z[1] or z[2] or z[3]) == 0L
fun setInfinity() {
for (i in 0 until 4) {
@@ -210,9 +210,9 @@ internal object ScalarN {
0L
}
val s1 = hiTimesNC[i] + loVal
val c1 = if (uLt(s1, hiTimesNC[i])) 1L else 0L
val c1 = if (uLtInline(s1, hiTimesNC[i])) 1L else 0L
val s2 = s1 + carry
val c2 = if (uLt(s2, s1)) 1L else 0L
val c2 = if (uLtInline(s2, s1)) 1L else 0L
w[i] = s2
carry = c1 + c2
}
@@ -250,9 +250,9 @@ internal object ScalarN {
saved3
}
val s1 = loVal + hi2NC[i]
val c1 = if (uLt(s1, loVal)) 1L else 0L
val c1 = if (uLtInline(s1, loVal)) 1L else 0L
val s2 = s1 + c2
val cc = if (uLt(s2, s1)) 1L else 0L
val cc = if (uLtInline(s2, s1)) 1L else 0L
out[i] = s2
c2 = c1 + cc
}
@@ -264,13 +264,13 @@ internal object ScalarN {
val c1lo = ov * N_COMPLEMENT[1]
val c1hi = unsignedMultiplyHigh(ov, N_COMPLEMENT[1])
val s0 = out[0] + c0lo
val carry0 = if (uLt(s0, out[0])) 1L else 0L
val carry0 = if (uLtInline(s0, out[0])) 1L else 0L
out[0] = s0
val s1 = out[1] + c0hi + c1lo + carry0
val carry1 = if (uLt(s1, out[1])) 1L else 0L
val carry1 = if (uLtInline(s1, out[1])) 1L else 0L
out[1] = s1
val s2 = out[2] + c1hi + ov + carry1
val carry2 = if (uLt(s2, out[2])) 1L else 0L
val carry2 = if (uLtInline(s2, out[2])) 1L else 0L
out[2] = s2
out[3] += carry2
}
@@ -106,7 +106,7 @@ internal object U256 {
): Int {
for (i in 3 downTo 0) {
if (a[i] != b[i]) {
return if (uLt(a[i], b[i])) -1 else 1
return if (uLtInline(a[i], b[i])) -1 else 1
}
}
return 0
@@ -125,31 +125,31 @@ internal object U256 {
// Limb 0 (no carry input)
s1 = a[0] + b[0]
c1 = if (uLt(s1, a[0])) 1L else 0L
c1 = if (uLtInline(s1, a[0])) 1L else 0L
out[0] = s1
var carry = c1
// Limb 1
s1 = a[1] + b[1]
c1 = if (uLt(s1, a[1])) 1L else 0L
c1 = if (uLtInline(s1, a[1])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[1] = s2
carry = c1 + c2
// Limb 2
s1 = a[2] + b[2]
c1 = if (uLt(s1, a[2])) 1L else 0L
c1 = if (uLtInline(s1, a[2])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[2] = s2
carry = c1 + c2
// Limb 3
s1 = a[3] + b[3]
c1 = if (uLt(s1, a[3])) 1L else 0L
c1 = if (uLtInline(s1, a[3])) 1L else 0L
s2 = s1 + carry
c2 = if (uLt(s2, s1)) 1L else 0L
c2 = if (uLtInline(s2, s1)) 1L else 0L
out[3] = s2
carry = c1 + c2
@@ -169,31 +169,31 @@ internal object U256 {
// Limb 0 (no borrow input)
d1 = a[0] - b[0]
c1 = if (uLt(a[0], b[0])) 1L else 0L
c1 = if (uLtInline(a[0], b[0])) 1L else 0L
out[0] = d1
var borrow = c1
// Limb 1
d1 = a[1] - b[1]
c1 = if (uLt(a[1], b[1])) 1L else 0L
c1 = if (uLtInline(a[1], b[1])) 1L else 0L
d2 = d1 - borrow
c2 = if (uLt(d1, borrow)) 1L else 0L
c2 = if (uLtInline(d1, borrow)) 1L else 0L
out[1] = d2
borrow = c1 + c2
// Limb 2
d1 = a[2] - b[2]
c1 = if (uLt(a[2], b[2])) 1L else 0L
c1 = if (uLtInline(a[2], b[2])) 1L else 0L
d2 = d1 - borrow
c2 = if (uLt(d1, borrow)) 1L else 0L
c2 = if (uLtInline(d1, borrow)) 1L else 0L
out[2] = d2
borrow = c1 + c2
// Limb 3
d1 = a[3] - b[3]
c1 = if (uLt(a[3], b[3])) 1L else 0L
c1 = if (uLtInline(a[3], b[3])) 1L else 0L
d2 = d1 - borrow
c2 = if (uLt(d1, borrow)) 1L else 0L
c2 = if (uLtInline(d1, borrow)) 1L else 0L
out[3] = d2
borrow = c1 + c2
@@ -235,19 +235,19 @@ internal object U256 {
lo = a0 * b1
s = lo + carry
c1 = if (uLt(s, lo)) 1L else 0L
c1 = if (uLtInline(s, lo)) 1L else 0L
out[1] = s
carry = unsignedMultiplyHigh(a0, b1) + c1
lo = a0 * b2
s = lo + carry
c1 = if (uLt(s, lo)) 1L else 0L
c1 = if (uLtInline(s, lo)) 1L else 0L
out[2] = s
carry = unsignedMultiplyHigh(a0, b2) + c1
lo = a0 * b3
s = lo + carry
c1 = if (uLt(s, lo)) 1L else 0L
c1 = if (uLtInline(s, lo)) 1L else 0L
out[3] = s
out[4] = unsignedMultiplyHigh(a0, b3) + c1
@@ -256,7 +256,7 @@ internal object U256 {
hi = unsignedMultiplyHigh(a1, b0)
prev = out[1]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
out[1] = s
carry = hi + c1
@@ -264,9 +264,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a1, b1)
prev = out[2]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[2] = s
carry = hi + c1 + c2
@@ -274,9 +274,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a1, b2)
prev = out[3]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[3] = s
carry = hi + c1 + c2
@@ -284,9 +284,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a1, b3)
prev = out[4]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[4] = s
out[5] = hi + c1 + c2
@@ -295,7 +295,7 @@ internal object U256 {
hi = unsignedMultiplyHigh(a2, b0)
prev = out[2]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
out[2] = s
carry = hi + c1
@@ -303,9 +303,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a2, b1)
prev = out[3]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[3] = s
carry = hi + c1 + c2
@@ -313,9 +313,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a2, b2)
prev = out[4]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[4] = s
carry = hi + c1 + c2
@@ -323,9 +323,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a2, b3)
prev = out[5]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[5] = s
out[6] = hi + c1 + c2
@@ -334,7 +334,7 @@ internal object U256 {
hi = unsignedMultiplyHigh(a3, b0)
prev = out[3]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
out[3] = s
carry = hi + c1
@@ -342,9 +342,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a3, b1)
prev = out[4]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[4] = s
carry = hi + c1 + c2
@@ -352,9 +352,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a3, b2)
prev = out[5]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[5] = s
carry = hi + c1 + c2
@@ -362,9 +362,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a3, b3)
prev = out[6]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[6] = s
out[7] = hi + c1 + c2
}
@@ -401,13 +401,13 @@ internal object U256 {
lo = a0 * a2
s = lo + carry
c1 = if (uLt(s, lo)) 1L else 0L
c1 = if (uLtInline(s, lo)) 1L else 0L
out[2] = s
carry = unsignedMultiplyHigh(a0, a2) + c1
lo = a0 * a3
s = lo + carry
c1 = if (uLt(s, lo)) 1L else 0L
c1 = if (uLtInline(s, lo)) 1L else 0L
out[3] = s
out[4] = unsignedMultiplyHigh(a0, a3) + c1
@@ -416,7 +416,7 @@ internal object U256 {
hi = unsignedMultiplyHigh(a1, a2)
prev = out[3]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
out[3] = s
carry = hi + c1
@@ -424,9 +424,9 @@ internal object U256 {
hi = unsignedMultiplyHigh(a1, a3)
prev = out[4]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
s += carry
c2 = if (uLt(s, carry)) 1L else 0L
c2 = if (uLtInline(s, carry)) 1L else 0L
out[4] = s
out[5] = hi + c1 + c2
@@ -435,7 +435,7 @@ internal object U256 {
hi = unsignedMultiplyHigh(a2, a3)
prev = out[5]
s = prev + lo
c1 = if (uLt(s, prev)) 1L else 0L
c1 = if (uLtInline(s, prev)) 1L else 0L
out[5] = s
out[6] = hi + c1
@@ -467,7 +467,7 @@ internal object U256 {
hi = unsignedMultiplyHigh(a0, a0)
out[0] = lo // out[0] was 0
s = out[1] + hi
c1 = if (uLt(s, out[1])) 1L else 0L
c1 = if (uLtInline(s, out[1])) 1L else 0L
out[1] = s
var dCarry = c1
@@ -475,14 +475,14 @@ internal object U256 {
lo = a1 * a1
hi = unsignedMultiplyHigh(a1, a1)
s = out[2] + lo
c1 = if (uLt(s, out[2])) 1L else 0L
c1 = if (uLtInline(s, out[2])) 1L else 0L
s += dCarry
c2 = if (uLt(s, dCarry)) 1L else 0L
c2 = if (uLtInline(s, dCarry)) 1L else 0L
out[2] = s
prev = out[3] + hi
val c3a = if (uLt(prev, out[3])) 1L else 0L
val c3a = if (uLtInline(prev, out[3])) 1L else 0L
prev += c1 + c2
val c4a = if (uLt(prev, c1 + c2)) 1L else 0L
val c4a = if (uLtInline(prev, c1 + c2)) 1L else 0L
out[3] = prev
dCarry = c3a + c4a
@@ -490,14 +490,14 @@ internal object U256 {
lo = a2 * a2
hi = unsignedMultiplyHigh(a2, a2)
s = out[4] + lo
c1 = if (uLt(s, out[4])) 1L else 0L
c1 = if (uLtInline(s, out[4])) 1L else 0L
s += dCarry
c2 = if (uLt(s, dCarry)) 1L else 0L
c2 = if (uLtInline(s, dCarry)) 1L else 0L
out[4] = s
prev = out[5] + hi
val c3b = if (uLt(prev, out[5])) 1L else 0L
val c3b = if (uLtInline(prev, out[5])) 1L else 0L
prev += c1 + c2
val c4b = if (uLt(prev, c1 + c2)) 1L else 0L
val c4b = if (uLtInline(prev, c1 + c2)) 1L else 0L
out[5] = prev
dCarry = c3b + c4b
@@ -505,12 +505,12 @@ internal object U256 {
lo = a3 * a3
hi = unsignedMultiplyHigh(a3, a3)
s = out[6] + lo
c1 = if (uLt(s, out[6])) 1L else 0L
c1 = if (uLtInline(s, out[6])) 1L else 0L
s += dCarry
c2 = if (uLt(s, dCarry)) 1L else 0L
c2 = if (uLtInline(s, dCarry)) 1L else 0L
out[6] = s
prev = out[7] + hi
val c3c = if (uLt(prev, out[7])) 1L else 0L
val c3c = if (uLtInline(prev, out[7])) 1L else 0L
prev += c1 + c2
out[7] = prev
}