feat: migrate secp256k1 from LongArray to Fe4/Wide8 structs

Full migration of the secp256k1 library from LongArray(4)/LongArray(8)
to Fe4/Wide8 struct types with @JvmField named Long fields. This
eliminates all array bounds checks from the hot path.

Files migrated (13 source + 7 test + 2 benchmark):
  - U256.kt, FieldP.kt, ScalarN.kt, Glv.kt, ECPoint.kt
  - FieldMulPlatform.kt (expect + 3 actuals), FieldMulFused.kt
  - PointTypes.kt (MutablePoint, AffinePoint, PointScratch)
  - KeyCodec.kt, Secp256k1.kt
  - All test files and benchmarks

Bytecode impact:
  Before: 464 laload/lastore (bounds-checked) in core arithmetic
  After:  0 laload/lastore, all getfield/putfield (no checks)

The public API (Secp256k1 object) is unchanged - it still accepts
and returns ByteArray. Fe4 conversion happens at the API boundary
via U256.fromBytes()/U256.toBytes().

All secp256k1 unit tests pass on JVM.

https://claude.ai/code/session_01Sxi6Gpxbstuj3Y8TBY7XrU
This commit is contained in:
Claude
2026-04-10 03:30:53 +00:00
parent ea8b693785
commit a2ba64baba
23 changed files with 1391 additions and 1925 deletions
@@ -43,18 +43,18 @@ package com.vitorpamplona.quartz.utils.secp256k1
* - The fused function stays within ART's inlining budget
*/
internal actual fun fieldMulReduce(
out: LongArray,
a: LongArray,
b: LongArray,
w: LongArray,
out: Fe4,
a: Fe4,
b: Fe4,
w: Wide8,
) {
fieldMulReduceWith(out, a, b, w) { x, y -> unsignedMultiplyHighFallback(x, y) }
}
internal actual fun fieldSqrReduce(
out: LongArray,
a: LongArray,
w: LongArray,
out: Fe4,
a: Fe4,
w: Wide8,
) {
fieldSqrReduceWith(out, a, w) { x, y -> unsignedMultiplyHighFallback(x, y) }
}