154 Commits
Author SHA1 Message Date
Claude ae0b70728e Merge remote-tracking branch 'origin/main' into claude/beautiful-brahmagupta-17clq5
# Conflicts:
#	commons/build.gradle.kts
#	quartz/build.gradle.kts
2026-09-12 23:11:15 +00:00
Claude a87222c51f refactor: split Compose UI out of commons into a new commonsUI module
`:commons` is on the CLI classpath, yet it declared Compose UI, Coil, Compose
resources, markdown and desktop Compose as dependencies, dragging ~40 MB of
UI/Skiko jars into every `amy` distribution. This moves every
Compose-dependent file into a new KMP module, `:commonsUI`, that
`api`-depends on `:commons`; `:commons` keeps only the Compose runtime
(stability annotations + snapshot state) and lifecycle-viewmodel.

Files keep their `com.vitorpamplona.amethyst.commons.*` packages, so the split
is a build-graph boundary and no consumer import changed. 236 files were
`git mv`'d (composables, icons, robohash, theme, Coil fetchers, the
`@Composable` relay-client entry points, `composeResources`, and the tests
that exercise them). Two headless files needed surgery instead of a move:
`GalleryParser` lost a vestigial foundation `@OptIn`, and the
`LocalPrivacyLockState`/`lockStateFor` CompositionLocal accessor moved out of
`PrivacyLockState` into its own commonsUI file. The feed DAL under `ui/feeds`
and `ui/note/ParentNote`+`ReplyContext` stay in `commons` because ViewModels
depend on them.

`amethyst`, `desktopApp`, `nappletHost` (NappletWebContract serves the shell
from composeResources) and `benchmark` now depend on `:commonsUI`; `cli`,
`geode` and `marmotBench` do not. commons' androidMain gains an explicit
androidx.core KTX dep it previously got transitively through Compose UI.

CI, crowdin, the icon-font tools and the escaping hook point at the new
composeResources location; CLAUDE.md, commons/ARCHITECTURE.md, a new
commonsUI/ARCHITECTURE.md, CONTRIBUTING, BUILDING and the affected skills
document the boundary. A plan doc under commons/plans records the
classification method and follow-ups.

Verified: JVM compiles for commons, commonsUI, cli, desktopApp; Android debug
compiles for nappletHost and amethyst; commons/commonsUI/cli JVM test suites;
both verifyKmpPurity gates; the cli runtime classpath no longer resolves
Compose UI, material3, Skiko or Coil.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N56KzPSYiN5edMRamvKEgD
2026-09-12 16:26:59 +00:00
Claude d63e14bb36 fix: clear the remaining compiler warnings in amethyst and desktopApp
Second half of the warning sweep, covering :amethyst (both flavors, all
build types, unit + instrumented tests), :desktopApp and :benchmark:

- GitReplyEvent (NIP-34 kind 1622) is deprecated in favour of NIP-22
  comments, but events already on relays still arrive and still have to be
  routed, rendered and surfaced. @Suppress("DEPRECATION") with that reason
  at the five production sites and the coverage test that pins them.
- The four instrumented Compose tests move to
  androidx.compose.ui.test.junit4.v2.createComposeRule. The v2 factory
  returns the same ComposeContentTestRule, so mainClock, setContent and the
  node assertions are unchanged; only the effect dispatcher differs.
- RelayAuthPromptBusTest / RelayAuthSessionGrantsTest: @OptIn for the
  ExperimentalCoroutinesApi members (testScheduler.currentTime, runCurrent)
  they already use, matching the annotation the file's other tests carry.
- MarmotFileUploader: drop a nullable alias of a non-null cipher, left
  behind when the v2 reference stopped being conditional.
- LocalCacheSearchParityTest: hoist the Json format out of the loader.
- LivesSection: FlowRowOverflow and FlowRow's overflow parameter are
  deprecated; the non-deprecated overload already clips beyond maxLines.
- HexBenchmark: drop a bare `null` expression statement from the measured
  lambda.

Also fixes :commons:compileCommonMainKotlinMetadata, which did not compile
at all: shared code called BigDecimal.toLong(), which resolves in every
platform compilation (every actual is a Number) but not in the common
metadata one, where only the expect class's own members are visible.
`expect class BigDecimal : Number` cannot work — java.math.BigDecimal leaves
toByte()/toShort() abstract, so the JVM typealias fails the expect/actual
modality check — so the conversion is a top-level expect/actual extension
instead, with actuals next to each BigDecimal actual.

Verified warning- and error-free across the jvm, android (play/fdroid ×
debug/release/benchmark), linuxX64, and the common/jvmAndroid/native/apple/
ios metadata compilations. The apple actuals are checked by
compileAppleMainKotlinMetadata, which runs the frontend against the Apple
klibs without needing a macOS host.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0123kXtseu4X18hL3GMDcdER
2026-09-12 16:17:00 +00:00
Claude 729fb1bc17 perf(quartz): hoist lookup tables in Hex.decode/encode/isEqual/readLong; bench new codecs
javap showed the hexToByte/byteToHex field re-loaded on every use inside
these methods (16 times per readLong call) — the JVM/ART doesn't reliably
prove the load loop-invariant. Hoisting it into a local measured ~25%
faster for decode and ~10% for isEqual and readLong on the JVM
(4096 random 32-byte ids, best-of-150 rounds, 3 repeats); encode was
neutral on HotSpot but is hoisted too since ART is historically worse
at this (see the internalIsHex comment).

Branchless variants of isHex/isHex64 were also measured and were a
wash-to-slightly-worse than the branchy early-exit versions on valid
input, so those keep their current implementations.

Also adds the new exact-size codecs to the on-device HexBenchmark
(decode64, decode64OrNull, encode64, decode128, encode128, toLong256,
and the old isHex64+decode two-pass for comparison) so ART numbers can
be collected with the existing benchmark harness.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hwv6XwT9mwGUQc57zH4ky4
2026-08-01 01:47:01 +00:00
davotoula 385f0bd459 fix(quartz): rename gzip test corpus to .json.gz to clear Sonar encoding warning 2026-07-01 10:54:15 +02:00
Claude 59fd1f2244 build: use directories.add for benchmark androidTest resources
srcDirs(vararg) on AGP 9 source-set Resources is deprecated; switch to
the directories MutableSet API. Preserves the original behavior of
including quartz/src/androidDeviceTest/resources in :benchmark's
androidTest java resources (verified bip39.vectors.json shows up in
processBenchmarkAndroidTestJavaRes output).
2026-05-20 15:56:53 +00:00
Claude ebfd066d5c build: convert remaining .gradle files to Kotlin DSL
Converts the last four Groovy build scripts to Kotlin DSL so the entire
build is consistent with the rest of the modules (commons, quartz, etc.).

- settings.gradle -> settings.gradle.kts
- build.gradle (root) -> build.gradle.kts
- amethyst/build.gradle -> amethyst/build.gradle.kts
- benchmark/build.gradle -> benchmark/build.gradle.kts

Notes:
- Switched the per-subproject spotless format from groovyGradle to
  kotlinGradle now that the only gradle scripts are .gradle.kts.
- benchmark module: moved targetSdk from defaultConfig to testOptions —
  AGP 9 removed targetSdk from library defaultConfig.
- Reimplemented getCurrentBranch() with ProcessBuilder (Groovy's
  String.execute() isn't available in Kotlin DSL).
2026-05-20 14:17:47 +00:00
Claude 2e8bf0d45d build: remove unused :ammolite module
The :ammolite module contained no production Kotlin/Java sources (just
a manifest, build.gradle, and proguard stubs) and no module in the
codebase imports com.vitorpamplona.ammolite.*.

Removes:
- ammolite/ directory (5 files)
- :ammolite project include in settings.gradle
- implementation project(':ammolite') from :amethyst
- androidTestImplementation project(':ammolite') from :benchmark
- :ammolite:testDebugUnitTest from CI workflow and pre-push hook
- -keep class com.vitorpamplona.ammolite.** rules from
  :amethyst, :commons, and :desktopApp proguard files
- Stale references in CONTRIBUTING.md, CLAUDE.md, and the
  gradle-expert skill dependency-graph doc

Small build-graph win: one fewer module to configure, compile, lint,
and spotless-check on every build, and one fewer unit-test target in
both CI and the local pre-push hook.
2026-05-16 14:40:03 +00:00
Vitor Pamplona 3751d6dc28 Fixes warnings 2026-05-12 19:27:12 -04:00
Claude 2ad1a48123 refactor(quartz): migrate in-tree C secp256k1 to libschnorr256k1-kmp
The custom C secp256k1 implementation under quartz/src/main/c/ was never
wired into Gradle (no externalNativeBuild block) and only existed for the
3-way benchmark + cross-validation test against ACINQ on JVM/Android.
The C library has been split out to vitorpamplona/libschnorr256k1{,-kmp},
so the in-repo copy is dead weight.

This change replaces it with the published Maven Central artifact
`com.vitorpamplona:schnorr256k1-kmp:1.0.0`, scoped to test/benchmark
configurations only — production crypto continues to use ACINQ
secp256k1-kmp on JVM/Android and the pure-Kotlin Secp256k1 on native.

The Android AAR ships libschnorr256k1_jni.so for arm64-v8a and x86_64,
so the Android benchmark now exercises the C row automatically (no more
manual build_android.sh). On JVM the .so still has to be installed by the
developer; the cross-validation test and triple-benchmark gracefully skip
the C row when System.loadLibrary fails, matching prior behavior.

Verified on JVM: all 13 secp256k1 jvmTest classes pass (188 tests), and
ACINQ vs pure-Kotlin benchmark numbers match the documented baseline
within sandbox noise (verifySchnorr ~15k ops/s, signSchnorr cached
~33k ops/s, pubkeyCreate+Compress ~36k ops/s).

Removes ~5,100 LOC: quartz/src/main/c/ (4,500), Secp256k1InstanceC.*
expect/actual shim (560), Secp256k1C JNI declaration object.

https://claude.ai/code/session_01KnvpK2amcVZKfFiZJvHjVe
2026-04-28 15:36:25 +00:00
Claude 63da850e3b perf(thumbhash): cache cosine tables and flatten hot loop in decoder
The reference port recomputed the inverse DCT cosine tables once per output
pixel — for a 32x24 decode that's ~43k redundant cos() calls. This change
lifts the tables out of the inner loop and caches them across decodes
keyed by (size, componentCount) so subsequent placeholders at the same
target size skip cosine evaluation entirely.

Additional wins:
- AC coefficients unpack into pre-sized DoubleArrays (no ArrayList<Double>
  boxing, no post-hoc copy)
- truncated hashes are rejected up-front via a single length check instead
  of mid-stream
- LPQA -> sRGB uses an inline branch clamp instead of a
  min/max/round/coerceIn chain

Tests: 12 unit tests cover determinism across repeated decodes, cache
clearing, alpha preservation, aspect-ratio preservation both directions,
average-color drift bounds, truncated input rejection, and round-tripping
base64 vs. raw bytes. All green.

Bench: new ThumbHashBenchmark exercises opaque decode, alpha decode,
warm- and cold-cache decode, aspect-ratio probe, and the full
decodeKeepAspectRatio pipeline so the perf delta is visible on device.
2026-04-20 00:33:26 +00:00
Claude 944562ddc8 feat: add SHA-256 benchmark comparing Android native vs our C vs Kotlin
Three SHA-256 implementations benchmarked on the same phone:
- sha256Android: Android's MessageDigest (BoringSSL + ARM64 CE hardware)
- sha256OurC: Our C SHA-256 (ARM64 CE hardware via JNI)
- sha256Kotlin: Kotlin's sha256 (platform MessageDigest on Android)

Also add nativeSha256 JNI method to expose our hardware SHA-256.

Why our C matches ACINQ on ARM64 despite different architectures:
- Our 4x64: 16 MUL+UMULH pairs per field mul
- ACINQ 5x52: 25 MUL+UMULH pairs per field mul
- We save 9 multiply pairs (~27ns on Cortex-X3) per fe_mul
- ACINQ saves ~6 normalizations with lazy reduction (~6ns)
- Net advantage: ~21ns per mul × 500 muls/verify > 0
- Plus our SHA-256 uses hardware CE, ACINQ's is software

https://claude.ai/code/session_011KVZhDcV2G7idNWEBz12GY
2026-04-11 15:02:27 +00:00
Claude 29b678ab14 feat: add custom C secp256k1 implementation for maximum platform performance
Add a complete C implementation of secp256k1 elliptic curve operations
alongside the existing Kotlin implementation, enabling direct comparison
and extraction of maximum performance from each platform (ARM64, x86_64).

C Implementation (quartz/src/main/c/secp256k1/):
- field.h/c: 5x52-bit limb field arithmetic with __int128 support and
  lazy reduction (12-bit headroom per limb vs Kotlin's fully-packed 4x64)
- scalar.h/c: Scalar mod n arithmetic, GLV decomposition, wNAF encoding
- point.h/c: Jacobian point operations (3M+4S double, 8M+3S mixed add),
  GLV+wNAF scalar multiplication, Strauss/Shamir dual scalar multiply,
  Montgomery batch-to-affine, precomputed G tables (wNAF-12)
- schnorr.c: BIP-340 Schnorr sign/verify/verifyFast/verifyBatch with
  pubkey decompression cache and precomputed tag hash prefixes
- sha256.c: Self-contained SHA-256 for BIP-340 tagged hashes
- secp256k1_c.h: Public API matching the Kotlin Secp256k1 object
- jni_bridge.c: JNI bridge for JVM/Android integration
- benchmark.c: Standalone C benchmark (cmake build)
- CMakeLists.txt: Build system with ARM64/x86_64 optimization flags

Kotlin Integration:
- Secp256k1InstanceC: expect/actual wrapper (commonMain/jvmMain/androidMain/nativeMain)
- Secp256k1C: JVM JNI binding class
- Secp256k1TripleBenchmark: Three-way JVM benchmark (ACINQ vs Kotlin vs Custom C)
- Secp256k1CBenchmark: Android benchmark for the C implementation

Current status: sign works correctly (verified against BIP-340 test vectors),
verify path needs ecmult_double_g debugging (GLV wNAF-12 table issue). The
comb table for ecmult_gen also needs fixing (currently falls back to GLV+wNAF).
Field arithmetic is fully verified: 5x52 limbs with R=0x1000003D10 fold.

https://claude.ai/code/session_011KVZhDcV2G7idNWEBz12GY
2026-04-11 02:36:58 +00:00
Vitor Pamplona a9e59d817f Improves benchmark names, options and formatting 2026-04-09 19:25:47 -04:00
Claude da64a4a4d3 fix: align all 3 benchmarks to identical operation set
All 3 platform benchmarks (Android, JVM, K/Native) now measure the
same core operations for cross-platform comparability:

  verifySchnorr        — strict BIP-340
  verifySchnorrFast    — Nostr x-check only (no y-parity inversion)
  signSchnorr          — derives pubkey each time
  signSchnorr(cached)  — pre-computed x-only pubkey
  compressedPubKeyFor  — create + compress
  secKeyVerify         — key validation
  privKeyTweakAdd      — BIP-32 key derivation
  ecdhXOnly            — Nostr ECDH (NIP-04/44)
  batch verify (8, 16) — same-pubkey batch

Changes:
- Android: added signSchnorrCachedPkOurs, ecdhXOnly/ecdhXOnlyOurs
  (replaced pubKeyTweakMulCompact naming)
- JVM: removed pubkeyCreate and pubKeyCompress (subsets of
  compressedPubKeyFor, not measured on other platforms)
- K/Native: added verifySchnorrFast

K/Native retains field micro-benchmarks (FieldP.mul/sqr/add/sub/inv,
unsignedMultiplyHigh, uLt) as a K/N-specific diagnostic tool.

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 15:02:39 +00:00
Claude b3206b8e48 feat: add batch verify to Android benchmark + expose in Secp256k1InstanceOurs
Add verifySchnorrBatch to Secp256k1InstanceOurs wrapper and add
Android benchmark tests for batch(8) and batch(16).

To get per-event cost: ns/op ÷ batchSize.
JVM benchmark showed 4-7× speedup over individual verify.
Android results TBD.

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 14:45:14 +00:00
Claude fbcd0d6326 feat: expose verifySchnorrFast in Secp256k1InstanceOurs + Android benchmark
Wire verifySchnorrFast (x-check only, no y-parity inversion) into:
- Secp256k1InstanceOurs wrapper for app-level usage
- Android benchmark as verifySchnorrFastOurs for Pixel 8 measurement

Expected: ~15% faster than verifySchnorrOurs (~100μs vs ~120μs on Pixel 8)

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 12:33:13 +00:00
Claude 0c27ed89bc fix: align all 3 secp256k1 benchmarks for fairness and comparability
JVM benchmark fixes:
- signSchnorr(cached pk): document that native baseline still derives
  pubkey (apples-to-oranges by design — shows what caching enables)
- privKeyTweakAdd: document .copyOf() penalty on native side (ACINQ
  wrapper mutates input, requiring defensive copy)
- Remove duplicate tweakMulCompact test (redundant with ecdhXOnly)
- Add cache-warming note to benchmark KDoc
- Change output "slower" → neutral "x" (0.7x isn't "slower")

Android benchmark fixes:
- Remove misnamed pubKeyCompressOurs (was identical to compressedPubKeyForOurs)
- Remove duplicate pubKeyCompress (was also doing create+compress)
- Clean up structure: matched Native/Ours pairs with clear section headers
- Add cache-warming note to benchmark KDoc
- Standardize test data comment for cross-platform comparability

K/Native benchmark fixes:
- Fix DCE risk in micro-benchmarks: use result-dependent chains
  (out→out for field ops, xor hiSink for multiplyHigh) so LLVM can't
  hoist constant computations out of the loop
- Add batch verify (was missing — JVM had it, Android/K/N didn't)
- Add -opt documentation warning in KDoc
- Remove unused pubkeyCreate/pubKeyCompress standalone benchmarks
  (compressedPubKeyFor already covers create+compress)
- Extract printResults helper to reduce duplication

All 3 benchmarks now:
- Use the same test data (same hex keys across JVM/Android/K/N)
- Measure the same core operations (verify, sign, compressedPubKeyFor,
  secKeyVerify, privKeyTweakAdd, ecdhXOnly/pubKeyTweakMulCompact)
- Document cache-warming effects in their KDoc
- Include batch verify (JVM + K/N; Android uses framework-managed tests)

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 01:58:54 +00:00
Vitor Pamplona 9b4d6247f0 Adds an android benchmark comparison for the new Secp 2026-04-06 18:00:46 -04:00
Claude 78d8914ee1 test: add Android microbenchmark for secp256k1 operations
Creates Secp256k1Benchmark.kt in the benchmark module using AndroidX
Benchmark (Jetpack Microbenchmark) to measure all secp256k1 operations
on real Android hardware/emulator with proper warmup and statistics.

Benchmarks: verifySchnorr, signSchnorr, compressedPubKeyFor,
secKeyVerify, pubKeyCompress, privateKeyAdd, pubKeyTweakMulCompact.

Run with: ./gradlew :benchmark:connectedAndroidTest

The existing SignVerifyBenchmark already tests sign/verify through
Nip01Crypto, but this new benchmark tests the Secp256k1Instance
operations directly, matching the JVM benchmark for comparison.

https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg
2026-04-05 20:32:56 +00:00
davotoulaandClaude Opus 4.6 c40c1ed383 perf: convert remaining 12 interpolated log calls to lambda overloads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:07:34 +02:00
Vitor Pamplona 75a8e461ad 20x Faster Rfc3986Normalizer and way less objects being created. 2026-03-26 19:04:18 -04:00
Vitor Pamplona 7c8d44559e Benchmark for the new Rfc3986 Normalizer 2026-03-26 17:32:07 -04:00
Vitor Pamplona e2ac534be0 spotless 2026-03-25 12:55:31 -04:00
Vitor PamplonaandGitHub d84d146981 Merge branch 'main' into claude/remove-libsodium-dependency-DjtWa 2026-03-25 11:24:55 -04:00
Vitor Pamplona 617db3613f Re-enables benchmark with native android ChaCha functions 2026-03-25 11:17:17 -04:00
Claude d586a0dc25 feat: replace libsodium with pure Kotlin ChaCha20/Poly1305 implementation
Remove LazySodium/JNA/libsodium native dependencies and replace with
pure Kotlin implementations of ChaCha20, HChaCha20, XChaCha20,
Poly1305 MAC, and XChaCha20-Poly1305 AEAD. This eliminates platform-
specific native binaries while maintaining full NIP-44 compatibility.

- Add ChaCha20Core with RFC 8439 block function, IETF stream XOR,
  HChaCha20, and XChaCha20
- Add Poly1305 MAC (RFC 8439 §2.5)
- Add XChaCha20Poly1305 AEAD encrypt/decrypt
- Convert LibSodiumInstance from expect/actual to commonMain object
- Delete platform-specific LibSodiumInstance actuals (android/jvm/ios)
- Remove iOS native interop (cinterop, linker opts, .a libraries)
- Remove lazysodium-java, lazysodium-android, JNA from build deps
- Clean up ProGuard rules (remove JNA/LazySodium keep rules)
- Add RFC 8439 + libsodium test vectors for ChaCha20 and XChaCha20
- Update benchmark to use simplified ChaCha20 API

https://claude.ai/code/session_01YHBwqnb3Z7Q7PX31tJ2G3i
2026-03-23 17:40:29 +00:00
Vitor Pamplona d431b12f94 Migrates EventStore from Android's SQLLite to KMP
Fixes testing of libsodium between java and android
2026-03-20 16:00:17 -04:00
Vitor Pamplona f4d401bc56 Switches to our own version of the Url Detector 2026-03-06 10:58:59 -05:00
Vitor Pamplona 64c8c0edfd Improves the name of the NIP01 Crypto object 2026-02-18 11:29:56 -05:00
Vitor Pamplona c755908db5 Removes string-concat compiler argument since it is not supported anymore 2026-02-17 19:02:53 -05:00
Vitor Pamplona cf7bdef028 Adds missing actual implementations on iOS 2026-02-17 19:00:24 -05:00
Vitor Pamplona eb66182211 - Updates several libraries
- Reformats code to the newest Klint
- Fixes isEmpty bug on Filters
2026-02-09 14:06:07 -05:00
Vitor Pamplona 710f15f790 - Fixes copyright using KDoc patterns instead of simpler comments
- Moves spotless and git-hooks to hidden folders
2026-02-09 13:06:41 -05:00
Vitor Pamplona 6125394354 Migrates to AGP 9 2026-02-08 16:33:39 -05:00
Vitor Pamplona 7bc7265757 Refactors the old NIP-05 code on Quartz
New Caching system for User metadata
New Caching system for NIP-05 verifications
2026-02-04 14:31:30 -05:00
Vitor Pamplona aa2f969be6 Faster event serializer -> sha256 -> id comparison without creating intermediary buffers. 2025-12-23 09:39:30 -05:00
Vitor Pamplona 79d6745ee6 Adds faster parsers for Messages and Commands
Unwraps inline runCatching because it seems faster for some reason.
2025-12-22 14:52:02 -05:00
Vitor Pamplona eefca1e3f4 Removes unnecessary tests 2025-12-22 08:11:55 -05:00
Vitor Pamplona 8cbc5f1e93 Faster Array Deserializer 2025-12-19 18:57:12 -05:00
Vitor Pamplona 664f0d0d59 Adds a Benchmark to simulate a real use on storage operators 2025-12-19 17:29:23 -05:00
Vitor Pamplona 8d15f0478f Faster MurMur hash for 64bit results. 2025-12-18 17:30:53 -05:00
Vitor Pamplona 7840bc3318 Uses in memory DB because that's where the performance hits 2025-12-18 11:57:38 -05:00
Vitor Pamplona 5df019e485 adds kotlin ktx to benchmark 2025-12-18 09:21:40 -05:00
Vitor Pamplona 625a12f4e2 Better way to clear the test db 2025-12-16 18:03:50 -05:00
Vitor Pamplona 0fb64c5ff7 Fixes new generics on the benchmark classes 2025-12-16 16:57:02 -05:00
Vitor Pamplona 83d14bd0e3 Minor adjustments and new benchmarks 2025-12-12 19:51:41 -05:00
Vitor Pamplona 95723479d6 Adds MurMur3128bits for x64 2025-12-12 16:54:34 -05:00
Vitor Pamplona 3eb662851b Adds a flatten to set utility 2025-10-31 18:36:05 -04:00
Vitor Pamplona bf664ea0c5 Avoids interning of large strings and objects where the duplication is not common 2025-10-28 12:18:19 -04:00