From c7025356bcabd90bcff35c40a4579c3c5177015b Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Wed, 19 Nov 2025 10:08:01 +0000 Subject: [PATCH 01/15] Refactor code for clarity and consistency, including updates to comments, method references, and variable declarations --- pom.xml | 2 +- .../openhft/chronicle/algo/MemoryUnit.java | 2 +- .../bitset/SingleThreadedFlatBitSetFrame.java | 4 +- .../algo/bytes/HotSpotStringAccessor.java | 2 +- .../chronicle/algo/hashing/CityHash_1_1.java | 34 ++- .../algo/hashing/LongHashFunction.java | 24 +-- .../chronicle/algo/hashing/MurmurHash_3.java | 196 +++++++----------- .../chronicle/algo/hashing/XxHash_r39.java | 17 +- .../algo/locks/TryAcquireOperations.java | 81 +------- .../chronicle/algo/bitset/BitSetTest.java | 5 +- .../bitset/ConcurrentFlatBitSetFrameTest.java | 4 +- .../algo/bitset/DirectBitSetTest.java | 50 ++--- .../algo/bitset/FlatBitSetAlgorithmTest.java | 5 +- .../algo/bitset/ReusableBitSetTest.java | 12 +- .../chronicle/algo/bytes/AccessTest.java | 18 +- .../algo/bytes/AccessUtilitiesTest.java | 23 +- .../algo/bytes/ByteBufferAccessTest.java | 5 +- .../algo/bytes/CharSequenceAccessTest.java | 5 +- .../algo/bytes/RandomDataInputAccessTest.java | 4 +- .../bytes/RandomDataOutputAccessTest.java | 8 +- .../chronicle/algo/bytes/WriteAccessTest.java | 2 +- .../algo/hashing/City64MoreTest.java | 12 +- .../algo/hashing/City64_1_1_Test.java | 40 ++-- .../algo/hashing/HashTestSupport.java | 4 +- .../algo/hashing/MurmurHash3MoreTest.java | 12 +- .../algo/hashing/MurmurHash3Test.java | 4 +- .../algo/hashing/XxHash_r39_Test.java | 7 +- .../algo/locks/LockingStrategyTest.java | 4 +- ...ReadWriteWithWaitsLockingStrategyTest.java | 2 - 29 files changed, 236 insertions(+), 352 deletions(-) diff --git a/pom.xml b/pom.xml index 8bf112d6..d6c61d45 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ net.openhft third-party-bom - 3.27ea5 + 3.27ea7 pom import diff --git a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java index aa3ba4d9..ef06d4df 100644 --- a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java +++ b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java @@ -805,7 +805,7 @@ static long y(long amount, long align) { static long ise(MemoryUnit unitToAlign, MemoryUnit alignmentUnit) { throw new IllegalStateException("Couldn't align " + unitToAlign + " by " + alignmentUnit); } -// To maintain full signature compatibility with 1.5, and to improve the + // To maintain full signature compatibility with 1.5, and to improve the // clarity of the generated javadoc (see 6287639: Abstract methods in // enum classes should not be listed as abstract), method convert // etc. are not declared abstract but otherwise act as abstract methods. diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java b/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java index 1bfb7dc8..ea522022 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java @@ -54,8 +54,8 @@ static long higherBitsIncludingThis(long bitIndex) { static long lowerBitsIncludingThis(long bitIndex) { return ALL_ONES >>> ~bitIndex; } -// conversions + // conversions static long higherBitsExcludingThis(long bitIndex) { return ~(ALL_ONES >>> ~bitIndex); } @@ -84,8 +84,8 @@ static void checkNumberOfBits(int numberOfBits) { if (numberOfBits <= 0 || numberOfBits > 64) throw new IllegalArgumentException("Illegal number of bits: " + numberOfBits); } -// checks + // checks static boolean checkNotFoundIndex(long fromIndex) { if (fromIndex < 0) { if (fromIndex == NOT_FOUND) diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/HotSpotStringAccessor.java b/src/main/java/net/openhft/chronicle/algo/bytes/HotSpotStringAccessor.java index 67147e5b..579dfeab 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/HotSpotStringAccessor.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/HotSpotStringAccessor.java @@ -57,7 +57,7 @@ public ReadAccess access() { @SuppressWarnings("unchecked") @Override public T handle(String source) { - return (T) MEMORY.getObject(source, valueOffset); + return MEMORY.getObject(source, valueOffset); } /** diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java b/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java index a0e5976b..33980a07 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java @@ -19,10 +19,6 @@ class CityHash_1_1 { // Singleton instance of CityHash_1_1 private static final CityHash_1_1 INSTANCE = new CityHash_1_1(); - // Singleton instance with native byte order - private static final CityHash_1_1 NATIVE_CITY = NATIVE_LITTLE_ENDIAN ? - CityHash_1_1.INSTANCE : BigEndian.INSTANCE; - // Constants used in the hashing algorithm private static final long K0 = 0xc3a5c85c97cb3127L; private static final long K1 = 0xb492b66fbe98f273L; @@ -33,6 +29,10 @@ class CityHash_1_1 { private CityHash_1_1() { } + private static CityHash_1_1 nativeCity() { + return NATIVE_LITTLE_ENDIAN ? INSTANCE : BigEndian.INSTANCE; + } + /** * Applies a bitwise shift and mix operation to the given value. * @@ -296,13 +296,9 @@ long cityHash64(ReadAccess access, T in, long off, long len) { } else if (len <= 64L) { return hashLen33To64(access, in, off, len); } - long x = fetch64(access, in, off + len - 40L); - long y = fetch64(access, in, off + len - 16L) + fetch64(access, in, off + len - 56L); long z = hashLen16(fetch64(access, in, off + len - 48L) + len, fetch64(access, in, off + len - 24L)); - long vFirst, vSecond, wFirst, wSecond; - // This and following 3 blocks are produced by a single-click inline-function refactoring. // IntelliJ IDEA ftw // WeakHashLen32WithSeeds @@ -314,12 +310,12 @@ long cityHash64(ReadAccess access, T in, long off, long len) { long z4 = fetch64(access, in, off + len - 64L + 24L); a3 += w4; b3 = rotateRight(b3 + a3 + z4, 21); - long c3 = a3; + final long c3 = a3; a3 += x4 + y4; b3 += rotateRight(a3, 44); - vFirst = a3 + z4; - vSecond = b3 + c3; + long x = fetch64(access, in, off + len - 40L); + long y = fetch64(access, in, off + len - 16L) + fetch64(access, in, off + len - 56L); // WeakHashLen32WithSeeds long a2 = y + K1; long b2 = x; @@ -332,8 +328,10 @@ long cityHash64(ReadAccess access, T in, long off, long len) { long c2 = a2; a2 += x3 + y3; b2 += rotateRight(a2, 44); - wFirst = a2 + z3; - wSecond = b2 + c2; + long wSecond = b2 + c2; + long wFirst = a2 + z3; + long vSecond = b3 + c3; + long vFirst = a3 + z4; x = x * K1 + fetch64(access, in, off); @@ -357,8 +355,8 @@ long cityHash64(ReadAccess access, T in, long off, long len) { long c1 = a1; a1 += x2 + y2; b1 += rotateRight(a1, 44); - vFirst = a1 + z2; vSecond = b1 + c1; + vFirst = a1 + z2; // WeakHashLen32WithSeeds long a = z + wSecond; @@ -372,8 +370,8 @@ long cityHash64(ReadAccess access, T in, long off, long len) { long c = a; a += x1 + y1; b += rotateRight(a, 44); - wFirst = a + z1; wSecond = b + c; + wFirst = a + z1; long tmp = x; x = z; @@ -434,14 +432,14 @@ private Object readResolve() { @Override public long hashLong(long input) { - input = NATIVE_CITY.toLittleEndian(input); + input = nativeCity().toLittleEndian(input); long hash = hash8To16Bytes(8L, input, input); return finalizeHash(hash); } @Override public long hashInt(int input) { - input = NATIVE_CITY.toLittleEndian(input); + input = nativeCity().toLittleEndian(input); long unsignedInt = Primitives.unsignedInt(input); long hash = hash4To7Bytes(4L, unsignedInt, unsignedInt); return finalizeHash(hash); @@ -496,7 +494,7 @@ private static class AsLongHashFunctionSeeded extends AsLongHashFunction { private static final long serialVersionUID = 0L; private final long seed0, seed1; - private final transient long voidHash; + private final long voidHash; private AsLongHashFunctionSeeded(long seed0, long seed1) { this.seed0 = seed0; diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/LongHashFunction.java b/src/main/java/net/openhft/chronicle/algo/hashing/LongHashFunction.java index d96ccfb1..d75ceb28 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/LongHashFunction.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/LongHashFunction.java @@ -262,7 +262,7 @@ public long hashBoolean(boolean input) { /** * Shortcut for {@link #hashBooleans(boolean[], int, int) hashBooleans(input, 0, input.length)}. */ - public long hashBooleans(@NotNull boolean[] input) { + public long hashBooleans(boolean @NotNull [] input) { return hashBooleans(input, 0, input.length); } @@ -276,7 +276,7 @@ public long hashBooleans(@NotNull boolean[] input) { * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} * or {@code len < 0} */ - public long hashBooleans(@NotNull boolean[] input, int off, int len) { + public long hashBooleans(boolean @NotNull [] input, int off, int len) { checkArrayOffs(input.length, off, len); return hash(booleanArrayAccessor(), input, off, len); } @@ -284,7 +284,7 @@ public long hashBooleans(@NotNull boolean[] input, int off, int len) { /** * Shortcut for {@link #hashBytes(byte[], int, int) hashBytes(input, 0, input.length)}. */ - public long hashBytes(@NotNull byte[] input) { + public long hashBytes(byte @NotNull [] input) { return hashBytes(input, 0, input.length); } @@ -298,7 +298,7 @@ public long hashBytes(@NotNull byte[] input) { * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} * or {@code len < 0} */ - public long hashBytes(@NotNull byte[] input, int off, int len) { + public long hashBytes(byte @NotNull [] input, int off, int len) { checkArrayOffs(input.length, off, len); return hash(byteArrayAccessor(), input, off, len); } @@ -343,7 +343,7 @@ public long hashMemory(long address, long len) { /** * Shortcut for {@link #hashChars(char[], int, int) hashChars(input, 0, input.length)}. */ - public long hashChars(@NotNull char[] input) { + public long hashChars(char @NotNull [] input) { return hashChars(input, 0, input.length); } @@ -359,7 +359,7 @@ public long hashChars(@NotNull char[] input) { * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} * or {@code len < 0} */ - public long hashChars(@NotNull char[] input, int off, int len) { + public long hashChars(char @NotNull [] input, int off, int len) { checkArrayOffs(input.length, off, len); return hash(charArrayAccessor(), input, off, len); } @@ -423,7 +423,7 @@ long hashNativeChars(CharSequence input, int off, int len) { /** * Shortcut for {@link #hashShorts(short[], int, int) hashShorts(input, 0, input.length)}. */ - public long hashShorts(@NotNull short[] input) { + public long hashShorts(short @NotNull [] input) { return hashShorts(input, 0, input.length); } @@ -439,7 +439,7 @@ public long hashShorts(@NotNull short[] input) { * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} * or {@code len < 0} */ - public long hashShorts(@NotNull short[] input, int off, int len) { + public long hashShorts(short @NotNull [] input, int off, int len) { checkArrayOffs(input.length, off, len); return hash(shortArrayAccessor(), input, off, len); } @@ -447,7 +447,7 @@ public long hashShorts(@NotNull short[] input, int off, int len) { /** * Shortcut for {@link #hashInts(int[], int, int) hashInts(input, 0, input.length)}. */ - public long hashInts(@NotNull int[] input) { + public long hashInts(int @NotNull [] input) { return hashInts(input, 0, input.length); } @@ -463,7 +463,7 @@ public long hashInts(@NotNull int[] input) { * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} * or {@code len < 0} */ - public long hashInts(@NotNull int[] input, int off, int len) { + public long hashInts(int @NotNull [] input, int off, int len) { checkArrayOffs(input.length, off, len); return hash(intArrayAccessor(), input, off, len); } @@ -471,7 +471,7 @@ public long hashInts(@NotNull int[] input, int off, int len) { /** * Shortcut for {@link #hashLongs(long[], int, int) hashLongs(input, 0, input.length)}. */ - public long hashLongs(@NotNull long[] input) { + public long hashLongs(long @NotNull [] input) { return hashLongs(input, 0, input.length); } @@ -487,7 +487,7 @@ public long hashLongs(@NotNull long[] input) { * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > input.length} * or {@code len < 0} */ - public long hashLongs(@NotNull long[] input, int off, int len) { + public long hashLongs(long @NotNull [] input, int off, int len) { checkArrayOffs(input.length, off, len); return hash(longArrayAccessor(), input, off, len); } diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java b/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java index 9ac47b15..08d7ff68 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java @@ -13,14 +13,11 @@ * Derived from https://github.com/google/guava/blob/fa95e381e665d8ee9639543b99ed38020c8de5ef * /guava/src/com/google/common/hash/Murmur3_128HashFunction.java */ +@SuppressWarnings("fallthrough") class MurmurHash_3 { // Singleton instance of MurmurHash_3 private static final MurmurHash_3 INSTANCE = new MurmurHash_3(); - // Singleton instance of MurmurHash_3 for native byte order - private static final MurmurHash_3 NATIVE_MURMUR = NATIVE_LITTLE_ENDIAN ? - MurmurHash_3.INSTANCE : BigEndian.INSTANCE; - // Constants used in the hash function private static final long C1 = 0x87c37b91114253d5L; private static final long C2 = 0x4cf5ad432745937fL; @@ -29,6 +26,10 @@ class MurmurHash_3 { private MurmurHash_3() { } + private static MurmurHash_3 nativeMurmur() { + return NATIVE_LITTLE_ENDIAN ? INSTANCE : BigEndian.INSTANCE; + } + /** * Finalizes the hash computation by mixing the hash values. * @@ -184,9 +185,9 @@ public long hash(long seed, T input, ReadAccess access, long offset, long long h2 = seed; long remaining = length; while (remaining >= 16L) { - long k1 = fetch64(access, input, offset); - long k2 = fetch64(access, input, offset + 8L); - offset += 16L; + long blockOffset = offset; + long k1 = fetch64(access, input, blockOffset); + offset = blockOffset + 16L; remaining -= 16L; h1 ^= mixK1(k1); @@ -194,6 +195,7 @@ public long hash(long seed, T input, ReadAccess access, long offset, long h1 += h2; h1 = h1 * 5L + 0x52dce729L; + long k2 = fetch64(access, input, blockOffset + 8L); h2 ^= mixK2(k2); h2 = Long.rotateLeft(h2, 31); @@ -201,122 +203,70 @@ public long hash(long seed, T input, ReadAccess access, long offset, long h2 = h2 * 5L + 0x38495ab5L; } if (remaining > 0L) { - long k1 = 0L; - long k2 = 0L; - switch ((int) remaining) { - case 15: - k2 ^= ((long) access.readUnsignedByte(input, offset + 14L)) << 48; // fall through - case 14: - k2 ^= ((long) access.readUnsignedByte(input, offset + 13L)) << 40; // fall through - case 13: - k2 ^= ((long) access.readUnsignedByte(input, offset + 12L)) << 32; // fall through - case 12: - k2 ^= ((long) access.readUnsignedByte(input, offset + 11L)) << 24; // fall through - case 11: - k2 ^= ((long) access.readUnsignedByte(input, offset + 10L)) << 16; // fall through - case 10: - k2 ^= ((long) access.readUnsignedByte(input, offset + 9L)) << 8; // fall through - case 9: - k2 ^= access.readUnsignedByte(input, offset + 8L); // fall through - case 8: - k1 ^= fetch64(access, input, offset); - break; - case 7: - k1 ^= ((long) access.readUnsignedByte(input, offset + 6L)) << 48; // fall through - case 6: - k1 ^= ((long) access.readUnsignedByte(input, offset + 5L)) << 40; // fall through - case 5: - k1 ^= ((long) access.readUnsignedByte(input, offset + 4L)) << 32; // fall through - case 4: - k1 ^= Primitives.unsignedInt(fetch32(access, input, offset)); - break; - case 3: - k1 ^= ((long) access.readUnsignedByte(input, offset + 2L)) << 16; // fall through - case 2: - k1 ^= ((long) access.readUnsignedByte(input, offset + 1L)) << 8; // fall through - case 1: - k1 ^= access.readUnsignedByte(input, offset); - case 0: - break; - default: - throw new AssertionError("Should never get here."); - } + int tailLength = (int) remaining; + long k1 = tailK1(access, input, offset, tailLength); + long k2 = tailK2(access, input, offset, tailLength); h1 ^= mixK1(k1); h2 ^= mixK2(k2); } -// This version appears to be working slower - -// if (remaining > 0L) { -// long k1 = 0L; -// long k2 = 0L; -// megaSwitch: -// { -// fetch0_7: -// { -// fetch8_11: -// { -// fetch0_3: -// { -// switch ((int) remaining) { -// case 15: -// k2 ^= ((long) access.readUnsignedByte(input, offset + 14L)) << 48; -// case 14: -// k2 ^= ((long) toLittleEndianShort( -// access.getUnsignedShort(input, offset + 12L))) << 32; -// break fetch8_11; -// case 13: -// k2 ^= ((long) access.readUnsignedByte(input, offset + 12L)) << 32; -// case 12: -// break fetch8_11; -// case 11: -// k2 ^= ((long) access.readUnsignedByte(input, offset + 10L)) << 16; -// case 10: -// k2 ^= (long) toLittleEndianShort( -// access.getUnsignedShort(input, offset + 8L)); -// break fetch0_7; -// case 9: -// k2 ^= ((long) access.readUnsignedByte(input, offset + 8L)); -// case 8: -// break fetch0_7; -// case 7: -// k1 ^= ((long) access.readUnsignedByte(input, offset + 6L)) << 48; -// case 6: -// k1 ^= ((long) toLittleEndianShort( -// access.getUnsignedShort(input, offset + 4L))) << 32; -// break fetch0_3; -// case 5: -// k1 ^= ((long) access.readUnsignedByte(input, offset + 4L)) << 32; -// case 4: -// break fetch0_3; -// case 3: -// k1 ^= ((long) access.readUnsignedByte(input, offset + 2L)) << 16; -// case 2: -// k1 ^= (long) toLittleEndianShort( -// access.getUnsignedShort(input, offset)); -// break megaSwitch; -// case 1: -// k1 ^= ((long) access.readUnsignedByte(input, offset)); -// break megaSwitch; -// default: -// throw new AssertionError(); -// } -// } // fetch0_3 -// k1 ^= unsignedInt(fetch32(access, input, offset)); -// break megaSwitch; -// } // fetch8_11 -// k2 ^= unsignedInt(fetch32(access, input, offset + 8L)); -// } // fetch0_7 -// k1 ^= fetch64(access, input, offset); -// } // megaSwitch -// -// h1 ^= mixK1(k1); -// h2 ^= mixK2(k2); -// } return finalize(length, h1, h2); } + private long tailK1(ReadAccess access, T input, long offset, int remaining) { + if (remaining >= 8) { + return fetch64(access, input, offset); + } + long k1 = 0L; + switch (remaining) { + case 7: + k1 ^= ((long) access.readUnsignedByte(input, offset + 6L)) << 48; // fall through + case 6: + k1 ^= ((long) access.readUnsignedByte(input, offset + 5L)) << 40; // fall through + case 5: + k1 ^= ((long) access.readUnsignedByte(input, offset + 4L)) << 32; // fall through + case 4: + k1 ^= Primitives.unsignedInt(fetch32(access, input, offset)); + break; + case 3: + k1 ^= ((long) access.readUnsignedByte(input, offset + 2L)) << 16; // fall through + case 2: + k1 ^= ((long) access.readUnsignedByte(input, offset + 1L)) << 8; // fall through + case 1: + k1 ^= access.readUnsignedByte(input, offset); + default: + break; + } + return k1; + } + + private long tailK2(ReadAccess access, T input, long offset, int remaining) { + if (remaining <= 8) { + return 0L; + } + long k2 = 0L; + switch (remaining) { + case 15: + k2 ^= ((long) access.readUnsignedByte(input, offset + 14L)) << 48; // fall through + case 14: + k2 ^= ((long) access.readUnsignedByte(input, offset + 13L)) << 40; // fall through + case 13: + k2 ^= ((long) access.readUnsignedByte(input, offset + 12L)) << 32; // fall through + case 12: + k2 ^= ((long) access.readUnsignedByte(input, offset + 11L)) << 24; // fall through + case 11: + k2 ^= ((long) access.readUnsignedByte(input, offset + 10L)) << 16; // fall through + case 10: + k2 ^= ((long) access.readUnsignedByte(input, offset + 9L)) << 8; // fall through + case 9: + k2 ^= access.readUnsignedByte(input, offset + 8L); + default: + break; + } + return k2; + } + /** - * Big-endian implementation of MurmurHash_3. + * Big-endian implementation of MurmurHash3. */ private static class BigEndian extends MurmurHash_3 { // Singleton instance of BigEndian @@ -353,7 +303,7 @@ int toLittleEndianShort(int unsignedShort) { } /** - * Implementation of LongHashFunction using MurmurHash_3. + * Implementation of LongHashFunction using MurmurHash3. */ private static class AsLongHashFunction extends LongHashFunction { // Singleton instance of AsLongHashFunction @@ -389,23 +339,23 @@ long hashNativeLong(long nativeLong, long len) { @Override public long hashLong(long input) { - return hashNativeLong(NATIVE_MURMUR.toLittleEndian(input), 8L); + return hashNativeLong(nativeMurmur().toLittleEndian(input), 8L); } @Override public long hashInt(int input) { - return hashNativeLong(Primitives.unsignedInt(NATIVE_MURMUR.toLittleEndian(input)), 4L); + return hashNativeLong(Primitives.unsignedInt(nativeMurmur().toLittleEndian(input)), 4L); } @Override public long hashShort(short input) { return hashNativeLong( - NATIVE_MURMUR.toLittleEndianShort(Primitives.unsignedShort(input)), 2L); + nativeMurmur().toLittleEndianShort(Primitives.unsignedShort(input)), 2L); } @Override public long hashChar(char input) { - return hashNativeLong(NATIVE_MURMUR.toLittleEndianShort(input), 2L); + return hashNativeLong(nativeMurmur().toLittleEndianShort(input), 2L); } @Override @@ -430,7 +380,7 @@ public long hash(T input, ReadAccess access, long off, long len) { } /** - * Implementation of LongHashFunction using MurmurHash_3 with a seed value. + * Implementation of LongHashFunction using MurmurHash3 with a seed value. */ private static class AsLongHashFunctionSeeded extends AsLongHashFunction { private static final long serialVersionUID = 0L; @@ -438,7 +388,7 @@ private static class AsLongHashFunctionSeeded extends AsLongHashFunction { // The seed value private final long seed; // The precomputed hash value for an empty input - private final transient long voidHash; + private final long voidHash; /** * Constructs an instance with the given seed. diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java b/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java index 45ec8175..43897b76 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java @@ -16,8 +16,6 @@ */ class XxHash_r39 { private static final XxHash_r39 INSTANCE = new XxHash_r39(); - private static final XxHash_r39 NATIVE_XX = NATIVE_LITTLE_ENDIAN ? - XxHash_r39.INSTANCE : BigEndian.INSTANCE; // Primes if treated as unsigned private static final long P1 = -7046029288634856825L; @@ -30,6 +28,10 @@ class XxHash_r39 { private XxHash_r39() { } + private static XxHash_r39 nativeXx() { + return NATIVE_LITTLE_ENDIAN ? INSTANCE : BigEndian.INSTANCE; + } + /** * Finalizes the hash value with additional mixing of bits. * @@ -262,7 +264,8 @@ long fetch32(ReadAccess access, T in, long off) { // Reverse bytes for big-endian compatibility return Integer.reverseBytes(access.readInt(in, off)) & 0xFFFFFFFFL; } -// fetch8 is not overloaded, because endianness doesn't matter for single byte + + // fetch8 is not overloaded, because endianness doesn't matter for single byte @Override long toLittleEndian(long v) { @@ -307,11 +310,11 @@ public long seed() { @Override public long hashLong(long input) { // Convert input to little-endian and compute hash - input = NATIVE_XX.toLittleEndian(input); - long hash = seed() + P5 + 8; + input = nativeXx().toLittleEndian(input); input *= P2; input = Long.rotateLeft(input, 31); input *= P1; + long hash = seed() + P5 + 8; hash ^= input; hash = Long.rotateLeft(hash, 27) * P1 + P4; return XxHash_r39.finalize(hash); @@ -320,7 +323,7 @@ public long hashLong(long input) { @Override public long hashInt(int input) { // Convert input to little-endian and compute hash - input = NATIVE_XX.toLittleEndian(input); + input = nativeXx().toLittleEndian(input); long hash = seed() + P5 + 4; hash ^= Primitives.unsignedInt(input) * P1; hash = Long.rotateLeft(hash, 23) * P2 + P3; @@ -330,7 +333,7 @@ public long hashInt(int input) { @Override public long hashShort(short input) { // Convert input to little-endian and compute hash - input = NATIVE_XX.toLittleEndian(input); + input = nativeXx().toLittleEndian(input); long hash = seed() + P5 + 2; hash ^= Primitives.unsignedByte(input) * P5; hash = Long.rotateLeft(hash, 11) * P1; diff --git a/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java b/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java index 8d7fbb8a..a4b0d343 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java @@ -13,109 +13,48 @@ public final class TryAcquireOperations { // TryAcquireOperation for LockingStrategy private static final TryAcquireOperation LOCK = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(LockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryLock(access, obj, offset); - } - }; + LockingStrategy::tryLock; // TryAcquireOperation for ReadWriteLockingStrategy - Read Lock private static final TryAcquireOperation READ_LOCK = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryReadLock(access, obj, offset); - } - }; + ReadWriteLockingStrategy::tryReadLock; // TryAcquireOperation for ReadWriteLockingStrategy - Upgrade Read to Write Lock private static final TryAcquireOperation UPGRADE_READ_TO_WRITE_LOCK = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryUpgradeReadToWriteLock(access, obj, offset); - } - }; + ReadWriteLockingStrategy::tryUpgradeReadToWriteLock; // TryAcquireOperation for ReadWriteLockingStrategy - Write Lock private static final TryAcquireOperation WRITE_LOCK = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryWriteLock(access, obj, offset); - } - }; + ReadWriteLockingStrategy::tryWriteLock; // TryAcquireOperation for ReadWriteWithWaitsLockingStrategy - Upgrade Read to Write Lock and Deregister Wait private static final TryAcquireOperation UPGRADE_READ_TO_WRITE_LOCK_AND_DEREGISTER_WAIT = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteWithWaitsLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryUpgradeReadToWriteLockAndDeregisterWait(access, obj, offset); - } - }; + ReadWriteWithWaitsLockingStrategy::tryUpgradeReadToWriteLockAndDeregisterWait; // TryAcquireOperation for ReadWriteWithWaitsLockingStrategy - Write Lock and Deregister Wait private static final TryAcquireOperation WRITE_LOCK_AND_DEREGISTER_WAIT = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteWithWaitsLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryWriteLockAndDeregisterWait(access, obj, offset); - } - }; + ReadWriteWithWaitsLockingStrategy::tryWriteLockAndDeregisterWait; // TryAcquireOperation for ReadWriteUpdateLockingStrategy - Update Lock private static final TryAcquireOperation UPDATE_LOCK = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteUpdateLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryUpdateLock(access, obj, offset); - } - }; + ReadWriteUpdateLockingStrategy::tryUpdateLock; // TryAcquireOperation for ReadWriteUpdateLockingStrategy - Upgrade Read to Update Lock private static final TryAcquireOperation UPGRADE_READ_TO_UPDATE_LOCK = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteUpdateLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryUpgradeReadToUpdateLock(access, obj, offset); - } - }; + ReadWriteUpdateLockingStrategy::tryUpgradeReadToUpdateLock; // TryAcquireOperation for ReadWriteUpdateLockingStrategy - Upgrade Update to Write Lock private static final TryAcquireOperation UPGRADE_UPDATE_TO_WRITE_LOCK = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteUpdateLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryUpgradeUpdateToWriteLock(access, obj, offset); - } - }; + ReadWriteUpdateLockingStrategy::tryUpgradeUpdateToWriteLock; // TryAcquireOperation for ReadWriteUpdateWithWaitsLockingStrategy - Upgrade Update to Write Lock and Deregister Wait private static final TryAcquireOperation UPGRADE_UPDATE_TO_WRITE_LOCK_AND_DEREGISTER_WAIT = - new TryAcquireOperation() { - @Override - public boolean tryAcquire(ReadWriteUpdateWithWaitsLockingStrategy strategy, - Access access, T obj, long offset) { - return strategy.tryUpgradeUpdateToWriteLockAndDeregisterWait( - access, obj, offset); - } - }; + ReadWriteUpdateWithWaitsLockingStrategy::tryUpgradeUpdateToWriteLockAndDeregisterWait; // Private constructor to prevent instantiation private TryAcquireOperations() { diff --git a/src/test/java/net/openhft/chronicle/algo/bitset/BitSetTest.java b/src/test/java/net/openhft/chronicle/algo/bitset/BitSetTest.java index 73c02d43..b45cdf11 100644 --- a/src/test/java/net/openhft/chronicle/algo/bitset/BitSetTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bitset/BitSetTest.java @@ -3,13 +3,14 @@ */ package net.openhft.chronicle.algo.bitset; -import junit.framework.TestCase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.*; -public class BitSetTest extends TestCase { +public class BitSetTest { private BitSet bitSet; @BeforeEach diff --git a/src/test/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrameTest.java b/src/test/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrameTest.java index 504bd197..72542848 100644 --- a/src/test/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrameTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrameTest.java @@ -3,15 +3,15 @@ */ package net.openhft.chronicle.algo.bitset; -import junit.framework.TestCase; import net.openhft.chronicle.algo.bytes.Access; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; @SuppressWarnings("unchecked") -public class ConcurrentFlatBitSetFrameTest extends TestCase { +public class ConcurrentFlatBitSetFrameTest { private ConcurrentFlatBitSetFrame bitSetFrame; private Access access; private Object handle; diff --git a/src/test/java/net/openhft/chronicle/algo/bitset/DirectBitSetTest.java b/src/test/java/net/openhft/chronicle/algo/bitset/DirectBitSetTest.java index 60b238f0..b037b3cf 100644 --- a/src/test/java/net/openhft/chronicle/algo/bitset/DirectBitSetTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bitset/DirectBitSetTest.java @@ -125,12 +125,12 @@ public void testGetSetClearAndCardinality() { assertTrue("At index " + i, bs.isClear(i)); } for (int i : INDICES) { - assertEquals("At index " + i, true, bs.setIfClear(i)); - assertEquals("At index " + i, false, bs.setIfClear(i)); + assertTrue("At index " + i, bs.setIfClear(i)); + assertFalse("At index " + i, bs.setIfClear(i)); } for (int i : INDICES) { - assertEquals("At index " + i, true, bs.clearIfSet(i)); - assertEquals("At index " + i, false, bs.clearIfSet(i)); + assertTrue("At index " + i, bs.clearIfSet(i)); + assertFalse("At index " + i, bs.clearIfSet(i)); } } @@ -138,11 +138,11 @@ public void testGetSetClearAndCardinality() { public void testFlip() { bs.clearAll(); for (int i : INDICES) { - assertEquals("At index " + i, false, bs.get(i)); + assertFalse("At index " + i, bs.get(i)); bs.flip(i); - assertEquals("At index " + i, true, bs.get(i)); + assertTrue("At index " + i, bs.get(i)); bs.flip(i); - assertEquals("At index " + i, false, bs.get(i)); + assertFalse("At index " + i, bs.get(i)); } } @@ -387,10 +387,10 @@ public void testRangeOpsWithinLongCase() { assertTrue(bs.isRangeSet(63, 63)); } bs.flipRange(0, 0); - assertEquals(false, bs.get(0)); + assertFalse(bs.get(0)); assertEquals(0, bs.cardinality()); bs.flipRange(0, 1); - assertEquals(true, bs.get(0)); + assertTrue(bs.get(0)); assertEquals(1, bs.cardinality()); if (singleThreaded) { assertTrue(bs.isRangeSet(0, 1)); @@ -398,17 +398,17 @@ public void testRangeOpsWithinLongCase() { assertFalse(bs.isRangeClear(0, 1)); } bs.clearRange(0, 0); - assertEquals(true, bs.get(0)); + assertTrue(bs.get(0)); assertEquals(1, bs.cardinality()); bs.clearRange(0, 1); - assertEquals(false, bs.get(0)); + assertFalse(bs.get(0)); assertEquals(0, bs.cardinality()); bs.setRange(0, 0); - assertEquals(false, bs.get(0)); + assertFalse(bs.get(0)); assertEquals(0, bs.cardinality()); bs.setRange(0, 1); - assertEquals(true, bs.get(0)); + assertTrue(bs.get(0)); assertEquals(1, bs.cardinality()); } @@ -417,16 +417,16 @@ public void testRangeOpsCrossLongCase() { bs.clearAll(); bs.flipRange(63, 64); - assertEquals(true, bs.get(63)); - assertEquals(false, bs.get(64)); + assertTrue(bs.get(63)); + assertFalse(bs.get(64)); assertEquals(1, bs.cardinality()); if (singleThreaded) { assertFalse(bs.isRangeSet(63, 65)); assertFalse(bs.isRangeClear(63, 65)); } bs.flipRange(63, 65); - assertEquals(false, bs.get(63)); - assertEquals(true, bs.get(64)); + assertFalse(bs.get(63)); + assertTrue(bs.get(64)); assertEquals(1, bs.cardinality()); if (singleThreaded) { assertFalse(bs.isRangeSet(63, 65)); @@ -434,28 +434,28 @@ public void testRangeOpsCrossLongCase() { } bs.clear(64); bs.setRange(63, 64); - assertEquals(true, bs.get(63)); - assertEquals(false, bs.get(64)); + assertTrue(bs.get(63)); + assertFalse(bs.get(64)); assertEquals(1, bs.cardinality()); bs.set(64); bs.clearRange(63, 64); - assertEquals(false, bs.get(63)); - assertEquals(true, bs.get(64)); + assertFalse(bs.get(63)); + assertTrue(bs.get(64)); assertEquals(1, bs.cardinality()); bs.clear(64); bs.setRange(63, 65); - assertEquals(true, bs.get(63)); - assertEquals(true, bs.get(64)); + assertTrue(bs.get(63)); + assertTrue(bs.get(64)); assertEquals(2, bs.cardinality()); if (singleThreaded) { assertTrue(bs.isRangeSet(63, 65)); assertFalse(bs.isRangeClear(63, 65)); } bs.clearRange(63, 65); - assertEquals(false, bs.get(63)); - assertEquals(false, bs.get(64)); + assertFalse(bs.get(63)); + assertFalse(bs.get(64)); assertEquals(0, bs.cardinality()); if (singleThreaded) { assertFalse(bs.isRangeSet(63, 65)); diff --git a/src/test/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithmTest.java b/src/test/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithmTest.java index a88a2dbf..970d7990 100644 --- a/src/test/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithmTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithmTest.java @@ -3,10 +3,11 @@ */ package net.openhft.chronicle.algo.bitset; -import junit.framework.TestCase; import org.junit.jupiter.api.Test; -public class FlatBitSetAlgorithmTest extends TestCase { +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FlatBitSetAlgorithmTest { @Test public void testSizeInBytes() { long logicalSize = 64L; diff --git a/src/test/java/net/openhft/chronicle/algo/bitset/ReusableBitSetTest.java b/src/test/java/net/openhft/chronicle/algo/bitset/ReusableBitSetTest.java index 19630f8a..cd5769f8 100644 --- a/src/test/java/net/openhft/chronicle/algo/bitset/ReusableBitSetTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bitset/ReusableBitSetTest.java @@ -114,9 +114,11 @@ void basicMutationsCoverAllOperations(String name, Supplier facto assertRangeClear(bs, clearedPrevStart, clearedPrevStart + 4); BitSet.Bits bits = bs.setBits().reset(); + int visited = 0; while (bits.next() >= 0) { - // iterate to exercise iterator implementation + visited++; } + assertEquals(bs.cardinality(), visited); bs.setAll(); assertEquals(LOGICAL_SIZE, bs.cardinality()); @@ -130,14 +132,12 @@ private static final class BitSetFixture implements AutoCloseable { private final Access access; private final Object handle; private final BytesStore bytesStore; - private final long offset; - private BitSetFixture(ReusableBitSet bitSet, Access access, Object handle, BytesStore bytesStore, long offset) { + private BitSetFixture(ReusableBitSet bitSet, Access access, Object handle, BytesStore bytesStore) { this.bitSet = bitSet; this.access = access; this.handle = handle; this.bytesStore = bytesStore; - this.offset = offset; } static BitSetFixture singleThreaded(ByteBuffer buffer) { @@ -146,7 +146,7 @@ static BitSetFixture singleThreaded(ByteBuffer buffer) { SingleThreadedFlatBitSetFrame frame = new SingleThreadedFlatBitSetFrame(LOGICAL_SIZE); Access bbAccess = Access.checkedByteBufferAccess(); ReusableBitSet bitSet = new ReusableBitSet(frame, bbAccess, buffer, offset); - return new BitSetFixture(bitSet, bbAccess, buffer, null, offset); + return new BitSetFixture(bitSet, bbAccess, buffer, null); } @SuppressWarnings("unchecked") @@ -157,7 +157,7 @@ static BitSetFixture concurrentStore() { Access storeAccess = Access.checkedBytesStoreAccess(); @SuppressWarnings("rawtypes") ReusableBitSet bitSet = new ReusableBitSet(frame, (Access) storeAccess, store, offset); - return new BitSetFixture(bitSet, storeAccess, store, store, offset); + return new BitSetFixture(bitSet, storeAccess, store, store); } ReusableBitSet bitSet() { diff --git a/src/test/java/net/openhft/chronicle/algo/bytes/AccessTest.java b/src/test/java/net/openhft/chronicle/algo/bytes/AccessTest.java index 4da998bf..31e4ef2e 100644 --- a/src/test/java/net/openhft/chronicle/algo/bytes/AccessTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bytes/AccessTest.java @@ -3,34 +3,26 @@ */ package net.openhft.chronicle.algo.bytes; -import junit.framework.TestCase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.*; @SuppressWarnings("unchecked") -public class AccessTest extends TestCase { +class AccessTest { private Access access; private Object handle; - private Access sourceAccess; - private Access targetAccess; - private Object source; - private Object target; @BeforeEach - public void setUp() { + void setUp() { access = mock(Access.class); handle = new Object(); - sourceAccess = mock(Access.class); - targetAccess = mock(Access.class); - source = new Object(); - target = new Object(); } @Test - public void testCompareAndSwapInt() { + void testCompareAndSwapInt() { long offset = 0L; int expected = 10; int value = 20; @@ -42,7 +34,7 @@ public void testCompareAndSwapInt() { } @Test - public void testCompareAndSwapLong() { + void testCompareAndSwapLong() { long offset = 0L; long expected = 10L; long value = 20L; diff --git a/src/test/java/net/openhft/chronicle/algo/bytes/AccessUtilitiesTest.java b/src/test/java/net/openhft/chronicle/algo/bytes/AccessUtilitiesTest.java index 6eef9d27..31d3c233 100644 --- a/src/test/java/net/openhft/chronicle/algo/bytes/AccessUtilitiesTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bytes/AccessUtilitiesTest.java @@ -114,12 +114,12 @@ void bytesAccessesFullDelegatesToBytesStore() { BytesStore store = BytesStore.nativeStoreWithFixedCapacity(32); try { @SuppressWarnings("rawtypes") - Full access = (Full) Full.INSTANCE; - assertTrue(access.compareAndSwapInt((BytesStore) store, 0, 0, 42)); + Full access = Full.INSTANCE; + assertTrue(access.compareAndSwapInt(store, 0, 0, 42)); assertEquals(42, store.readInt(0)); - assertTrue(access.compareAndSwapLong((BytesStore) store, 8, 0L, 123L)); + assertTrue(access.compareAndSwapLong(store, 8, 0L, 123L)); assertEquals(123L, store.readLong(8)); - assertEquals(store.byteOrder(), access.byteOrder((BytesStore) store)); + assertEquals(store.byteOrder(), access.byteOrder(store)); } finally { store.releaseLast(); } @@ -132,10 +132,9 @@ void randomDataInputAccessReadsPrimitiveValues() { store.writeLong(0, 0x0102030405060708L); store.writeInt(16, 0x11223344); RandomDataInputAccess access = BytesAccesses.RandomDataInputReadAccessEnum.INSTANCE; - RandomDataInput handle = store; - assertEquals(0x11223344, access.readInt(handle, 16)); - assertEquals(0x0102030405060708L, access.readLong(handle, 0)); - assertEquals(handle.byteOrder(), access.byteOrder(handle)); + assertEquals(0x11223344, access.readInt(store, 16)); + assertEquals(0x0102030405060708L, access.readLong(store, 0)); + assertEquals(store.byteOrder(), access.byteOrder(store)); } finally { store.releaseLast(); } @@ -151,8 +150,8 @@ void arrayAccessorOffsetsScalePerElement() { byte[] bytes = new byte[8]; assertEquals( - ArrayAccessors.Byte.INSTANCE.offset(bytes, 5) - ArrayAccessors.Byte.INSTANCE.offset(bytes, 0), - 5 + 5, + ArrayAccessors.Byte.INSTANCE.offset(bytes, 5) - ArrayAccessors.Byte.INSTANCE.offset(bytes, 0) ); } @@ -161,11 +160,11 @@ void hotSpotStringAccessorExposesBackingStorage() { String sample = "Cafe"; Object handle = CharSequenceAccessor.stringAccessor.handle(sample); if (Jvm.isJava9Plus()) { - assertTrue(handle instanceof byte[]); + assertInstanceOf(byte[].class, handle); byte[] asBytes = (byte[]) handle; assertTrue(asBytes.length >= sample.length()); } else { - assertTrue(handle instanceof char[]); + assertInstanceOf(char[].class, handle); char[] asChars = (char[]) handle; assertEquals(sample.length(), asChars.length); } diff --git a/src/test/java/net/openhft/chronicle/algo/bytes/ByteBufferAccessTest.java b/src/test/java/net/openhft/chronicle/algo/bytes/ByteBufferAccessTest.java index 2e41c9a8..3cc14ba0 100644 --- a/src/test/java/net/openhft/chronicle/algo/bytes/ByteBufferAccessTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bytes/ByteBufferAccessTest.java @@ -3,14 +3,15 @@ */ package net.openhft.chronicle.algo.bytes; -import junit.framework.TestCase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.nio.ByteBuffer; import java.nio.ByteOrder; -public class ByteBufferAccessTest extends TestCase { +import static org.junit.jupiter.api.Assertions.*; + +public class ByteBufferAccessTest { private ByteBufferAccess access; private ByteBuffer buffer; diff --git a/src/test/java/net/openhft/chronicle/algo/bytes/CharSequenceAccessTest.java b/src/test/java/net/openhft/chronicle/algo/bytes/CharSequenceAccessTest.java index 883dd513..762529f8 100644 --- a/src/test/java/net/openhft/chronicle/algo/bytes/CharSequenceAccessTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bytes/CharSequenceAccessTest.java @@ -3,12 +3,13 @@ */ package net.openhft.chronicle.algo.bytes; -import junit.framework.TestCase; import org.junit.jupiter.api.Test; import java.nio.ByteOrder; -public class CharSequenceAccessTest extends TestCase { +import static org.junit.jupiter.api.Assertions.*; + +public class CharSequenceAccessTest { private static final CharSequence TEST_SEQUENCE = "0123456789ABCDEF"; @Test diff --git a/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccessTest.java b/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccessTest.java index f3cff26f..8821496c 100644 --- a/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccessTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccessTest.java @@ -3,16 +3,16 @@ */ package net.openhft.chronicle.algo.bytes; -import junit.framework.TestCase; import net.openhft.chronicle.bytes.RandomDataInput; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.nio.ByteOrder; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; -public class RandomDataInputAccessTest extends TestCase { +public class RandomDataInputAccessTest { private RandomDataInput mockInput; private RandomDataInputAccess access; diff --git a/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccessTest.java b/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccessTest.java index 06edcc79..3d0ce6a5 100644 --- a/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccessTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccessTest.java @@ -3,16 +3,16 @@ */ package net.openhft.chronicle.algo.bytes; -import junit.framework.TestCase; import net.openhft.chronicle.bytes.RandomDataOutput; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.nio.ByteOrder; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; -public class RandomDataOutputAccessTest extends TestCase { +public class RandomDataOutputAccessTest { private RandomDataOutputImpl mockOutput; private RandomDataOutputAccess access; @@ -110,6 +110,6 @@ public void testByteOrder() { } // Mock class extending RandomDataOutput with self-referential generic type - abstract class RandomDataOutputImpl implements RandomDataOutput { + abstract static class RandomDataOutputImpl implements RandomDataOutput { } -} \ No newline at end of file +} diff --git a/src/test/java/net/openhft/chronicle/algo/bytes/WriteAccessTest.java b/src/test/java/net/openhft/chronicle/algo/bytes/WriteAccessTest.java index 70093fe3..3d18cdf6 100644 --- a/src/test/java/net/openhft/chronicle/algo/bytes/WriteAccessTest.java +++ b/src/test/java/net/openhft/chronicle/algo/bytes/WriteAccessTest.java @@ -9,8 +9,8 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import static org.junit.Assume.assumeFalse; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.mockito.Mockito.*; @SuppressWarnings("unchecked") diff --git a/src/test/java/net/openhft/chronicle/algo/hashing/City64MoreTest.java b/src/test/java/net/openhft/chronicle/algo/hashing/City64MoreTest.java index 644658a2..f11b0fcc 100644 --- a/src/test/java/net/openhft/chronicle/algo/hashing/City64MoreTest.java +++ b/src/test/java/net/openhft/chronicle/algo/hashing/City64MoreTest.java @@ -8,7 +8,7 @@ import org.junit.Ignore; import org.junit.Test; -import java.security.SecureRandom; +import java.util.concurrent.ThreadLocalRandom; /** * Created by peter on 28/06/15. @@ -46,8 +46,8 @@ public void testSmallRandomness() { if (t % 50 == 0) System.out.println(t + " - Score: " + score); } - System.out.println("Average score: " + scoreSum / 500); - System.out.printf("Average time %.3f us%n", time / timeCount / 1e3); + System.out.println("Average score: " + (scoreSum / 500.0)); + System.out.printf("Average time %.3f us%n", (time / (double) timeCount) / 1e3); } @Ignore("Long running, avg score = 6852") @@ -59,7 +59,7 @@ public void testRandomness() { long[] hashs = new long[8192]; NativeBytes b = NativeBytes.nativeBytes(hashs.length / 64); byte[] init = new byte[hashs.length / 64]; - new SecureRandom().nextBytes(init); + ThreadLocalRandom.current().nextBytes(init); for (int i = 0; i < hashs.length; i++) { b.clear(); b.write(init); @@ -85,7 +85,7 @@ public void testRandomness() { if (t % 50 == 0) System.out.println(t + " - Score: " + score); } - System.out.println("Average score: " + scoreSum / 500); - System.out.printf("Average time %.3f us%n", time / timeCount / 1e3); + System.out.println("Average score: " + (scoreSum / 500.0)); + System.out.printf("Average time %.3f us%n", (time / (double) timeCount) / 1e3); } } diff --git a/src/test/java/net/openhft/chronicle/algo/hashing/City64_1_1_Test.java b/src/test/java/net/openhft/chronicle/algo/hashing/City64_1_1_Test.java index 7286d400..b379d18d 100644 --- a/src/test/java/net/openhft/chronicle/algo/hashing/City64_1_1_Test.java +++ b/src/test/java/net/openhft/chronicle/algo/hashing/City64_1_1_Test.java @@ -2088,26 +2088,26 @@ public void testCityWithoutSeeds() { } // The following numbers is the result of compiling & running this program -// with city-1.1.1, reference impl: -// -// #include -// #include -// #include -// -// main() { -// char* src = (char*) malloc(1024); -// for (int i = 0; i < 1024; i++) { -// src[i] = (char) i; -// } -// printf("without seeds\n"); -// for (int i = 0; i <= 1024; i++) { -// printf("%lldL,\n", (long long)CityHash64(src, i)); -// } -// printf("with seeds 0, 0\n"); -// for (int i = 0; i <= 1024; i++) { -// printf("%lldL,\n", (long long)CityHash64WithSeeds(src, i, 0, 0)); -// } -// } + // with city-1.1.1, reference impl: + // + // #include + // #include + // #include + // + // main() { + // char* src = (char*) malloc(1024); + // for (int i = 0; i < 1024; i++) { + // src[i] = (char) i; + // } + // printf("without seeds\n"); + // for (int i = 0; i <= 1024; i++) { + // printf("%lldL,\n", (long long)CityHash64(src, i)); + // } + // printf("with seeds 0, 0\n"); + // for (int i = 0; i <= 1024; i++) { + // printf("%lldL,\n", (long long)CityHash64WithSeeds(src, i, 0, 0)); + // } + // } @Test public void testCityWithOneSeed() { test(LongHashFunction.city_1_1(0L, 0L), HASHES_OF_LOOPING_BYTES_WITH_SEEDS_0_0); diff --git a/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java b/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java index 782d5a61..60831a8d 100644 --- a/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java +++ b/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java @@ -148,8 +148,8 @@ private static void exerciseNegativePrimitiveHashes(LongHashFunction function) { Arrays.fill(bytes, (byte) -1); long byteHash = function.hashBytes(bytes, 0, 1); long shortHash = function.hashBytes(bytes, 0, 2); - long intHash = function.hashBytes(bytes, 0, 4); - long longHash = function.hashBytes(bytes, 0, 8); + final long intHash = function.hashBytes(bytes, 0, 4); + final long longHash = function.hashBytes(bytes, 0, 8); assertEquals("hashByte(-1)", byteHash, function.hashByte((byte) -1)); assertEquals("hashShort(-1)", shortHash, function.hashShort((short) -1)); diff --git a/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3MoreTest.java b/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3MoreTest.java index 80e433aa..d256e9ed 100644 --- a/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3MoreTest.java +++ b/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3MoreTest.java @@ -8,7 +8,7 @@ import org.junit.Ignore; import org.junit.Test; -import java.security.SecureRandom; +import java.util.concurrent.ThreadLocalRandom; /** * Created by peter on 28/06/15. @@ -46,8 +46,8 @@ public void testSmallRandomness() { if (t % 50 == 0) System.out.println(t + " - Score: " + score); } - System.out.println("Average score: " + scoreSum / 500); - System.out.printf("Average time %.3f us%n", time / timeCount / 1e3); + System.out.println("Average score: " + (scoreSum / 500.0)); + System.out.printf("Average time %.3f us%n", (time / (double) timeCount) / 1e3); } @Ignore("Long running, avg score = 6836") @@ -59,7 +59,7 @@ public void testRandomness() { long[] hashs = new long[8192]; NativeBytes b = NativeBytes.nativeBytes(hashs.length / 64); byte[] init = new byte[hashs.length / 64]; - new SecureRandom().nextBytes(init); + ThreadLocalRandom.current().nextBytes(init); for (int i = 0; i < hashs.length; i++) { b.clear(); b.write(init); @@ -85,7 +85,7 @@ public void testRandomness() { if (t % 50 == 0) System.out.println(t + " - Score: " + score); } - System.out.println("Average score: " + scoreSum / 500); - System.out.printf("Average time %.3f us%n", time / timeCount / 1e3); + System.out.println("Average score: " + (scoreSum / 500.0)); + System.out.printf("Average time %.3f us%n", (time / (double) timeCount) / 1e3); } } diff --git a/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3Test.java b/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3Test.java index cb24421c..fe7e8263 100644 --- a/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3Test.java +++ b/src/test/java/net/openhft/chronicle/algo/hashing/MurmurHash3Test.java @@ -8,7 +8,7 @@ import org.junit.Test; import java.util.Arrays; -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; public class MurmurHash3Test { @@ -24,7 +24,7 @@ public void testMurmurWithSeed() { private void testMurmur(LongHashFunction tested, HashFunction referenceFromGuava) { byte[] testData = new byte[1024]; - new Random().nextBytes(testData); + ThreadLocalRandom.current().nextBytes(testData); for (int i = 0; i < testData.length; i++) { byte[] data = Arrays.copyOf(testData, i); LongHashFunctionTest.test(tested, data, referenceFromGuava.hashBytes(data).asLong()); diff --git a/src/test/java/net/openhft/chronicle/algo/hashing/XxHash_r39_Test.java b/src/test/java/net/openhft/chronicle/algo/hashing/XxHash_r39_Test.java index 448e6a29..a48d784b 100644 --- a/src/test/java/net/openhft/chronicle/algo/hashing/XxHash_r39_Test.java +++ b/src/test/java/net/openhft/chronicle/algo/hashing/XxHash_r39_Test.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.List; @RunWith(Parameterized.class) public class XxHash_r39_Test { @@ -18,8 +19,8 @@ public class XxHash_r39_Test { * from https://code.google.com/p/xxhash/ *

* #include "xxhash.c" - * #include - * #include + * #include <stdlib.h> + * #include <stdio.h> * int main() * { * char* src = (char*) malloc(1024); @@ -2098,7 +2099,7 @@ public class XxHash_r39_Test { @Parameterized.Parameters public static Collection data() { - ArrayList data = new ArrayList(); + List data = new ArrayList<>(); for (int len = 0; len < 1025; len++) { data.add(new Object[]{len}); } diff --git a/src/test/java/net/openhft/chronicle/algo/locks/LockingStrategyTest.java b/src/test/java/net/openhft/chronicle/algo/locks/LockingStrategyTest.java index 47497750..ccd137ff 100644 --- a/src/test/java/net/openhft/chronicle/algo/locks/LockingStrategyTest.java +++ b/src/test/java/net/openhft/chronicle/algo/locks/LockingStrategyTest.java @@ -179,7 +179,7 @@ public void testUpdateLockUpgradeToWriteLock() throws ExecutionException, Interr assertTrue(e1.submit(() -> rwuls().tryUpgradeUpdateToWriteLock()).get()); // Release the write lock in thread 1... - e1.submit(() -> rwuls().downgradeWriteToUpdateLock()); + e1.submit(() -> rwuls().downgradeWriteToUpdateLock()).get(); // Release the update lock in thread 1... e1.submit(updateUnlockTask).get(); @@ -211,7 +211,7 @@ public void testReadWriteLockTransitions() { rwls().readUnlock(); assertTrue(rwls().tryWriteLock()); } -// write lock is held + // write lock is held readUnlockForbidden(); upgradeReadToWriteLockForbidden(); diff --git a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java index 9fed8e5b..9dae9caf 100644 --- a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java +++ b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java @@ -15,14 +15,12 @@ class VanillaReadWriteWithWaitsLockingStrategyTest { private Access access; - private ReadAccess readAccess; private Object handle; private ReadWriteWithWaitsLockingStrategy strategy; @BeforeEach void setUp() { access = mock(Access.class); - readAccess = mock(ReadAccess.class); handle = new Object(); strategy = VanillaReadWriteWithWaitsLockingStrategy.instance(); } From 552335aa794dc08239abe8c7918b6decc309e7b4 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 20 Nov 2025 19:36:42 +0000 Subject: [PATCH 02/15] Add documentation files for AI agents and project overview --- AGENTS.md | 161 +++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 107 ++++++++++++++++++++++++++++++ README.adoc | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 15 ----- 4 files changed, 451 insertions(+), 15 deletions(-) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 README.adoc delete mode 100644 README.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..5c83c58f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,161 @@ +# Guidance for AI agents, bots, and humans contributing to Chronicle Software's OpenHFT projects. + +LLM-based agents can accelerate development only if they respect our house rules. This file tells you: + +* how to run and verify the build; +* what *not* to comment; +* when to open pull requests. + +## Language & character-set policy + +| Requirement | Rationale | +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------| +| **British English** spelling (`organisation`, `licence`, *not* `organization`, `license`) except technical US spellings like `synchronized` | Keeps wording consistent with Chronicle's London HQ and existing docs. See the University of Oxford style guide for reference. | +| **ISO-8859-1** (code-points 0-255), except in string literals. Avoid smart quotes, non-breaking spaces and accented characters. | ISO-8859-1 survives every toolchain Chronicle uses, incl. low-latency binary wire formats that expect the 8th bit to be 0. | +| If a symbol is not available in ISO-8859-1, use a textual form such as `micro-second`, `>=`, `:alpha:`, `:yes:`. This is the preferred approach and Unicode must not be inserted. | Extended or '8-bit ASCII' variants are *not* portable and are therefore disallowed. | + +## Javadoc guidelines + +**Goal:** Every Javadoc block should add information you cannot glean from the method signature alone. Anything else is +noise and slows readers down. + +| Do | Don't | +|----|-------| +| State *behavioural contracts*, edge-cases, thread-safety guarantees, units, performance characteristics and checked exceptions. | Restate the obvious ("Gets the value", "Sets the name"). | +| Keep the first sentence short; it becomes the summary line in aggregated docs. | Duplicate parameter names/ types unless more explanation is needed. | +| Prefer `@param` for *constraints* and `@throws` for *conditions*, following Oracle's style guide. | Pad comments to reach a line-length target. | +| Remove or rewrite autogenerated Javadoc for trivial getters/setters. | Leave stale comments that now contradict the code. | + +The principle that Javadoc should only explain what is *not* manifest from the signature is well-established in the +wider Java community. + +## Build & test commands + +Agents must verify that the project still compiles and all unit tests pass before opening a PR: + +```bash +# From repo root +mvn -q verify +``` + +## Commit-message & PR etiquette + +1. **Subject line <= 72 chars**, imperative mood: Fix roll-cycle offset in `ExcerptAppender`. +2. Reference the JIRA/GitHub issue if it exists. +3. In *body*: *root cause -> fix -> measurable impact* (latency, allocation, etc.). Use ASCII bullet points. +4. **Run `mvn verify`** again after rebasing. + +## What to ask the reviewers + +* *Is this AsciiDoc documentation precise enough for a clean-room re-implementation?* +* Does the Javadoc explain the code's *why* and *how* that a junior developer would not be expected to work out? +* Are the documentation, tests and code updated together so the change is clear? +* Does the commit point back to the relevant requirement or decision tag? +* Would an example or small diagram help future maintainers? + +## Project requirements + +See the [Decision Log](src/main/docs/decision-log.adoc) for the latest project decisions. +See the [Project Requirements](src/main/docs/project-requirements.adoc) for details on project requirements. + +## Elevating the Workflow with Real-Time Documentation + +Building upon our existing Iterative Workflow, the newest recommendation is to emphasise *real-time updates* to documentation. +Ensure the relevant `.adoc` files are updated when features, requirements, implementation details, or tests change. +This tight loop informs the AI accurately and creates immediate clarity for all team members. + +### Benefits of Real-Time Documentation + +* **Confidence in documentation**: Accurate docs prevent miscommunications that derail real-world outcomes. +* **Reduced drift**: Real-time updates keep requirements, tests and code aligned. +* **Faster feedback**: AI can quickly highlight inconsistencies when everything is in sync. +* **Better quality**: Frequent checks align the implementation with the specified behaviour. +* **Smoother onboarding**: Up-to-date AsciiDoc clarifies the system for new developers. +* **Incremental changes**: AIDE flags newly updated files so you can keep the documentation synchronised. + +### Best Practices + +* **Maintain Sync**: Keep documentation (AsciiDoc), tests, and code synchronised in version control. Changes in one area should prompt reviews and potential updates in the others. +* **Doc-First for New Work**: For *new* features or requirements, aim to update documentation first, then use AI to help produce or refine corresponding code and tests. For refactoring or initial bootstrapping, updates might flow from code/tests back to documentation, which should then be reviewed and finalised. +* **Small Commits**: Each commit should ideally relate to a single requirement or coherent change, making reviews easier for humans and AI analysis tools. +- **Team Buy-In**: Encourage everyone to review AI outputs critically and contribute to maintaining the synchronicity of all artefacts. + +## AI Agent Guidelines + +When using AI agents to assist with development, please adhere to the following guidelines: + +* **Respect the Language & Character-set Policy**: Ensure all AI-generated content follows the British English and ISO-8859-1 guidelines outlined above. +Focus on Clarity: AI-generated documentation should be clear and concise and add value beyond what is already present in the code or existing documentation. +* **Avoid Redundancy**: Do not generate content that duplicates existing documentation or code comments unless it provides additional context or clarification. +* **Review AI Outputs**: Always review AI-generated content for accuracy, relevance, and adherence to the project's documentation standards before committing it to the repository. + +## Company-Wide Tagging + +This section records **company-wide** decisions that apply to *all* Chronicle projects. All identifiers use the --xxx prefix. The `xxx` are unique across in the same Scope even if the tags are different. Component-specific decisions live in their xxx-decision-log.adoc files. + +### Tag Taxonomy (Nine-Box Framework) + +To improve traceability, we adopt the Nine-Box taxonomy for requirement and decision identifiers. These tags are used in addition to the existing ALL prefix, which remains reserved for global decisions across every project. + +.Adopt a Nine-Box Requirement Taxonomy + +|Tag | Scope | Typical examples | +|----|-------|------------------| +|FN |Functional user-visible behaviour | Message routing, business rules | +|NF-P |Non-functional - Performance | Latency budgets, throughput targets | +|NF-S |Non-functional - Security | Authentication method, TLS version | +|NF-O |Non-functional - Operability | Logging, monitoring, health checks | +|TEST |Test / QA obligations | Chaos scenarios, benchmarking rigs | +|DOC |Documentation obligations | Sequence diagrams, user guides | +|OPS |Operational / DevOps concerns | Helm values, deployment checklist | +|UX |Operator or end-user experience | CLI ergonomics, dashboard layouts | +|RISK |Compliance / risk controls | GDPR retention, audit trail | + +`ALL-*` stays global, case-exact tags. Pick one primary tag if multiple apply. + +### Decision Record Template + +```asciidoc +=== [Identifier] Title of Decision + +Date:: YYYY-MM-DD +Context:: +* What is the issue that this decision addresses? +* What are the driving forces, constraints, and requirements? +Decision Statement:: +* What is the change that is being proposed or was decided? +Alternatives Considered:: +* [Alternative 1 Name/Type]: +** *Description:* Brief description of the alternative. +** *Pros:* ... +** *Cons:* ... +* [Alternative 2 Name/Type]: +** *Description:* Brief description of the alternative. +** *Pros:* ... +** *Cons:* ... +Rationale for Decision:: +* Why was the chosen decision selected? +* How does it address the context and outweigh the cons of alternatives? +Impact & Consequences:: +* What are the positive and negative consequences of this decision? +* How does this decision affect the system, developers, users, or operations? +- What are the trade-offs made? +Notes/Links:: +** (Optional: Links to relevant issues, discussions, documentation, proof-of-concepts) +``` + +## Asciidoc formatting guidelines + +### List Indentation + +Do not rely on indentation for list items in AsciiDoc documents. Use the following pattern instead: + +```asciidoc +section:: Top Level Section +* first level + ** nested level +``` + +### Emphasis and Bold Text + +In AsciiDoc, an underscore `_` is _emphasis_; `*text*` is *bold*. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..dff4e186 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,107 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Chronicle-Algorithms is a zero-allocation, high-performance Java library providing efficient algorithms for: +- Hashing (CityHash, MurmurHash, XxHash) +- Bit set operations +- Raw byte access to data types +- Off-heap locking mechanisms + +Part of the OpenHFT Chronicle suite, this library focuses on performance-critical operations with minimal memory allocation. + +## Build and Test Commands + +### Building +```bash +mvn clean install +``` + +### Running Tests +```bash +# Run all tests +mvn test + +# Run a single test class +mvn test -Dtest=BitSetTest + +# Run a specific test method +mvn test -Dtest=BitSetTest#testFlip +``` + +### Code Coverage +The project uses JaCoCo for code coverage with targets defined in pom.xml: +- Line coverage: 57.9% +- Branch coverage: 36.4% + +## Architecture + +### Package Structure + +The codebase is organized into four main functional areas under `net.openhft.chronicle.algo`: + +#### 1. Hashing (`algo.hashing`) +- **LongHashFunction**: Abstract base class for all hash function implementations. Subclasses should implement methods for single primitives, `hashVoid()`, and the core `hash(Object, ReadAccess, long, long)` method. All other methods delegate to these. +- Hash implementations: `CityHash_1_1`, `MurmurHash_3`, `XxHash_r39` +- All hash functions produce cross-platform consistent results (same output on little-endian and big-endian systems), though performance favors little-endian platforms + +#### 2. Bytes Access (`algo.bytes`) +- **Access Pattern**: The core abstraction for reading/writing raw bytes from various data sources + - `ReadAccess`: Read operations on type T + - `WriteAccess`: Write operations on type T + - `Access`: Combines both read and write capabilities + - `AccessCommon`: Base interface with common metadata operations +- **Accessor Pattern**: Converts between source types and Access handles + - `Accessor`: Maps source type S to target type T with access strategy A + - Implementations for arrays, ByteBuffer, BytesStore, CharSequence +- **Key implementations**: + - `NativeAccess`: Direct native memory access + - `ByteBufferAccess`: Access ByteBuffer contents + - `BytesAccesses`: Access Chronicle Bytes BytesStore + - Array accessors for all primitive types +- The Access/Accessor pattern enables uniform byte-level operations across heterogeneous data sources (heap arrays, direct buffers, off-heap memory) + +#### 3. Bit Sets (`algo.bitset`) +- **BitSet**: Main interface with rigid `logicalSize()` (unlike java.util.BitSet which has dynamic capacity) +- **BitSetAlgorithm**: Static utility methods operating on raw memory via Access pattern +- **BitSetFrame**: Combines BitSet interface with Access-based implementation + - `SingleThreadedFlatBitSetFrame`: Optimized for single-threaded use + - `ConcurrentFlatBitSetFrame`: Thread-safe implementation with atomic operations +- **ReusableBitSet**: Adapter for reusing BitSet instances with different underlying storage +- All operations throw IndexOutOfBoundsException for out-of-bounds access + +#### 4. Locks (`algo.locks`) +- Off-heap locking strategies for concurrent access control +- **LockingStrategy**: Base interface for lock/unlock/reset operations via Access pattern +- **Lock state interfaces**: Separate state from strategy + - `ReadWriteLockState` / `ReadWriteLockingStrategy` + - `ReadWriteUpdateLockState` / `ReadWriteUpdateLockingStrategy` (adds update locks) + - `ReadWriteUpdateWithWaitsLockState` / corresponding strategy (tracks waiting threads) +- **AcquisitionStrategy**: Defines try/lock behaviors (`TryAcquireOperation`, `TryAcquireOperations`) +- Vanilla implementations: `VanillaReadWriteUpdateWithWaitsLockingStrategy`, `VanillaReadWriteWithWaitsLockingStrategy` +- All locking is managed through the Access abstraction, enabling off-heap lock storage + +### Key Design Patterns + +1. **Access/Accessor Abstraction**: Unified interface for byte-level operations on diverse data sources. Access defines operations on a handle type T, while Accessor converts sources to Access handles with offset calculations. + +2. **Zero-Allocation**: Algorithms are designed to avoid object allocation in hot paths. Prefer primitive types, reuse objects (e.g., ReusableBitSet), and operate directly on raw memory. + +3. **Off-Heap Support**: All core algorithms work via the Access pattern, allowing operations on off-heap memory without GC pressure. + +4. **Strategy Pattern**: Locking and hashing use strategy interfaces to allow algorithm selection and customization. + +## Dependencies + +Core Chronicle dependencies: +- `chronicle-core`: Foundation utilities +- `chronicle-bytes`: Byte buffer abstractions + +Test framework uses both JUnit 4 and JUnit 5 (Jupiter), plus Mockito for mocking. + +## License + +Apache 2.0 (SPDX-License-Identifier: Apache-2.0) +Copyright 2013-2025 chronicle.software diff --git a/README.adoc b/README.adoc new file mode 100644 index 00000000..7236bab1 --- /dev/null +++ b/README.adoc @@ -0,0 +1,183 @@ += Chronicle-Algorithms +:license: Apache 2.0 +:toc: macro +:toclevels: 3 + +image:https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms/badge.svg[link="https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms"] +image:https://javadoc.io/badge2/net.openhft/chronicle-algorithms/javadoc.svg[link="https://javadoc.io/doc/net.openhft/chronicle-algorithms"] +image:https://img.shields.io/badge/License-Apache%202.0-blue.svg[link="https://opensource.org/licenses/Apache-2.0"] + +Chronicle-Algorithms is a Java library providing zero-allocation, high-performance algorithms for hashing, bit set operations, off-heap locking, and low-level memory access. It is designed for latency-sensitive systems where garbage collection pauses are critical concerns. + +toc::[] + +== Features + +* **Hashing**: Non-cryptographic 64-bit hash functions including CityHash, MurmurHash3, and xxHash +* **Bit Sets**: High-performance, rigid-capacity bit sets with both single-threaded and concurrent implementations +* **Bytes Access**: Unified abstractions for accessing raw bytes from diverse sources (arrays, ByteBuffers, Strings, off-heap memory) with zero allocation +* **Locking**: Off-heap read-write-update locking strategies for concurrent access control + +== Hashing + +The library provides a unified API for several non-cryptographic 64-bit hash functions through the `LongHashFunction` class. These implementations are optimized for performance, produce consistent results across platforms (big-endian and little-endian), and generate zero garbage. + +=== Supported Algorithms +* **CityHash 1.1**: Based on Google's CityHash algorithm +* **MurmurHash3**: Based on the SMHasher suite implementation +* **xxHash r39**: Based on Cyan4973's xxHash (r39 revision) + +=== Usage Examples + +[source,java,opts=novalidate] +---- +import net.openhft.chronicle.algo.hashing.LongHashFunction; + +public class HashingExample { + public static void main(String[] args) { + String input = "Hello World"; + + // Get an instance of the hash function + LongHashFunction xxHash = LongHashFunction.xx_r39(); + + // Hash a String + long hash = xxHash.hashChars(input); + + // Hash a primitive + long longHash = xxHash.hashLong(123456789L); + + // Hash a byte array + byte[] data = new byte[] {1, 2, 3, 4, 5}; + long bytesHash = LongHashFunction.city_1_1().hashBytes(data); + + // Hash off-heap memory (unsafe access) + // long address = ...; // unsafe memory address + // long length = 64; + // long memoryHash = LongHashFunction.murmur_3().hashMemory(address, length); + } +} +---- + +== Bit Sets + +The `net.openhft.chronicle.algo.bitset` package provides `BitSet` implementations that operate over raw memory or byte stores. Unlike `java.util.BitSet`, which has dynamic capacity, Chronicle bit sets have a rigid logical size and throw `IndexOutOfBoundsException` for out-of-bounds access. + +=== Implementations +* **SingleThreadedFlatBitSetFrame**: Not thread-safe, optimized for single-threaded access. +* **ConcurrentFlatBitSetFrame**: Thread-safe implementation using CAS (Compare-And-Swap) operations for concurrent access. + +=== Usage Examples + +[source,java,opts=novalidate] +---- +import net.openhft.chronicle.algo.bitset.BitSetFrame; +import net.openhft.chronicle.algo.bitset.SingleThreadedFlatBitSetFrame; +import net.openhft.chronicle.algo.bitset.ReusableBitSet; +import net.openhft.chronicle.algo.bytes.Access; +import java.nio.ByteBuffer; + +// Create a frame definition for 64 bits +BitSetFrame frame = new SingleThreadedFlatBitSetFrame(64); + +// Create a ByteBuffer to back the bit set +ByteBuffer buffer = ByteBuffer.allocate(8); // 64 bits = 8 bytes + +// Create the ReusableBitSet wrapper +ReusableBitSet bitSet = new ReusableBitSet(frame, Access.checkedByteBufferAccess(), buffer, 0); + +// Operations +bitSet.set(1); +bitSet.set(3); +boolean isSet = bitSet.get(1); // true +long nextSet = bitSet.nextSetBit(0); // 1 +---- + +== Bytes Access + +The `net.openhft.chronicle.algo.bytes` package provides a unified `Access` and `Accessor` abstraction to read and write primitives from various underlying sources without creating objects. This enables zero-allocation operations across heterogeneous data types. + +=== Supported Sources +* **Native Memory**: Direct access via `Unsafe` +* **ByteBuffer**: Both heap and direct ByteBuffers +* **Arrays**: All primitive array types (`byte[]`, `long[]`, `int[]`, etc.) +* **CharSequence/String**: Efficient access to String internals (supports compact strings in Java 9+) +* **BytesStore**: Chronicle Bytes abstractions + +[source,java] +---- +import net.openhft.chronicle.algo.bytes.Access; +import net.openhft.chronicle.algo.bytes.NativeAccess; + +// Native access singleton +Access unsafeAccess = NativeAccess.instance(); +long value = unsafeAccess.readLong(object, offset); +---- + +== Locking + +The `net.openhft.chronicle.algo.locks` package provides logic for read-write-update locks that can be stored off-heap or in shared memory. + +* **Read Lock**: Multiple readers allowed. +* **Update Lock**: Only one update lock allowed, but allows concurrent readers. Can upgrade to Write Lock. +* **Write Lock**: Exclusive access. + +=== Locking Strategy +The primary implementation is `VanillaReadWriteUpdateWithWaitsLockingStrategy`, which supports: +* Lock upgrading (Read -> Update -> Write) +* Lock downgrading +* Waiting strategies + +== Maven Dependency + +To include Chronicle-Algorithms in your project, add the following dependency to your `pom.xml`: + +[source,xml] +---- + + net.openhft + chronicle-algorithms + 2.27ea1 + +---- + +NOTE: Check link:https://search.maven.org/artifact/net.openhft/chronicle-algorithms[Maven Central] for the latest available version. + +== Building from Source + +To build the project locally: + +[source,bash] +---- +# Clone the repository +git clone https://github.com/OpenHFT/Chronicle-Algorithms.git +cd Chronicle-Algorithms + +# Build and run tests +mvn clean install + +# Run specific test +mvn test -Dtest=BitSetTest +---- + +== Support + +For questions, issues, or feature requests: + +* GitHub Issues: https://github.com/OpenHFT/Chronicle-Algorithms/issues +* Documentation: https://javadoc.io/doc/net.openhft/chronicle-algorithms +* Chronicle Software: https://chronicle.software + +== Related Projects + +Part of the OpenHFT Chronicle suite: + +* link:https://github.com/OpenHFT/Chronicle-Core[Chronicle-Core] - Low-level utilities and memory management +* link:https://github.com/OpenHFT/Chronicle-Bytes[Chronicle-Bytes] - Zero-copy bytes abstractions +* link:https://github.com/OpenHFT/Chronicle-Queue[Chronicle-Queue] - Persisted low-latency messaging +* link:https://github.com/OpenHFT/Chronicle-Map[Chronicle-Map] - Off-heap key-value store + +== License + +Copyright 2013-2025 chronicle.software + +Licensed under the Apache License, Version 2.0. See the link:LICENSE[LICENSE] file for details. diff --git a/README.md b/README.md deleted file mode 100644 index 4ee14d18..00000000 --- a/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Chronicle-Algorithms - - - - - - - - -Zero allocation, efficient algorithms for - -- hashing -- bit set operations -- access the raw bytes of an data type -- off heap locking From 43208dd1cd96389cc109aa9b4257906902f11a69 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 20 Nov 2025 19:36:52 +0000 Subject: [PATCH 03/15] Add parameterized tests for XxHash functionality --- .../hashing/reference/City64_1_1_Test.java | 2126 ++++++++++++++++ .../algo/hashing/reference/XxHashTest.java | 2128 +++++++++++++++++ 2 files changed, 4254 insertions(+) create mode 100644 src/test/resources/net/openhft/chronicle/algo/hashing/reference/City64_1_1_Test.java create mode 100644 src/test/resources/net/openhft/chronicle/algo/hashing/reference/XxHashTest.java diff --git a/src/test/resources/net/openhft/chronicle/algo/hashing/reference/City64_1_1_Test.java b/src/test/resources/net/openhft/chronicle/algo/hashing/reference/City64_1_1_Test.java new file mode 100644 index 00000000..73654f38 --- /dev/null +++ b/src/test/resources/net/openhft/chronicle/algo/hashing/reference/City64_1_1_Test.java @@ -0,0 +1,2126 @@ +/* + * Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ +package net.openhft.hashing; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Collection; + +import static org.junit.runners.Parameterized.Parameter; +import static org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class City64_1_1_Test { + + @Parameters + public static Collection data() { + ArrayList data = new ArrayList(); + for (int len = 0; len < 1025; len++) { + data.add(new Object[] {len}); + } + return data; + } + + @Parameter + public int len; + + @Test + public void testCityWithoutSeeds() { + test(LongHashFunction.city_1_1(), HASHES_OF_LOOPING_BYTES_WITHOUT_SEEDS); + } + + @Test + public void testCityWithOneSeed() { + test(LongHashFunction.city_1_1(0L, 0L), HASHES_OF_LOOPING_BYTES_WITH_SEEDS_0_0); + } + + private void test(LongHashFunction city, long[] hashesOfLoopingBytes) { + byte[] data = new byte[len]; + for (int j = 0; j < data.length; j++) { + data[j] = (byte) j; + } + LongHashFunctionTest.test(city, data, hashesOfLoopingBytes[len]); + } + +// The following numbers is the result of compiling & running this program +// with city-1.1.1, reference impl: +// +// #include +// #include +// #include +// +// main() { +// char* src = (char*) malloc(1024); +// for (int i = 0; i < 1024; i++) { +// src[i] = (char) i; +// } +// printf("without seeds\n"); +// for (int i = 0; i <= 1024; i++) { +// printf("%lldL,\n", (long long)CityHash64(src, i)); +// } +// printf("with seeds 0, 0\n"); +// for (int i = 0; i <= 1024; i++) { +// printf("%lldL,\n", (long long)CityHash64WithSeeds(src, i, 0, 0)); +// } +// } + + private static final long[] HASHES_OF_LOOPING_BYTES_WITHOUT_SEEDS = { + -7286425919675154353L, + -4728684028706075820L, + -4422457430495752843L, + -7736835464683084646L, + -9025216361070533312L, + -5422428610433466039L, + -7854914535251369165L, + -6710152398449367391L, + -5955425696247891048L, + -9135800243314829233L, + -7246206370539175958L, + -927412511068636451L, + -6929387038567547523L, + -4483949857698136942L, + 5465584872023869041L, + -8779115096593678947L, + 1080060857502750420L, + -4920561954712641764L, + 8788987475711186918L, + -7811586469569372367L, + -8225851168889855767L, + -1446326939218740700L, + 2947276334089957408L, + 460179928224693724L, + 4556289589497654983L, + -5431404645194118082L, + 1374684061788708333L, + 4791352535680686582L, + -6530211739313377370L, + -7635818062080712801L, + 5236473510478810791L, + -299119187023926975L, + 1917831512995979081L, + 5107424530006203066L, + -5351750064093194974L, + 2946934858665984768L, + 5031111514403073L, + 3910662880520648515L, + 7104787927248062489L, + -6487722535395806461L, + 3960877915061173532L, + -4579031603096916569L, + -3869369943781850205L, + 5545493761745899838L, + -7059462733818922495L, + 6807020698875987225L, + -404529411533207610L, + -5190881841756839606L, + -4104575122654935515L, + 6967381383547484689L, + 8297988497614279881L, + 8680592459788761385L, + -3059691078085565528L, + -6315132929596828281L, + -4334276152181959987L, + -535710436645363679L, + -7591547014909512897L, + -6322657031286798644L, + 7490021577199580942L, + -8877856250499437898L, + -1633403071681209495L, + -5579376360386761981L, + 3395840816824425443L, + -5822993263498516753L, + -1613775140304724827L, + -6027895920215728850L, + -5805352503949881486L, + 1532677441468290047L, + -8648407032749049966L, + -2939164377159033571L, + -4702680364495832252L, + 105631500981943270L, + -7893756812661322999L, + 5760642662739372587L, + -6215695861042047454L, + 1238201813735746316L, + -4809334409104512081L, + 2347957779168721077L, + 9062861991168352058L, + 6741188021946160720L, + 5759783405795756054L, + -7404571833801891275L, + 5236586458250640726L, + -6440402695065204540L, + 7127501107294950542L, + -8740931757300170334L, + 5534676620576843972L, + -4574941845361945294L, + -9883751627416689L, + 7607362424232991178L, + -3354796234778573261L, + -3645150900513625504L, + -6488903739323758581L, + 6012082827380234497L, + -5054558154612698247L, + 3912192630192643044L, + -2020201547348302146L, + -5668877223161468438L, + 8268442247828559279L, + -5794570113714942465L, + -6593295974839137082L, + -3017674363433867291L, + 9132819821668885553L, + 4741264366937614131L, + 830814054897026754L, + -2034640718262093716L, + 8943931193848644945L, + -8152524248109219563L, + -6859491045979443967L, + 5989638100417143996L, + -3267834036936991810L, + -7636942225548479235L, + -4414857242429251885L, + -2291796691719558349L, + -443263958430047225L, + 7365713933907296010L, + -3873163659277696512L, + 3210434025964027265L, + 4488179162024237572L, + -4930451962295763338L, + 7001793786790109268L, + 2260583935679101347L, + 6302158474829298170L, + -2419988900997440242L, + -8014717202309677597L, + -8235679274201152527L, + -5412354269470908685L, + -1164721218407162475L, + 1202834260335129493L, + 5097669210588415856L, + 5123804704029457567L, + -6598196598389898964L, + -6869069910041547416L, + -928355525786123860L, + -966564912375064896L, + 4636972776252349972L, + -2242946385954433108L, + -2308096272056919881L, + -6298993315544438985L, + -3151578775439575412L, + -2981346332242477399L, + 6868228731909122983L, + -6986102546523057772L, + 3966488015587306733L, + -7964296030132213922L, + -5968054086424703428L, + -5682984903553203201L, + 1262045945453884357L, + -8506021221334832979L, + 7003579340962719964L, + 7942843347128085593L, + 3274150487722006282L, + 4427242625667076769L, + -5558614835558052533L, + 8189732125765662222L, + -2778584257768737506L, + -6226635033105800171L, + 7651720467242209474L, + 9181931113760444130L, + 2531900585268751432L, + 5021256001343290469L, + -5934384589108485717L, + -1862924803786167203L, + 1489099108801110675L, + 7297283605813218793L, + -8415280978394092215L, + -4126156388588540951L, + -3706737886726786804L, + -2710208030451980715L, + -8047451206915723423L, + -1218572947384892459L, + 8297865478600584233L, + 8165902466320925460L, + 5554419482037121102L, + 4417403317404803986L, + -6616982450866646170L, + -7959099281697237016L, + -3114405717510473052L, + -1857505830677138154L, + -1018685550688766348L, + 5207428187340024429L, + 5300227297807876147L, + -2390037343420204123L, + -448127685853213712L, + -6225388303620718856L, + 2389000856964185630L, + -2067625213238325040L, + -241429434055336511L, + -8970491894816477388L, + -6897203400744644612L, + -4604959413085934526L, + 2400135546673933001L, + -3045961230403678092L, + -1917277105023051478L, + 8197811581050490133L, + 3786786968548875789L, + 4625663088087573665L, + -2168704627193825976L, + 7192692656796588680L, + 2481695319570886548L, + -805495018187668520L, + 5671304642231997436L, + -4228301512035074347L, + -7701083686405511339L, + -1427738904980858657L, + 8356642386295377804L, + -353719534132831289L, + 706229336943583572L, + -9168064130899442751L, + 8265029971140615336L, + -2707147319767299550L, + 7353033265757382049L, + 8397636325397273152L, + -6517736165712294631L, + 6949546038097145245L, + 1648771344345529694L, + 6558709565158356186L, + 1808377088858220390L, + 2838565433860722913L, + 1308279908036033190L, + 8824692270735996388L, + 4066525655875567756L, + 5152272828145679687L, + -3469524600427842330L, + 188800643931297464L, + 7173304178017026190L, + -5347641926849324594L, + -8829553366459830305L, + 8778291414581187896L, + 593871733331593377L, + 2192404833132388154L, + -3564506003420601160L, + 2859700462125450624L, + -7123068915788342214L, + -9199725509076335326L, + 4749263509373213952L, + -3638383731952186227L, + -6283092296877861618L, + -2825268767310280965L, + 7643742019486170884L, + 7034401305567905177L, + -31827767771004462L, + -3569709783922447606L, + 1011781009512126791L, + -5982832679535324039L, + 2402494289382923228L, + 5378572830995800063L, + -4978012351095471455L, + -3034756850229693434L, + -6743229956355567041L, + -1028117510121450274L, + -1267497062066519287L, + -5053670629173080711L, + -460732196015338926L, + -6371275689446166637L, + 6288834997689259448L, + 894299094737143437L, + -6014774806034970825L, + -3271595897687689742L, + -7449732170732070004L, + 506523418677247916L, + -687365991489907728L, + 8228603339396783688L, + 7211450665110285461L, + -3009830902792319569L, + -5417937957852652579L, + 6051039017008413932L, + -5925978207158526805L, + -2615140071349844608L, + -8654933370440320601L, + -6342253313262031587L, + 4461643906497668150L, + -819522441838551231L, + -1359425915347178296L, + 1075135447892840058L, + 7643058122247322338L, + -4070529264423045602L, + 6335201156325848872L, + 4776486447069195757L, + -4254562051076226566L, + 5766929006988848669L, + -884034037937901831L, + 1766456663364676290L, + -4311719146183820266L, + 7666581505151857266L, + 671421170492658629L, + -1964099404051832475L, + 1732360456059290553L, + -297869400412879955L, + -9030316701971057409L, + -9075660047343779046L, + 3583673289738670454L, + -9182941546024088613L, + 1136735461790749536L, + 8366765554392407195L, + -5540891596657836355L, + -7821100180551973617L, + -1977279128251662041L, + -2356171669808568513L, + -2015573691705664756L, + 4488487306883615842L, + 4851354791727756109L, + -3251092166327359481L, + -601646434326145067L, + 776101951221215280L, + -6668237828878985553L, + 7844860178588967334L, + 64341060285013340L, + 7036395122924142569L, + -7724784063616999535L, + 2914805329168628994L, + 7621906733182421570L, + 2118815299569935033L, + -8611860394051996699L, + -2517166550051884828L, + -6993083065762083347L, + 2404060287424189503L, + -8081836069740145167L, + -6067471269374793929L, + 3439258482592575547L, + -6466818119401182672L, + 1855293097271252452L, + -6761456087842467624L, + 6656763620585181420L, + -4645642491601388295L, + -8829570488301084514L, + -6279091021271619556L, + -1913500423661250093L, + -8293385927741834686L, + -808977409753631920L, + -2730813255791690623L, + 760899304567634337L, + 3447062143237006129L, + -8842923486609316688L, + -1505518261280441404L, + -8952792346352363916L, + -3654437654855386526L, + -8894745855055459645L, + 253433424322101103L, + 9087982386284623409L, + 5229689677888986164L, + 7591231218923024443L, + -6553455979736582189L, + -6817900072998950224L, + 1012237197570815938L, + -1041501749233381438L, + 6870652863042402620L, + 7290269702536111943L, + -2011669460814939543L, + -4739132450972235476L, + 6066906978691731285L, + 1546459970278232517L, + 7264475946711979454L, + -6827279988316999463L, + 6948666464698968123L, + 5066099854277588391L, + 3617923505625432817L, + 1470423865947425164L, + -2407848614631507329L, + -2721518777381923816L, + -8523365410901703222L, + 4677154254765168702L, + -3770388132335360433L, + 2921549272211529780L, + -675990637368864946L, + 851813270104783927L, + 1645312556841013286L, + 7927523946826503527L, + 2802530705554935060L, + 4420122776914984561L, + 5168061431322460870L, + -3637982376709290280L, + -4792218222117838791L, + -1594804027447799011L, + 7019536217023665362L, + 5718841507582027847L, + 1100038721024625254L, + 4344644567377313784L, + 8200393826966791959L, + 8894425291364977602L, + 2359988989741956746L, + 33375660597707981L, + 3669152498936403685L, + -2718673953441374568L, + 92663594252170279L, + -4255839685607808051L, + -712976418504655651L, + 4188336312392147780L, + 2678387573955385138L, + 5321904963044271153L, + -6249628719291181094L, + -8876650223107687355L, + 8352423161613591273L, + -2028799093461825949L, + 9011909818387084247L, + -5940434430375305675L, + 3490020360211624506L, + 8424335559697179192L, + 3222699924556192045L, + 7964158943145881894L, + 330499497334085755L, + 8764983981643618893L, + -1653480401860466428L, + -1353880172593700164L, + -6469256613830029852L, + -4893038789738483635L, + 8164190368596497481L, + 5278453078131476326L, + 910888251237419688L, + 3697943209022914547L, + 5449624560010431329L, + -3584621013753301872L, + 654189080535454533L, + -7562028051554401340L, + 8924718183483314324L, + -1485127518392421693L, + 3918745837987619627L, + -4539406462388765487L, + 5483323815514497307L, + 6306137176139938292L, + -807721373860280201L, + -9165053290624784358L, + 2697602178198341027L, + 4348395670472375164L, + -400178961926803853L, + -7689451542459549880L, + 4509866787834747782L, + 9185710136408363969L, + 7923865403849230565L, + -5869104529577485293L, + 4854955700697037319L, + 9191216701481807090L, + -679449825281621614L, + -3189846996545570031L, + -8083169535868277187L, + -9174257325298378624L, + -4552176765196275L, + 1628631992923682209L, + 8319654855481955340L, + 8861739932800214810L, + -993117140134665724L, + -7815627532394322917L, + -5524260825536443502L, + 6983369624720592264L, + 2975165537865741602L, + 1451865941470664872L, + 8661262499023857011L, + 9204748273209932460L, + -5006258975566865529L, + -1964973191525498109L, + -6345850612890808987L, + 6330350968582806446L, + -4566626859227178484L, + 4080473761572400112L, + -6346529945189783184L, + 7055723585952818695L, + 7811169230131832954L, + -7306057383456388215L, + 5652715072883610701L, + -2250631360270905098L, + 8948341566778589071L, + -7814352745627737399L, + -2083093040021743435L, + -4144374577642832518L, + 4554659244267885692L, + -4805527992091411974L, + 3879386590110957199L, + -7095733810311131713L, + 4218157720399299286L, + -3959329580238802474L, + 1731201417108224317L, + -8732695545326287246L, + -8127721874141088173L, + 2847953048942004818L, + -2848770956679986940L, + 1154351656441528122L, + 4106410957236720378L, + 477496151948916105L, + 8872899165245904476L, + 3834365941712504069L, + 8233875208097499501L, + 6544005900573385217L, + 371511961864400977L, + 5302630743605424838L, + 7619059416641067912L, + 938163523491488924L, + -2193498991179441780L, + -4381948476662408917L, + 2437161357208041044L, + -1853214813114072629L, + 4032256607594450812L, + -4569645391300269034L, + 996805768016039863L, + -5352653220786799159L, + -4072867815316954984L, + 5829678081429819442L, + 5854970045203806958L, + 7196705546676684298L, + 8855821442059151758L, + 1691257326941530873L, + 516443419472701223L, + -189326359229885042L, + -7069256705822756785L, + 8484184957260042276L, + 4751495376086537417L, + -3538622506527375158L, + -1130604628135516641L, + -662884267626379918L, + -1626547571415880505L, + 4362310446718468471L, + -4692137164995780722L, + -1878686192989058772L, + -1262801893323802033L, + 316850896103923056L, + -8337266500312820398L, + -7607930981261565972L, + -7606942324380249703L, + -1863279537410737853L, + 515589381621691011L, + 1963273998306328480L, + 3626876516104382454L, + -4734613701579936168L, + 1268078677159514015L, + -7562820495728610458L, + -5881301520585529952L, + 7263589689395116216L, + 3332748335049164596L, + -928492619425385303L, + -8439668591687876707L, + 6057690584855876482L, + 7709510645357107021L, + 688216636303161488L, + 191126336719796113L, + 4222857931985709754L, + 5163370007345445271L, + -6942747002185630386L, + -2732326623400822979L, + 41325922645173190L, + 4083911336538913161L, + 3094117323938386883L, + 3557206941692843782L, + -2802805090114871259L, + -396752131642527880L, + -3107705530439472535L, + 8070257791496704758L, + 5555978803158201323L, + 4409520550497292548L, + 6336286888800178635L, + 3317356027694838288L, + 2401575734406277533L, + -7762952901621766636L, + -8495556902666486415L, + -6098553262029734092L, + 364791930541331805L, + -3034434066885855765L, + 7941447497229394663L, + -6311456469393535820L, + -3224469377911062967L, + 8110978943348454528L, + 7644406205313833523L, + 8931656291415416874L, + 4830016430262424325L, + -8438474386071045565L, + 6477831547342095051L, + 3795147179128460013L, + 2753065962007277619L, + 6069828580914843210L, + -5070382024314025872L, + 1576707579300544287L, + 5453704031214058740L, + -1035262976071773160L, + 3387395655425490542L, + -4848984716268304731L, + 8616838443866781524L, + -3948140786885003158L, + 3962330984502924344L, + -3394110440125760919L, + 8437322113039475260L, + -4462275713722410457L, + -9105148434050568503L, + -5788212949545869877L, + 4557608001681875598L, + -621234956095881342L, + 1797543657423762991L, + 6130226975770239840L, + -6937918406956986622L, + 4193803048882394276L, + 4324662453655033332L, + 3904929732026970589L, + -5512830190293331704L, + -5238129213566557209L, + 540373761178912749L, + 3337453168137959715L, + 8356242320057396388L, + -4507786512266822044L, + -698048955859231008L, + 1181416669291835619L, + 3643161574413908044L, + -4297980572116458092L, + -2910009689167799889L, + -9219400384203405648L, + 2837257119074162583L, + -8143475796343843303L, + -6701262784428931798L, + -3566846192190811525L, + -5826064075185101904L, + 7314616728107169430L, + -7237382661205518959L, + 6614127174385956622L, + 4579105225630387051L, + -4031772022249101869L, + -3620132425485383754L, + -6583523957977840094L, + 6091510613049819644L, + -6657436664451253776L, + 8818554346883882723L, + 1172158546676437076L, + 2582843905454312864L, + -875396097026320083L, + -8848203911887421254L, + 6216447546397552656L, + 5663680539561409764L, + 209883782871623112L, + 6956397065493936061L, + -5822486364606447659L, + -2376186988282686016L, + -6524574392506270574L, + -5270703630108479361L, + 5121019866792000912L, + 945935884404515280L, + -3784584736823369966L, + -2986471018582996853L, + -3856234881587215840L, + 6305579424806652269L, + -4601892864817094249L, + -4715544044948588160L, + -1178634098444085344L, + -4565928887270776879L, + 3733099898005319061L, + 6069592779991791222L, + 9107963518416746035L, + 6039316923758014718L, + 8297782059544644167L, + -2184105415491254451L, + 2001634139595818848L, + 9198267247175603385L, + -971507504085650973L, + 1529684592715776773L, + -6499571738329764748L, + 2692794621907637848L, + 3620078955080706311L, + -3810905539411016286L, + -4315538097904969971L, + 238288165777703356L, + 3801607999515704624L, + -8796282819004971627L, + -7143692292464130110L, + -2163491158557034519L, + -9011885533150911632L, + 9155112387717094928L, + 9088915215752483036L, + -1237520018892636128L, + -6753599194173607835L, + 336577035174699985L, + 4747700477808735060L, + 931844140272524176L, + -4257344590201194145L, + -670422981995636407L, + 2500401999619637609L, + 7406487034015272912L, + -384292968442149342L, + -7987787036136248263L, + -2653231840350927715L, + 4488358012056331513L, + 4132004061554806745L, + 2000006126034333275L, + 2367660688967266790L, + -4085353431072751340L, + -6333747719369049272L, + -4139886406965236122L, + -5592180402897144267L, + 5629551944241090329L, + 2272991263231641145L, + -5168344584178448710L, + 5982172003825524793L, + -4097896509839310227L, + -2173000713225115918L, + 7108547918299652551L, + -8878799355822473463L, + -6248630805665498946L, + 5163839098786800196L, + 5795734275921137263L, + -7245153276785179186L, + -7094809303783005595L, + -1803470859826091831L, + 4874431305017870420L, + -8839194352522271777L, + 4701999825563368375L, + -3679426707168942163L, + 4734328664805795607L, + -768556148270379847L, + 3947269125893368179L, + 4714950126806030589L, + -5247268458767477724L, + -1879729542263864540L, + 1641255074942093290L, + -9116204329902429525L, + -364742432814767105L, + -69357515456246742L, + 8333855547662608034L, + 1864002674034900754L, + 6403905632971416781L, + -7065616950334616275L, + -8174670288470068397L, + -1788643243994894927L, + 2040528535819048731L, + -7614591261684631428L, + -8476219755505693753L, + 3296595282811904830L, + -4038686171536252708L, + -173444937930635352L, + 4379378816273396403L, + -1083617946856135532L, + 2829396743633429008L, + 7647167960435994992L, + -6693126224881188257L, + 3108807460115157477L, + 8562491110202112769L, + -7424963641864880746L, + 2081921398431501385L, + 5209400744054399273L, + 5112090417850934870L, + 1524655582665697947L, + -5843275962356379462L, + -6334239724025378211L, + -7268154201988435641L, + 1659668141032724392L, + 7389323132785440806L, + 5590854007476007348L, + 5302894709895800109L, + 8939357616797202357L, + 8822514621675961012L, + -5171376528302818295L, + 1884135603723970677L, + 1618024292298833293L, + -1237011265202015266L, + -8040883111734337726L, + -5506883502078400727L, + -5535461054765222007L, + 6987425158845534706L, + -5917819605734669552L, + -128823547864917643L, + 2306699256825946343L, + 6578043582810501418L, + 1333071240688068841L, + -844978627973023134L, + 1165513423049959936L, + -3821092351522083096L, + 4178119893083594287L, + -7966305568215876834L, + -3090958372925773111L, + 6379864721688110803L, + 8454365886776707192L, + 7642874047594127629L, + -657318587403536924L, + 3801960633076006868L, + 1417228866369858393L, + -6177293427545629057L, + -4532758952191612784L, + 7264967871106174537L, + -4377935371893251778L, + -5733943093645858937L, + -6680841553969427023L, + -7726067291839077718L, + 8383662776008964734L, + -1112744575338004890L, + 6374190320986843773L, + -8999217966784745583L, + -7597176706996915696L, + -1016011267603323245L, + -8855672237269976658L, + 1866081428501204101L, + -5633137211449093941L, + -3633923734370033552L, + 6356569017217682507L, + 5058160257775482340L, + -7437707824467063063L, + 7650351067322618291L, + -7870694419219039600L, + 1007692631473636679L, + -6154343863836713521L, + 2504745592130278975L, + 88486550721415362L, + -7438916213215366445L, + 2983976134777543021L, + -4146088135092960461L, + 6999580209156770608L, + -7009740189170395954L, + 4126839178241879770L, + 5225682274323639211L, + 4660353570181491047L, + -3242111597353447920L, + 1803242034579090657L, + 8094113187590542457L, + 7111382607287164209L, + 3662908704051040727L, + -3379205925121269346L, + 6747462450220404315L, + 65992546736538642L, + 8188714708026451259L, + 7059032778575684879L, + -4375005614825264977L, + -6109413170920934528L, + 4325812979374770173L, + 6190341203443080272L, + 3806377003483660789L, + 7584471990548161252L, + -3767546025951476771L, + 5011498119849592471L, + 4585280751135869910L, + -2774285440269761924L, + -2219523968621249741L, + -6788014939853324942L, + -6760697001786001699L, + -1907834706280913583L, + 2768880461784823049L, + -629361951557696226L, + -5050911681363224361L, + -9166005476966639742L, + 31804289095347444L, + 639074948574684643L, + 6010055855691161228L, + -6702617244872776165L, + 4147599647636813218L, + 7651401543024655900L, + 4739867532288311604L, + -7311026522201000188L, + -2481600927193112363L, + -4295248724569156530L, + 5040986942772410406L, + 8763074685442978007L, + -7780650549244157320L, + 4727619369834180192L, + 8711570616947608575L, + 2722322146515041536L, + 5060226879657446005L, + -6544404061220128813L, + 6434919141259253970L, + -5427874400580062812L, + -7156085410253767250L, + -6601841961191942213L, + -9147266855024119868L, + -354433397501853706L, + -6814497327235846905L, + -8982035476653972472L, + 8930700532836854232L, + -1726278544235169634L, + 1951478969618711815L, + 851982242210611420L, + -6990203687021297279L, + 1368571238713408667L, + 2986039481571029352L, + -626535432523998987L, + 4415114859836957989L, + -8678134461890671357L, + -6061358215352047476L, + 7915140762335918295L, + -8378664661437708973L, + -3058127489434967617L, + 6225893737093916241L, + -1787758126471351031L, + -393755980982643891L, + -5268722683029966701L, + 4156689635576901740L, + 7365991146882099857L, + 8946946338475364603L, + 7319960897807520998L, + -2393576873586390100L, + 8152201155239646390L, + 115383870797338026L, + -7773145637941940242L, + -318186749599182520L, + 3089445632531235737L, + 7372359700832992279L, + -684419690766751897L, + 8663412456358708908L, + -8423162022518559117L, + -8645640258213218521L, + 3755512748576611566L, + -3913197578066841395L, + 5316673743969283163L, + 6831695766395531003L, + -8386643932900364475L, + 2245144203632789924L, + 5811854679522258384L, + -3767061474776765896L, + 5961692927981326209L, + -8247190832034282434L, + -2778260837579024711L, + -5629023501990762250L, + 8537394932332054145L, + -6062925171595331986L, + 6840408648564451314L, + 6831505181423122970L, + 6050924032963061444L, + 97002770831342714L, + -5440958264654316884L, + -8531281358297662856L, + -5585494473146494361L, + -8316232109598521210L, + -5015449123380194340L, + 546734480177265602L, + 4311680116951854912L, + -5000334068336613611L, + 5095429433761178592L, + -8984703830265496675L, + -1796164578353805109L, + -7862084290604723254L, + -3341202509537190675L, + -2120175014098274861L, + 6962378115816372563L, + 8337372275175376334L, + 2619274369511557562L, + -6859437991409806193L, + -6934562751052811686L, + -361162941396148816L, + 3477913128345375098L, + 6500092632270742214L, + -7787173285733693207L, + 1702735166445523176L, + 1447314647588646838L, + -6166213076072914876L, + 8250474851845160242L, + 3877968303074149070L, + 72258823402464273L, + -7794958806496084829L, + 582313431235093783L, + 5654370140388242557L, + 2361322084587394780L, + 7098843402525243411L, + 3090863845420947690L, + 9095251832683567577L, + 7351973108085879975L, + -5523854289062931886L, + 1385990973911762672L, + -1056696196230341112L, + -4777822501121417674L, + 7453925677222043959L, + 4245544569709356516L, + 4912957528661637311L, + -7303723525646889588L, + 8383839844005204972L, + 2636108895426426864L, + 7446083165659408850L, + -1230331481495042331L, + 2165552178018697300L, + 8589713469255323753L, + -104035337559208181L, + 9109517341871300972L, + -5557606019056305482L, + -2082770932342226712L, + -7664170423633849264L, + -6739763730657282594L, + 4217727556012572028L, + -4230549046719159326L, + -7870215613010795436L, + -1573598371112622115L, + 8374003956860023067L, + -4162778827118794697L, + -4999879893029494430L, + -5470698342693924491L, + -524838860730151022L, + 2056390379798965398L, + -7635140489953799830L, + -4895934908017276310L, + -8494320702432460395L, + 4375244527171869608L, + 5749214457757073666L, + 4541994463651552366L, + 4448135749491527723L, + 3252319268873763159L, + -4937698705299440219L, + -1443238972529269463L, + 5690643651433470600L, + -9020999177617872107L, + 5216703363076035920L, + 8692072066293807690L, + -2202944082561610978L, + -3202058202844418274L, + 9199667660131659024L, + -7208718625219556439L, + -8188854117697466457L, + 6229032659379082713L, + 6056662700481738610L, + -2741651824312128388L, + -5770752964459016300L, + -6200251094809993544L, + -8462183157391465625L, + 1991684432526984227L, + 7539287820084627776L, + 2339478854158321950L, + 6202507390678485586L, + 7743951748128383694L, + 4168070312184911657L, + 8672082835392561991L, + 6896073963991207358L, + 1101380276289164762L, + 6605809935833891247L, + -438522298677572710L, + 3905054981608874906L, + -1747754391336276367L, + 1032773222913269798L, + 6843327699919057660L, + -8003124643992369023L, + -631503341286938581L, + 4129740207606678749L, + -1702072036006461106L, + 7744011005333910111L, + -6885964098355695662L, + 6294542643192709825L, + -7426983010848522334L, + -2954466992510897276L, + -7979800600032271131L, + -8655210458445057123L, + -7169091905545403953L, + }; + + private static final long[] HASHES_OF_LOOPING_BYTES_WITH_SEEDS_0_0 = new long[]{ + 6665653827947065942L, + -5789604048565922719L, + -3544073118936500090L, + -2677072096376561857L, + 8974148226120660824L, + -4749991284220333463L, + 8297039314422555359L, + -8088911438875509914L, + 3424528861645039236L, + -421993933668452455L, + -3091699041169951528L, + 1163501013095869222L, + -1554311774836581326L, + 4121966646419608524L, + -5821497637003820218L, + -4128235463417739287L, + 1634251901919194052L, + -9040019856632616077L, + 1183275435239077349L, + -6101391766615068007L, + -3755326226698648655L, + 1818343754347462935L, + -6462354084044314322L, + -814980520133498484L, + 1615579219767298748L, + -6066678408453320652L, + -5834994416669600405L, + 6932484884661269235L, + -7738687275954138493L, + -445315170800868989L, + 6203156606326072466L, + -8944279252978819749L, + 5060297072545920013L, + -3956343463993130235L, + -9180490411183400199L, + -4817718227656051657L, + 785979865396935574L, + -7689259778972129265L, + 6878639307143602827L, + -1707085302887161029L, + -1565439692045367513L, + 145188358359952638L, + 5950830465561353178L, + -5798478302038700751L, + -2226708668641330939L, + 6469448358736909862L, + 8664958527704152036L, + 5535349946889143487L, + -5492973006601933162L, + 1056630503881604364L, + 309692344193328064L, + -1325766938638327983L, + -7482929830970430416L, + -4408424302596019484L, + -480574950088335999L, + -3307863187790378596L, + 3477765577142638670L, + -2331230081208486379L, + 3911594671769223260L, + -6780531386208631646L, + -8510677449436680990L, + -626520326023685130L, + 6361450738099140926L, + 2394752145895650387L, + -1428144106153991705L, + -8083151844911747669L, + -7436004472807581894L, + 5782046067893733552L, + -5292026140423046307L, + 5533934070794082284L, + -7662366745440754477L, + 2985568173297445164L, + 6966476425189845713L, + -7703121456776836315L, + -1510987927978493047L, + 7303134625337334164L, + -8202990867786288428L, + 1319339862757959960L, + -3077790914603251977L, + -8454808621776160478L, + -2753146122957105748L, + 3373398064125255264L, + 8346019299144821571L, + -8486870268569731271L, + -2336559059056769901L, + 4511628550243589470L, + 6951149477250785149L, + 5417720661433288424L, + 8309421963807893058L, + 5112522658470376561L, + 8234176485072859240L, + 7799608401388908342L, + 4378449040504281742L, + -7989739383215628611L, + -4732084855234830012L, + 3167384580555501185L, + -3643215394046503577L, + -7349901699683782836L, + -5349550264170666110L, + 756076486099874176L, + 4174502207370688508L, + -1151758869353979658L, + 8848338984622513194L, + 6395913475161294746L, + 1469705818420514455L, + -6295758011496721124L, + 5241715235088273374L, + -6511478119514275748L, + 8758910874313508247L, + -1699706016752355418L, + -690362402544790978L, + 2941321643463612597L, + -4293872409356543041L, + -8869301228299428567L, + 1141068614246669386L, + 647542286173136771L, + -5081241094287956867L, + 7611746854774550166L, + 8286824316663843591L, + 5293297384504364695L, + -5982798360475369212L, + -6572523711787919267L, + 4407085069020124145L, + 4613619958838436303L, + 7684164341448790302L, + 6756516403404278842L, + 2473985321567407573L, + -1849052731267467607L, + -560354543015577264L, + -373043150459477314L, + 6995361206199059042L, + -4868650397665721927L, + -7208287292799671945L, + -3899683041439439017L, + 1521234411290838670L, + 5267471567701155516L, + 6474031661344396260L, + 4283176820990066383L, + -774826789342914073L, + 4335739136054102737L, + 200896861914240508L, + -4316420436327989620L, + -5088641514239825154L, + 5164519541776509316L, + 2219746828642761402L, + 3587472414755725088L, + -3488503791590966004L, + -1652046437211338111L, + -5535426239533412177L, + -3602265696983958223L, + -4567427711302233998L, + 8184240716274055400L, + -5266269477414042060L, + -7324103519668272668L, + 229999798703974345L, + 7096405761766463580L, + -6255709187415618861L, + 852735384705532175L, + -8938214114308238198L, + 8963621340924508593L, + 9112541540378925595L, + -4616697869335781648L, + -1233934456967866939L, + -4077001463173053748L, + -6419528926392839608L, + 1929390749779564956L, + -7253316895888692088L, + 3527041640449918221L, + -7080491663870455048L, + -7454823183023009856L, + -6713602407554956640L, + -5298856948360600322L, + -1501770146154973327L, + -3425534612569530048L, + 8395223338644809391L, + -4742678068980964529L, + 1652567688904060596L, + 5564504478001751639L, + -8517554112392241558L, + 3786868227755834874L, + -5719304763773211634L, + 3763970332575479507L, + 2649812513621696558L, + -4445024488002933964L, + -8450466196049720316L, + 5754528146566703292L, + 4852625517416018587L, + 7311959397744128586L, + -327622418271024417L, + -5089985239000418204L, + -4480294659534985688L, + -1294989405694625777L, + -615947055237665163L, + -4568269373826433084L, + -6647170598113447270L, + -2205400148055461188L, + -2960875377488314259L, + -7802864814797980125L, + -4662829720569086630L, + 2546408082472556554L, + 890804262993354031L, + -8226401715675614014L, + -8917275821815880727L, + 2477618749365003865L, + 8418269367864851601L, + 4662094108308307351L, + -8118793192420184206L, + 6846264423372553523L, + -7942173008166231500L, + -4108512744107291799L, + -7904090155421027898L, + 5523466200613751305L, + -2953379233731225425L, + -1197095549386947091L, + 6045846757134608180L, + -3707869269183903522L, + 2779236905743216135L, + -361676587843055307L, + -2635261306415357726L, + -6509798004878518435L, + 1863587909403013988L, + -7520580316527163576L, + -6379291317211929448L, + -7620905891725098001L, + -2465551527582106307L, + 7241964578148990184L, + -6311322781101340202L, + -3020667296869548603L, + 8216782627512460387L, + -2692182243233829563L, + 1747175548503678565L, + -8885656099747617845L, + 522291218856276218L, + 6283744457032450774L, + 916230451834982654L, + -4089965662770677423L, + -8903058414982940070L, + -3738198241317312383L, + 1445085914657575113L, + -2012273464670594509L, + 6404077030013937454L, + 1329465815301186919L, + 4635873553023090471L, + -5377753772517225420L, + 1015019521353160404L, + -1665992354319528315L, + 9012340776556375011L, + 5778123565462793861L, + 8530605005049046593L, + -4591714514116980507L, + -4494594919048493483L, + 1893166869054693141L, + -9061649457570254120L, + 2914267276964910135L, + -6284492017246979138L, + -7055505827569739765L, + -889475583938310148L, + -8187613934134840238L, + -3308687460189573629L, + -897141441007718763L, + -6710963242654816172L, + -5341924825235386471L, + 4347432584948358099L, + 8927713241297101393L, + 2180557435070426802L, + 4579020122958742093L, + -5534158339970490803L, + 2185492605512194012L, + -327633447467916153L, + 9215998522891732804L, + -7912803364675245541L, + -1806233245666346644L, + -9038630050176177334L, + -2192019490984975973L, + -6479398744604567096L, + 6995952040088368841L, + -4309518653977861918L, + 6102791465247431297L, + -5104457163765865537L, + 7861681047136438901L, + -5076301891857452794L, + 1819637793566329678L, + -5361659997421131017L, + -2091157752616506018L, + -3248867894565820843L, + 8380590357118949537L, + -5390027978162823802L, + 4679766642994167265L, + 1808649257049920713L, + 1521853533084038975L, + -3254885160393954675L, + 4676349884210895679L, + 7152105176348873586L, + 4019498085477893861L, + -7688826658849547105L, + 7725487018181678237L, + 2843148296909797321L, + -2111458518911373960L, + -5930988189464757132L, + 2999836080082916584L, + 5258645044061481873L, + -4374901417507719180L, + 5968988542990945295L, + 7063865688418250092L, + -3082390282994194982L, + -1769924709834072774L, + 5156154634139202143L, + -5042052718766755463L, + -3999291805788718223L, + -1650492645962554370L, + -2788399451859036047L, + 7757384865629391019L, + 6764067541394908728L, + -2964620754340212099L, + -8835812450211244550L, + -4330613157254549476L, + 5382312720775017309L, + -8912238112613037874L, + 6729362625991860149L, + 5040339868437664129L, + 1986442221150817249L, + 2833965222715421174L, + 4454879067173589066L, + 4214179707119429897L, + 7969471537580882301L, + 4707712647580178131L, + -6276384029844312381L, + 5003823498704182200L, + -7159224012504849677L, + -6732468713847601045L, + -451150815967949945L, + -3304945333512306051L, + 8721127390513069488L, + -6257492216267905806L, + 6994701391892471561L, + 7369521965253705159L, + -1942957112123842402L, + -1274643128018116059L, + -1580125162564136735L, + 9136185408214755747L, + -2914537383120971740L, + 9209644639937450115L, + 487124280788007393L, + -8177344317197823195L, + 2738707339044517752L, + 8095872149006863063L, + -545157444532302601L, + -936698329718580485L, + -4901388582496778106L, + -1399963386439197980L, + 1690941657066922406L, + -6188898220632922030L, + 182177611176833150L, + -5235331291371493590L, + -7215173511743087678L, + -2940930949094457090L, + -3554616762777959507L, + -1227566774803650594L, + 126409523184734199L, + -5552904319120555059L, + 7352012128947000025L, + 175845163851021692L, + 7689535477863431441L, + 1688817097916176071L, + -8309357218398085711L, + 1143303078449829434L, + 4988650444510350305L, + 989390459273330745L, + -4404786474907964461L, + -6013357091088560707L, + -3369486357840647176L, + -5617919047910994332L, + 7862597641680704753L, + 6153533607628655113L, + -5935817060689825006L, + -4638742470542759160L, + -5170200139486489942L, + -3797462862816231632L, + -7523250579546769374L, + 3432885051112683135L, + -594962147648253627L, + -1635875643285631379L, + 6231350693553808879L, + 7408417052020966543L, + 2762871106861808563L, + -5173631699220114637L, + 5713727412733125037L, + -3899822138441414888L, + 2531424564706126868L, + 2668705972796311220L, + -8505630464979201291L, + 5232417711683756420L, + -6193480636951185723L, + 3997557899298166160L, + -499329436764373579L, + -4168998692140880977L, + -1278702168248437939L, + -4205714015212589720L, + -6075452672774566057L, + 5316851879595668811L, + -856263686801815946L, + 249453684176791550L, + 8631795819413273172L, + -6359854298613460820L, + -4880284840543237455L, + -8505753341883846372L, + 2210511848333928251L, + 7866118606324100230L, + -6686723182606252640L, + -8022317142606681640L, + 2872846752948911332L, + 1462486761827744910L, + -2333698582625662536L, + 2351971687147951698L, + 8780992513024852527L, + -1055703511181057423L, + -5129838204285009330L, + 6019857852521847817L, + 3474804733922603440L, + -3438026173701472540L, + -5014200821131413864L, + 3722183079515657580L, + 4595459098697613986L, + -7273302362390554577L, + -1183243147173106410L, + 1250316480703787335L, + -4036417308378739551L, + -8171241684564025199L, + -1444817278101452987L, + -5149004456737721464L, + -9151361129918396129L, + -3397841654363889387L, + 5939018758065831959L, + -4618833968900085099L, + -4804710050485360752L, + -986147323305919153L, + 8433402046252694868L, + 3402472387886333079L, + 6648721581812913642L, + 7545001534469525767L, + -2159558352983318523L, + -527918061511557161L, + -9097842819427090448L, + 5490764520636435462L, + 8940907420974044282L, + 8065885367294761717L, + 9126781255864608166L, + -7038128550034808274L, + 2129349033611316048L, + 6122145305083854433L, + -3131698705914526997L, + 8513873847555997838L, + 2641185331298884484L, + -3933359261337583276L, + 4455822931565268868L, + 6210597485361343375L, + 48275763469138112L, + -4040150889516064080L, + -380969185514364438L, + 4241813299302917418L, + -1595624218715483276L, + -4776935416378672245L, + -4376925234762941627L, + 4047867035099872744L, + -1360084872964546187L, + 622387020347388700L, + -5131645918980513847L, + 408338571741801931L, + 7363750087346687688L, + 6737473532720012277L, + 2318019708548967324L, + 8771768074500179526L, + 8857646919759472215L, + 2522573097657493641L, + -2423326328890116522L, + 1989746966925038863L, + 7672722008502212941L, + 2140362728746429911L, + -2673802457555972488L, + -1773151482900640326L, + -313068483478418644L, + 5013158890396496539L, + 5482660465451132885L, + 3258472208968020185L, + 4767670779359132511L, + 7693552999338372999L, + -901680228690526025L, + 1089180371118481814L, + 4293375244035886346L, + -1962629080279766201L, + 2222330065043425897L, + 3369405500095244802L, + 2658789151545528727L, + -7774565807858620379L, + 1084326140869671947L, + -5434432268705031901L, + 2180520833581215938L, + 632866827282395242L, + 7401769093998420929L, + -1501945418691678209L, + -6519039992723163516L, + -3237878798648121431L, + 1445316291631581042L, + 9067784747908349955L, + 6720511821996419101L, + -4604090926074340083L, + -1703427890781067435L, + -2332449337351599134L, + -7134581291331345557L, + -100619425730545485L, + -8928331454614465558L, + -5414664566994091947L, + -250253323907790747L, + -4125120859704104205L, + 5265608675113327534L, + -1106440358316798986L, + -3132948339320524042L, + -1769360217727663390L, + -6148228432119684450L, + 5051735026708131735L, + -3084188413564311460L, + 8759728664177720433L, + -4859095946336685737L, + -1886889459731067640L, + -1378480539638315159L, + -9049809243416485286L, + -2000107983033711361L, + 4157120773731364487L, + -1808265212831445402L, + -2196498993493480264L, + -8386935930399696667L, + 4759938096703369345L, + -4118521846188308313L, + 7157295486858813240L, + 4945752308016651452L, + -4173785935384824363L, + 1788529025053697021L, + 3993842499528395149L, + 9171317917249731442L, + -634141534904935122L, + -2072087936990361526L, + -7526214993566150005L, + 6612748581543768045L, + -3336262380081111460L, + 4976550170355560820L, + 8588219279211966004L, + -4599952352051238782L, + -3077807470649213797L, + 3519048410419239281L, + -1269625857054326672L, + -1981810369066884456L, + 3215154362269493852L, + -1785458974914263946L, + -7685571788755122241L, + -842157214814107044L, + -5897864338134155533L, + -6208498518724029718L, + 1499049555982089916L, + -7395915256615735849L, + 2984391195155257274L, + 5877953066484841227L, + 6846689224681680487L, + 3262845941307632598L, + 5343873341106550578L, + 8674160231567510634L, + -8964078304780361510L, + 8508234887302759010L, + 177823134353084724L, + -6206673588147938556L, + -5743358946993952513L, + -4303394514558459612L, + 3274927803723806123L, + -4798523778581238548L, + -570481748089052408L, + -3841292296997736004L, + 6731855287357772628L, + -7228244941482034575L, + -2491894868983308234L, + 151002941274804308L, + 6365761415219096791L, + 6910374953287400988L, + -8244739115056188084L, + 7312238168197737958L, + 7043896837953553432L, + -105689371098164936L, + -3281826222318725416L, + -5392584437397907545L, + -1244502770939334171L, + 1422952733642352893L, + -781084903411999364L, + 1396690387514113203L, + -8234418537024402963L, + 933069852671849324L, + 3458378457074859210L, + -432385914044143895L, + -333866867497008084L, + -5703273811341863097L, + -2034540751574753942L, + -2369557092226975438L, + -815026134899265013L, + -7959365582485730906L, + -7197967434421910831L, + 4747509881653331798L, + 653308083545458473L, + 5930493565363152735L, + 4681031764662240390L, + 6800487255255275529L, + 2997868047200386085L, + -4012551584799863895L, + -2732276893078481698L, + -6020710793223976880L, + -4359477391069411647L, + -9021880775816161346L, + 6353329025823001408L, + 2805319525008521714L, + 5679548538811076916L, + -6219297722635931220L, + -8841573986244661336L, + 8963781793551427953L, + 2688506298906176650L, + 6141741081705776696L, + 2510363714831351328L, + -2730397005289452736L, + 7708495123904590946L, + -632248182436338500L, + -5234821280863028627L, + 1321223421208197172L, + 5864841446223183074L, + -5988460782579658037L, + -8225052281044207214L, + -897540494473733225L, + 8590474636782421992L, + 7220132770424705042L, + -9106622746426894075L, + -3585709112504182555L, + 7808697748897822522L, + -4089854074839215479L, + 6016223108476798945L, + -6597172736630482691L, + -2193801513557418184L, + 5825159972581893620L, + 4631846790359335398L, + -5532611793901955549L, + -5243152382106090709L, + -127459936222352081L, + 6091495647920317970L, + 6462841941099889780L, + -4575635345767708116L, + -2542164493227712148L, + -305478661809303004L, + -4059150405046622549L, + -5381054086283578893L, + 7191490357105815377L, + 3276929466127581069L, + 2009085051555744551L, + 3249445681007134225L, + -8121229117439800671L, + 3440037568412847743L, + 3280179938427916363L, + 1442329761432187844L, + -1693017785953323849L, + -3408752277115922281L, + -3038837448636151594L, + -3070429694929466029L, + -7559544014133244350L, + 2583256147707906484L, + 8809049921046234748L, + 8707285529402118928L, + 680585173321551184L, + 2835422586302063689L, + -2367902852764733088L, + 4311754893046855300L, + -7420248434161482753L, + -115331812692054874L, + 932066338714068818L, + -8023806876384453665L, + 3566420863959396435L, + 4981613369266357307L, + -3434457476282205941L, + 4903586440989717216L, + 3268581766723018296L, + -6679520660856856176L, + -5331329368963679157L, + -2266666248595158753L, + -8523119193122881242L, + -55424956038138295L, + -9070536805481137606L, + 5417874584175861223L, + -9170990702439119877L, + -2874187966968250082L, + -2946382889610762149L, + 4460563949925001083L, + 208629763415621209L, + -2006752850050214804L, + 4078329933745202367L, + -6003178253606500673L, + -1901357459835262850L, + -8628316773608528907L, + -2367045297086306897L, + 5181249700081074386L, + -4589928625788551233L, + -2552920600683065276L, + 3839074001010260393L, + 6062571583983586246L, + 3105281105213899486L, + -8099385440700840978L, + 4787643747225137633L, + -8984875174291612426L, + 4913083880029400303L, + 6268216711282604489L, + -9161084900657602886L, + 4091506170626504784L, + -6137301573374744154L, + 862946098808666372L, + -6257228414093693534L, + 846885534512613336L, + -8079328287598987503L, + -6720900737415180224L, + 1285878208148563529L, + 7631267414265336249L, + -2101551039318119517L, + 5109001452480742834L, + 3045563723015329655L, + -2678263607699919634L, + -6111470810863893821L, + -62607678110828373L, + 2055784805590000566L, + 1529635868940897778L, + 7944938393711537630L, + -8622354108627238341L, + 400616186093007467L, + -3365668985765229920L, + 520796926667976058L, + 102953245028782442L, + -2887814565519713483L, + 1134845382723719106L, + 9165308674806362050L, + -6744097273442400118L, + 6792112760482467418L, + -2608343247634721333L, + -4300634750668796357L, + 9114849223412999163L, + 3292520868553201409L, + 8990457701612625656L, + -8604807838878366041L, + 6771571915702855913L, + -2596622766084861700L, + -1646084290072088508L, + 1986205531231129502L, + -7397245895787143030L, + 1322416902629630467L, + 8798541050009010963L, + -2603841395104921386L, + -543569387127414242L, + 984277979951833313L, + -3660009424046808871L, + -8594713258206394011L, + 8481462325069318424L, + -7693778854396921111L, + -3466292502757840479L, + -2782730956760988243L, + 2144829447800020843L, + 1822306312783027271L, + -6176295933444085182L, + 622474367537194108L, + -4672048499304291212L, + -4264273507669187343L, + 6547219371359541315L, + 307228520032121068L, + -6000079446917495846L, + 1421275154031788543L, + -5016167630802770982L, + -8153331626666077741L, + 4942105349496831629L, + 3433248069013654310L, + -2222196715022867294L, + 1813002790841082845L, + -3166716117255484472L, + -9054518662678110779L, + -7366837763863382746L, + 1821322667002800477L, + -6699279961062916425L, + 5275413951856993906L, + -1764403036698451877L, + -6814217963826368587L, + 7436121024271456880L, + 8020503156016080684L, + 4790388985973217959L, + 1217850670627339453L, + 9024348854253136643L, + 1103129819330605922L, + -2166392621148129624L, + 1180647242684910729L, + -1356076635533405843L, + -6621817644273909238L, + 8889272575079464367L, + 4253064062765640293L, + -8444342477389972075L, + -4449332965293453838L, + -4037054741244914652L, + -5783630812876862786L, + -6227123841055454074L, + 2689340898385899414L, + -5298687834900317834L, + -5771269026024081892L, + 1945144907664070561L, + -2548379487047027869L, + -4846198189662238716L, + 6383035859800179563L, + -538840917214433039L, + 8270516200955665520L, + -8600518090590687029L, + 3805661707968319824L, + 7599817584154307234L, + -3646938568457564007L, + 43016748520311967L, + 3409116355300614893L, + 621933859667984230L, + 4420539797901766919L, + -8854667100425996404L, + 7203838388356217445L, + -7264835226236053678L, + -1623402918890722788L, + -4166106671946901643L, + 8889077380182099507L, + 8937812779969367487L, + 4083244217264466556L, + 7823919447681612722L, + -385459494499317144L, + -5883272230680561812L, + 6356338096717516045L, + 9162899879168759439L, + 566477718171182844L, + 5138116499374346600L, + -8162099721989626792L, + 2871419627484181402L, + 4549390537257157879L, + -2450300817394156370L, + 7914639949613314474L, + 860572809253792281L, + 2292560778148293412L, + -7502514745528454484L, + -6882165832291626199L, + -2630674516935294102L, + -4989794580249597060L, + -7513651950755561937L, + 4804536116066169381L, + -5242688622696191670L, + 8047321759875327873L, + -3677209646627471284L, + 6980331724177633705L, + -375074456792592810L, + -6802449435897247678L, + -1628562059596464092L, + 8113462089103701362L, + -3970435268208640319L, + -9097918839183737600L, + 6199140712580348865L, + -268991411330185044L, + -7817073335811580945L, + -3405223752470266629L, + 7993791576935207402L, + 5192774131052489482L, + -9042927321514383766L, + -3601662122081534094L, + 4841841972164327977L, + -1645688674582329230L, + 7159999496075283486L, + -7405132443615822400L, + -3717231289253565466L, + 2918520769168028237L, + -1260804183044051163L, + 8154917047376864752L, + 5508346499230105531L, + 3285997221882934909L, + -5617134513664899328L, + 8293867188447369346L, + -3882977634293431140L, + 1239307736392879380L, + -8924851511568278673L, + -1622087619217032532L, + -5551432630671196153L, + -1121763370203524511L, + 551938970558940490L, + 448453096366444138L, + 5667305190458742300L, + 4539597042043946745L, + 5829786741944860299L, + 3393352605677422507L, + 335053384967789388L, + 4394222496211014534L, + 5370000130739018087L, + -565706613123683753L, + -7833497599449750817L, + -3437882830797020390L, + 4937862675193204437L, + 5959554141150583384L, + 3983730657745060070L, + -2467280586303360795L, + -335334767324786992L, + -640382658335040542L, + -6577797313708187062L, + 1125349079636120123L, + -494879484631175552L, + -5623945463935727777L, + -3970027725779406711L, + -8493400026672732241L, + -311293892634841311L, + 6355980595541216637L, + -5751497682715332938L, + 2347741401598364925L, + -4809577486191269354L, + 1420282983140681264L, + 3613315133783948228L, + 8625254293652687419L, + 7531382631561216614L, + 5399763597085607760L, + 3035446121449853380L, + -2120112973020043286L, + 480192923742041432L, + -2548797010939265844L, + -3405974478077804102L, + -133708079963712608L, + -337250121171329984L, + 4042336883248424281L, + -5364750416296539339L, + -6498306095021896398L, + -7473497501035559608L, + 1723304923372711161L, + 5006605643417679342L, + -909630909226495535L, + 4651967258997819637L, + -2492450197158626287L, + 8848922133698826227L, + 6782108621218678042L, + 4567479157936435262L, + -820689158472515069L, + 4826415566140008821L, + -2484634481640370398L, + 1380433635719727570L, + 8147033694125853433L, + -3881420496323039737L, + -5072661488520121646L, + -1001254897970286729L, + 6441576346453560757L, + -7535835287918290060L, + 7430502536985186200L, + 5108187444240043248L, + 1549419730978779681L, + 7111883894871337879L, + 6796158162775215639L, + 2516639939991012468L, + -2371674177998310802L, + 1127854323859071735L, + -8295387485661924306L, + 1253693892107448444L, + -354249102833783868L, + 1065848432473299948L, + 4980932879340301589L, + -3265506302710279538L, + 1321586933496286980L, + -4844842473063803960L, + -4204298827240721647L, + -3118913691980453704L, + 7305336767320557495L, + -6798785057541149778L, + 8746540548113783399L, + -7969167725986709018L, + 8609211018983958021L, + -7231030245443353922L, + 5692294488862404752L, + -5761197062576580840L, + -5894104633667262135L, + -1372322724071052152L, + -1152616426443151651L, + 935972424443347664L, + 8940890555228973330L, + -619270121883985361L, + 8372920364579516256L, + 4398889684895596727L, + -4160078105340506886L, + 17822379882525818L, + -1430879876106006468L, + 3128763795393100346L, + 607666137432825035L, + -766289326504346177L, + -4462174050261663777L, + -1140803182508002260L, + 1035794337970190842L, + 299393203454704382L, + 7734246045329515707L, + 6361639674133231345L, + -4159331747805036027L, + -4615813274428812655L, + 3873955101764325164L, + -6849074412332003603L, + -8511457087328374957L, + 1188632971701951322L, + -4073667337443196875L, + 4905058734702399313L, + -4717225456603964250L, + 5342494502015340877L, + -1341838399813369350L, + -1184900213109944408L, + 7269941727655174395L, + -8379459598706879314L, + 3162473609960755880L, + -3008200309695401191L, + 2351068467933459341L, + -71569529145854359L, + 3900859699454157168L, + 7000831594956186274L, + 4124542402944063388L, + 517836136499145469L, + -3563369622913903581L, + -6131810259721881352L, + 2478930569265994206L, + -7335894002456063877L, + -1852552332759896185L, + -7661455803549448534L, + 4220258643753458017L, + -2576514654123627237L, + -4329614475513280706L, + -6312701748516438716L, + -8712455751362790038L, + }; +} diff --git a/src/test/resources/net/openhft/chronicle/algo/hashing/reference/XxHashTest.java b/src/test/resources/net/openhft/chronicle/algo/hashing/reference/XxHashTest.java new file mode 100644 index 00000000..2323febd --- /dev/null +++ b/src/test/resources/net/openhft/chronicle/algo/hashing/reference/XxHashTest.java @@ -0,0 +1,2128 @@ +/* + * Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ +package net.openhft.hashing; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Collection; + +@RunWith(Parameterized.class) +public class XxHashTest { + + @Parameterized.Parameters + public static Collection data() { + ArrayList data = new ArrayList(); + for (int len = 0; len < 1025; len++) { + data.add(new Object[]{len}); + } + return data; + } + + @Parameterized.Parameter + public int len; + + @Test + public void testCityWithoutSeeds() { + test(LongHashFunction.xx(), HASHES_OF_LOOPING_BYTES_WITHOUT_SEED); + } + + @Test + public void testCityWithOneSeed() { + test(LongHashFunction.xx(42L), HASHES_OF_LOOPING_BYTES_WITH_SEED_42); + } + + private void test(LongHashFunction city, long[] hashesOfLoopingBytes) { + byte[] data = new byte[len]; + for (int j = 0; j < data.length; j++) { + data[j] = (byte) j; + } + LongHashFunctionTest.test(city, data, hashesOfLoopingBytes[len]); + } + +/** + * Test data is output of the following program with xxHash implementation + * from https://github.com/Cyan4973/xxHash + * + * #include "xxhash.c" + * #include + * #include + * int main() + * { + * char* src = (char*) malloc(1024); + * const int N = 1024; + * for (int i = 0; i < N; i++) { + * src[i] = (char) i; + * } + * + * printf("without seed\n"); + * for (int i = 0; i <= N; i++) { + * printf("%lldL,\n", (long long) XXH64(src, i, 0)); + * } + * + * printf("with seed 42\n"); + * for (int i = 0; i <= N; i++) { + * printf("%lldL,\n", (long long) XXH64(src, i, 42)); + * } + * } + */ + + private static final long[] HASHES_OF_LOOPING_BYTES_WITHOUT_SEED = { + -1205034819632174695L, + -1642502924627794072L, + 5216751715308240086L, + -1889335612763511331L, + -13835840860730338L, + -2521325055659080948L, + 4867868962443297827L, + 1498682999415010002L, + -8626056615231480947L, + 7482827008138251355L, + -617731006306969209L, + 7289733825183505098L, + 4776896707697368229L, + 1428059224718910376L, + 6690813482653982021L, + -6248474067697161171L, + 4951407828574235127L, + 6198050452789369270L, + 5776283192552877204L, + -626480755095427154L, + -6637184445929957204L, + 8370873622748562952L, + -1705978583731280501L, + -7898818752540221055L, + -2516210193198301541L, + 8356900479849653862L, + -4413748141896466000L, + -6040072975510680789L, + 1451490609699316991L, + -7948005844616396060L, + 8567048088357095527L, + -4375578310507393311L, + -3749919242623962444L, + 888155921178136237L, + -228195649085979072L, + -521095004075279741L, + -2458702038214709156L, + -2792334161285995319L, + 7509323632532862410L, + 46046374822258777L, + -731200582691896855L, + 933917387460394992L, + 5623144551929396680L, + 6456984547425914359L, + -6398540474588876142L, + 1224372500617079775L, + -931727396974525131L, + 979677643219401656L, + -8078270932489049756L, + -92767506898879473L, + 2379112167176776082L, + 2065719310945572007L, + -4972682801816081667L, + -7346559332994187462L, + 4674729779638751546L, + 5844780159702313017L, + 925606237565008152L, + 8164325403643669774L, + 5124005065773312983L, + -4646462236086916483L, + 4733593776494364101L, + -6408850806317360L, + 7405089268865026700L, + -2131704682637193649L, + -592659849139514384L, + -4386868621773355429L, + -2216833672566288862L, + 4022619316305276641L, + -60464713570988944L, + 2416749694506796597L, + 3576590985110933976L, + 3368688771415645536L, + -357157638897078259L, + 3484358739758473117L, + 2078888409435083535L, + 8053093288416703076L, + -4934736471585554038L, + -7784370683223414061L, + -4109284735634941390L, + 5982490102027564625L, + -4991107002810882893L, + 8664747912276562373L, + 8536879438728327651L, + 2358675440174594061L, + 5352236919104495867L, + 6340852522718110192L, + 5075606340464035668L, + -6313168920073458239L, + -6428599582591385786L, + -7278654800402467208L, + -6630626099856243581L, + -7548742438664634646L, + 5514383762309532642L, + -5996126265702944431L, + 4011116741319319261L, + -7289240093981845088L, + 4975257207486779926L, + -3945500877932691916L, + 1973955144068521079L, + 3884425912161913184L, + 7692681977284421015L, + -1616730378439673826L, + 4799493270916844476L, + -6107310582897997679L, + 3643294092300179537L, + 5406040598516899149L, + -3032420409304067208L, + 5044227119457305622L, + 9165032773225506149L, + 7553488247682850248L, + 2247298339072845043L, + 7380491470304042584L, + -456791943260357427L, + -1906500292613319324L, + -4025157985304129897L, + 6167829983725509611L, + -8678196943431064825L, + -636391087313417831L, + 5757999497725839182L, + 8999325347316115948L, + -6042339776328081249L, + 7988836354190359013L, + 2818448030979902104L, + -8484201484113382447L, + -1140175406473847155L, + 3042776987426497381L, + 3147338037480432386L, + 5065714330193756569L, + 8827021486636772242L, + 838335823706922959L, + 481844220820054909L, + 5333474685474667077L, + -3722898251196013565L, + 7909417627390150381L, + 7116148225996109646L, + 7520381989775811302L, + 6045444672904719015L, + 169039646730338133L, + -2144629916252757106L, + -3752608501798118554L, + 8374704774878780935L, + -5830926781667225570L, + 3202139393110256022L, + 4400219135677717216L, + -5663710220155589201L, + -2589002340345751622L, + -8240133511464343390L, + -4036798392879835146L, + 501599054729008501L, + -4851415719238782188L, + 7565157933617774080L, + -6428091359957700043L, + 4081845077806300175L, + -9016659258880122392L, + 7811786097015457596L, + 1357606791019752376L, + 6522211979684949668L, + -3462397075047559451L, + 3075504459164148117L, + 3055992297861390732L, + -7230492327399411047L, + -1128103378253532506L, + 1834607408788151585L, + 7065978976369231860L, + 6566122632438908362L, + -3440855531356735824L, + 6271453770746181891L, + 413365468403580071L, + -8342682158827061522L, + -3713303136987568731L, + -8959326895824091541L, + -2793862582117663595L, + -184756427409317729L, + -7052502019782453427L, + 3666196071825438258L, + 170204095295428634L, + -1880693509859077843L, + 5179169206996749826L, + 2866097700453114958L, + 1859104195026275510L, + 3782323564639128125L, + -6485194456269981193L, + 6761934873296236857L, + 5764605515941066448L, + 597754945258033208L, + -4888986062036739232L, + -6490228233091577705L, + 3234089784845854336L, + -5506883591180767430L, + 1491493862343818933L, + 3232293217886687768L, + -4079803366160739972L, + 4884134040093556099L, + -7274733680156962461L, + 5265680254123454403L, + 1036855740788018258L, + 423439784169709263L, + -3627743032115866622L, + -6311378083791982305L, + -3058076915688265687L, + 5826550132901840796L, + 8049712006832885455L, + 1707844692241288946L, + -3293048440386932248L, + -2458638193238955307L, + 943059295184967928L, + 3899561579431348819L, + -1516862862245909493L, + 4448476568037673976L, + 8738531437146688925L, + -1033913449611929894L, + 733668166271378558L, + 438686375775205249L, + -4325889118346169305L, + -238178883117433622L, + -7972205050662019794L, + -1263398103237492853L, + -8333197763892905802L, + 7796341294364809534L, + -1381767618016537445L, + 2892579485651013970L, + -3376209887503828920L, + -8575120126045607817L, + -1609355362031172055L, + -386138918275547508L, + 4598874691849543747L, + -2961781601824749597L, + -3032925351997820092L, + -4256249198066449735L, + 6712291718681474012L, + -4281614253751277086L, + 3727487933918100016L, + -2744649548868700294L, + 8662377383917584333L, + -9154398439761221404L, + -6895275824272461794L, + 3394857180017540444L, + 2010825527298793302L, + 4894417464710366872L, + -6879244364314087051L, + 83677167865178033L, + -8258406393927169823L, + 5042126978317943321L, + 6485279223034053259L, + 4442956705009100620L, + 316801800427881731L, + 1381431847939703076L, + 5172932759041399062L, + -69656533526213521L, + -5302643413630076306L, + -3956089084400440856L, + 372087412941022771L, + 4711314482928419386L, + 3255220726505012060L, + 8917854303046844847L, + 1116214654602499731L, + 2282408585429094475L, + -9207590323584417562L, + 8881688165595519866L, + 1731908113181957442L, + 3847295165012256987L, + 4457829016858233661L, + 4944046822375522396L, + 3445091217248591320L, + -5055680960069278553L, + -399195423199498362L, + -8109174165388156886L, + 4967185977968814820L, + -5911973391056763118L, + 2239508324487797550L, + -954783563382788523L, + 8523699184200726144L, + 932575865292832326L, + -7491448407022023047L, + 1809887519026638446L, + -8610524715250756725L, + 6158809695983348998L, + 4948400960714316843L, + -4513370424175692831L, + -3955280856263842959L, + 6440233015885550592L, + 8756942107256956958L, + 7895095834297147376L, + 370033091003609904L, + 948078545203432448L, + -8523229038380945151L, + 100794871657160943L, + -2186420796072284323L, + -9221115378196347951L, + 8102537654803861332L, + 5857339063191690550L, + -4554257374958739421L, + 6607496554818971053L, + -778402196622557070L, + -3817535277727878318L, + 3564122000469288769L, + -44446230828995950L, + 1322708749649533240L, + 6150374672341998205L, + -3300275952549095391L, + 5700833512536085850L, + -8559358370491270937L, + 5434443260519512697L, + -8031025173259990945L, + 7117462129248544172L, + 5425177419943569451L, + -7215427371174054838L, + -5728669976971194528L, + -2096361446095323077L, + -4247416835972286805L, + 4912769047482466787L, + 7755341152739082452L, + 6797061233443658471L, + 4089361562209715474L, + 5830701413838808929L, + 5514515889578551370L, + 609334005368729318L, + 177310574483850759L, + -820431153866372784L, + 7188454041446661654L, + 7480194911613035473L, + 4564607884390103056L, + 888496928954372093L, + -5480535802290619117L, + 9100964700413324707L, + 510523132632789099L, + 8249362675875046694L, + 5340321809639671537L, + -4633081050124361874L, + -839915092967986193L, + -7377542419053401928L, + 1820485955145562839L, + 8517645770425584256L, + -1877318739474090786L, + 7674371564231889244L, + -3311130470964498678L, + -880090321525066135L, + -5670998531776225745L, + -8828737503035152589L, + -6029750416835830307L, + -6535608738168818581L, + -550872341393232043L, + 2831504667559924912L, + -4613341433216920241L, + 502960879991989691L, + 576723875877375776L, + -2575765564594953903L, + -4642144349520453953L, + 7939746291681241029L, + 6486356905694539404L, + -9086235573768687853L, + 5369903658359590823L, + 3199947475395774092L, + 8384948078622146995L, + -3365598033653273878L, + -2525526479099052030L, + 2648498634302427751L, + 3715448294999624219L, + -4734466095330028983L, + -8440427851760401644L, + -371198022355334589L, + 8864079431738600817L, + -4205600060099565684L, + 6617166152874298882L, + -6515522971156180292L, + 7254251246745292298L, + -420587237082849417L, + 1190495815435763349L, + -474540026828753709L, + -8150622114536376016L, + -5790621848044235275L, + -2780522220219318167L, + -2991155855957250848L, + 1692932912262846366L, + 8814949734565782733L, + -8746818869495012552L, + 7931250816026891600L, + -7434629709560596700L, + 4388261932396122996L, + 7154847153195510802L, + -2810154398655124882L, + 2601892684639182965L, + 7781574423676509607L, + -6647000723020388462L, + -8679132292226137672L, + -2447013202020963672L, + 3658855631326217196L, + 2176620921764007759L, + 3654402165357492705L, + 4511989090021652156L, + -3254638803798424003L, + 9050506214967102331L, + 922579360317805810L, + 609820949221381248L, + 5723875594772949290L, + 4637721466210023638L, + 6195303339320487374L, + -38202587086649325L, + -2142927092331878341L, + 5355751314914287101L, + -7170892783575760055L, + -7506612729078573199L, + 8645580445823695595L, + 3221950179890871958L, + 1638211443525398634L, + 7356718304253861777L, + -296260062751271549L, + -1790105985391377345L, + -7004118620405119098L, + 7056012094479909462L, + -7673357898031223798L, + -8929502135696203556L, + 7527161467311997998L, + 6182865571027510002L, + -2163310275402596869L, + 6285112477695252864L, + 3703909999924067987L, + 962491298117560533L, + 138936592567072793L, + 6094857527471100960L, + 5914305068838335718L, + -8896724991235492552L, + -2667562314507789198L, + -7456492499188304500L, + -3422709784851063201L, + -1511644999824238281L, + -7130158069449057322L, + 6243266426571961929L, + 2713895636371672711L, + 5765589573821453640L, + 2624585483746388367L, + 3933828437519859601L, + -5664404238108533781L, + 7086393398544811684L, + 1322058227068490376L, + -8232508114671021371L, + -5963804389649678229L, + -3318229976491806899L, + -6261789542948241754L, + 199130260709663583L, + 7521707465510595039L, + 507353862067534334L, + -7737968456769005928L, + -8964687882992257099L, + -7735003539801528311L, + 6989812739838460574L, + -6986289777499051441L, + 1881562796144865699L, + -6077719780113966592L, + -5427071388091979746L, + 1660707436425817310L, + -4338189980197421104L, + 5330934977599207307L, + 4461280425701571033L, + -7426107478263746863L, + 4258305289832328199L, + -8003283151332860979L, + -2500604212764835216L, + -8883941775298564436L, + -5059709834257638733L, + -4582947579039913741L, + 1371959565630689983L, + -1925163414161391371L, + -1180269729544278896L, + -6603171789097590304L, + 8985062706306079731L, + -3588748723254272836L, + -6052032019910018725L, + 6200960040430493088L, + 2146343936795524980L, + 7785948646708747443L, + 4524411768393719400L, + 749211414228926779L, + -163844243342465015L, + 1066801203344117463L, + -3687825939602944988L, + -4873811917429870500L, + -3765115783578949524L, + 3344884226049804020L, + -22793631121165636L, + -5636541624133159076L, + -6201449576244177151L, + -4533734412127714050L, + -2064657727206266594L, + -1325853623186040989L, + -2651306529045029511L, + 903264360879626406L, + 6082283797495873520L, + 6185446819995987847L, + -5727850940826115079L, + 8356646143516726527L, + -7705915341280821272L, + 9137633133909463406L, + 6613483969797411894L, + 8598514961735984460L, + 6805925079991408361L, + 6009403222422527608L, + 2216303622650116705L, + -3736062178532154638L, + -7139008962939637477L, + -1537711200058404375L, + 8896755073380580322L, + -6063426810787442347L, + -3472064301690015285L, + -4568131486464952371L, + -8141256104294687045L, + 5627435360893599536L, + 1136003802967708029L, + 2730027518034735037L, + 1985287040172139729L, + -3643431491383365431L, + -9042919736106376701L, + 8879968900590373568L, + 8504486139877409399L, + 5832665747670146536L, + 4202923651402292496L, + 1738511892080946286L, + 4512683881549777042L, + 9200194457599870145L, + -1948301178705617139L, + 8655715314401162523L, + 412698981651521600L, + -1479274044808688580L, + 2688302549664693359L, + -3059920027366623178L, + -4275753325231806565L, + -8321791698013769889L, + -3678119714812414102L, + -2500922551770832553L, + 9018541633115002061L, + 5713301371152396803L, + 4180584812840471799L, + 3062416401091271879L, + -8125716681035757962L, + -2076056159878596225L, + 8855540523533374738L, + 2402007906402689092L, + 2020584786288649542L, + 1707405964421070701L, + -3681994462249973122L, + -3982567775984742012L, + 7133200226358561844L, + -5270514263562558963L, + 9060760368219219429L, + -6967162372382490281L, + -9094664463528453384L, + -3968518633408880046L, + 8618660189330281694L, + -4668946581954397558L, + -8596433172676363407L, + -1264942061713169049L, + -5309493221793643795L, + -1099320768477039529L, + 8925041285873295227L, + -6809278181760513499L, + -7039439984223885585L, + 6188209901527865226L, + 1487353394192637059L, + 2402097349430126337L, + -3818359601525025681L, + 4123217079279439249L, + -1424515143377220376L, + 1742298536803356877L, + -2836832784751148874L, + -4838603242771410698L, + 2383745618623084414L, + -2790832243316548423L, + -1176683649587660160L, + 1862928178605117401L, + 5208694030074527671L, + 4339841406618876548L, + -7704801448691668472L, + 500068664415229033L, + -2111184635274274347L, + -1387769336519960517L, + -2368660677263980293L, + -4980481392402938776L, + -6856361166068680884L, + 1708658704968066797L, + -9013068514618931938L, + -2616479975851677179L, + 7121103440247327570L, + -7094192881960646061L, + -4042342930006488618L, + 5294323611741266775L, + 5235545113690922502L, + -2562011392475214878L, + -4613304566070234734L, + -3784386310583029381L, + -4526148219816534267L, + -8643470129031767968L, + -4573761335510927866L, + -8255399593563317902L, + -1925488377092111963L, + -1747797357090594237L, + 7292772921748919564L, + 3951718848780851600L, + 5339305877764077075L, + 7889570407201305102L, + -8935437555550449315L, + -1858205318388884024L, + 381779657795494278L, + -3769854251228686168L, + -7957724087073627355L, + 4349540075286824743L, + -2476434494603040708L, + -4506107235113109706L, + -7120863144673563848L, + -8534342596639587598L, + 2205658724629050493L, + 604438195864305027L, + 4530331938860561927L, + -2074141653226683751L, + -1114378227875974007L, + 3377301950002508302L, + 5369356700690664306L, + -1747063224581819445L, + -6320380781966280801L, + -2075443262555773155L, + 1028541493355576591L, + -4694402890123574860L, + -5250660999767019003L, + 3847087895315315136L, + -4448050214964317066L, + -4591316307978008151L, + 4894820902772635901L, + 3088847887353411593L, + -6699208183127463352L, + 4636731998354510780L, + 9095126525233209263L, + 4135373626035182291L, + 3835688804093949701L, + -3490782692819028324L, + -561453348486424761L, + -3329283619698366365L, + 3251154327320814221L, + -8006986328190314286L, + 5856651505286251345L, + -8871425101391073L, + 7806993676637210959L, + 7586479850833664643L, + -7091216108599847229L, + -3410137297792125447L, + -8251963871271100526L, + -8849730915506517177L, + 8400334327557485676L, + 1676125861848906502L, + -8480324002538122254L, + -1402216371589796114L, + 5951911012328622382L, + 8596811512609928773L, + -2266336480397111285L, + -8840962712683931463L, + 4301675602445909557L, + 1843369157327547440L, + 2169755460218905712L, + -1592865257954325910L, + -8763867324602133653L, + -4283855559993550994L, + -7577702976577664015L, + -5152834259238990784L, + 4596243922610406362L, + -4326545138850544854L, + 1480440096894990716L, + 8548031958586152418L, + 6705615952497668303L, + -2915454802887967935L, + -6137002913510169520L, + 2908515186908319288L, + 5834242853393037250L, + -6721431559266056630L, + -7810820823419696676L, + 1954209413716096740L, + 6657013078387802473L, + 2214178984740031680L, + 8789512881373922013L, + 1240231669311237626L, + 8694612319028097761L, + 492180561068515854L, + -6047127535609489112L, + 7436686740711762797L, + -4520261623507558716L, + 938282189116272147L, + 3232025564608101134L, + -5425498066931840551L, + 932123105892452494L, + 9054941090932531526L, + 8066693670021084601L, + 764877609198828864L, + -489112437588815338L, + 4827691353685521957L, + 1948321254606741278L, + 6117773063719937712L, + 4645962658121906639L, + -7846887104148029590L, + 4210795945791252618L, + -8879516722990993098L, + -2621063563373927241L, + 2094675051444850863L, + -8681225697045319537L, + 6072534474938492189L, + 6181923696407824226L, + 5463607676777614919L, + 3708342890820711111L, + 8844501223821777366L, + -1459359143442302680L, + 2225439088478089068L, + -3866259492807347627L, + 5715020051188773955L, + 3922300588924895992L, + -9142841818158905228L, + 2234845285375211931L, + 2466598091809457099L, + -5086614780930363190L, + -59740786891006359L, + 3484340182077240897L, + 5684798394905475931L, + 8492255409537329167L, + 5276601975076232447L, + -723955912320185993L, + 9032937149732310432L, + 2226206333274026280L, + 5631303328800272036L, + 3943832708526382713L, + -3756282686478033644L, + -5407377327559185078L, + 2025162219823732106L, + -8802502232162774782L, + 9039368856081455195L, + 663058667658971174L, + 3624269418844967319L, + 1835338408542062149L, + 6821836507221295281L, + 6273547355770435776L, + -3104373869480308814L, + 1150888014781722836L, + 7638478751521711777L, + -6407096352658729423L, + -2242514077180426481L, + -3181824045541296523L, + -4562287221569080073L, + -5550768647534615669L, + -5786611484859469238L, + -6147722345444149090L, + 3737249616177808079L, + 3401215612108618403L, + -713522925214097648L, + 7938558781452631257L, + -2822931074351003413L, + -6484774850345918944L, + 3384659068511379086L, + 6976459554734427695L, + 4254162229878558339L, + -3312164339867139602L, + 7263045146222903358L, + 4561625003713187235L, + -3350421200373539593L, + -6329267008823047447L, + -6889593333717619051L, + -6470291206680780949L, + -1925391510610223335L, + 4955720513801530785L, + -6515999401129420095L, + -5146900596178823847L, + 2572121582663686783L, + -4958678197003031937L, + -1295912792184970105L, + -8320363273488883198L, + -8213501149234986129L, + -3883775881968950160L, + -8925953418077243474L, + 3199784299548492168L, + -6836506744583692202L, + -5007347279129330642L, + 7387675960164975441L, + -5841389805259238070L, + 6263589037534776610L, + 3327727201189139791L, + 3673450414312153409L, + -1563909967243907088L, + -3758518049401683145L, + 6368282934319908146L, + -6025191831649813215L, + 1223512633484628943L, + -8540335264335924099L, + -8569704496403127098L, + -5712355262561236939L, + -6468621715016340600L, + 7015005898276272746L, + -1037164971883038884L, + -6108649908647520338L, + -6781540054819591698L, + -2762739023866345855L, + -270930832663123436L, + -2387080926579956105L, + -3984603512651136889L, + 2367015942733558542L, + 2997123688964990405L, + -424413420483149165L, + 2906467516125124288L, + 7979917630945955701L, + 2879736983084566817L, + 558436267366797870L, + 6471658168855475843L, + -3453803644372811678L, + 95470628886709014L, + 5666911245054448862L, + 1594133734978640945L, + 3790246368687946045L, + 8636400206261643605L, + 5901994795106283147L, + -6774812279971490610L, + -4622588246534854941L, + 5395884908872287278L, + 7381412950348018556L, + 5461775216423433041L, + 2851500852422732203L, + 1153428834012773824L, + 2567326223464897798L, + 6290362916558214218L, + 6095765709335097474L, + -3526424734043456674L, + -8411274175041022530L, + 7565408328520233290L, + -1318636864706103626L, + 1261242784453012654L, + -472643963000448611L, + -7126293899612852456L, + 5072187962931197668L, + 4775251504230927816L, + -1624676500499667689L, + 2252385971292411863L, + 7908437759266752884L, + -8948829914565397845L, + 5258787823809553293L, + 3885696202809019506L, + -4551784314460062669L, + 5315762970089305011L, + 7218180419200466576L, + 109471822471146966L, + 3901499100759315793L, + -5613018173558603696L, + 5782419706003468119L, + 8285176821902721729L, + -2944182278904878473L, + 8089487615165958290L, + 6934039118340963316L, + 8481603619533191729L, + -6321491167299496492L, + 6441589800192421521L, + 6436057639713571196L, + 6819921695214365155L, + 1185928916708893611L, + 2597068862418243401L, + -7637601550649263782L, + 9129303862479379164L, + 4047905726243458335L, + 6672087858539795207L, + -4841432774404255351L, + 5501215987763227677L, + -5300305896512100453L, + 1635946349436492617L, + -5017459781050596604L, + -7313558338536196566L, + 4625509831332846264L, + -1241826701278444028L, + 2916178164108211239L, + -6947453283344846915L, + 5520544791845620925L, + 5009241392834567026L, + -630825152277572403L, + 6246654103747517292L, + -5632205909016659384L, + -5099826214945383802L, + 2466330894206710401L, + -1463559257726812272L, + 4922422449110036517L, + -4940410396057186660L, + 8835766963654337957L, + -1984334093384497740L, + 5616151800825184227L, + -8442970605804311782L, + -5396399970392474268L, + 2711274356126287353L, + -5090439840321959043L, + 6638617029380445409L, + -6424875729377006548L, + -7243574969986334324L, + -904268348341193502L, + -6196811069886893217L, + -7742123331454617135L, + 1449632469607275832L, + 3212140938119717436L, + 8676942774083692265L, + -6625590425417154859L, + 8720904664575676760L, + 9151723732605931383L, + 7642401923610349184L, + -3454390566366389884L, + -232373658792783206L, + -8933620623437682010L, + 2514068248201398743L, + 6757007617821370359L, + -2870340646674679163L, + 416331333845426881L, + -5319172016123138702L, + 3294412564645954555L, + 2812538484970453169L, + -9128349093860081905L, + 6784456254618976198L, + -2861881330654872638L, + 3912429093271518508L, + -2562542119887175820L, + 4835616088583228965L, + 427639171891209425L, + 2590582080178010045L, + -6288067880951692635L, + -3204510905067065501L, + 9008426291442999873L, + -4085962609397876083L, + -3786041297813905157L, + -6006475053574578261L, + -6174022276199807178L, + 7958957647277035097L, + 2915785807118517755L, + 2139592530283433011L, + -8562048562533248017L, + -4991735207930685025L, + 393144860250454082L, + -5852177196425420458L, + -2652303154023739579L, + 2079679586901234739L, + -1386526064824772584L, + 1574420554361329695L, + -855542130447493508L, + 8291940350733154044L, + -5330200233059892402L, + 5140782607921164290L, + -977254437067235218L, + -261520846651909307L, + -7369143208070837455L, + -4728766390712852111L, + -8572213434879266955L, + -6754813768712497692L, + 7946121307356573089L, + 504268959085012646L, + -5536654029698676818L, + -6021520522792328781L, + 6968613512520500871L, + 4029920623217569312L, + 2738878342460920492L, + 4562432005481165726L, + -1279037845195368028L, + 1746645308450474697L, + 2538150989161378915L, + 2012299649948738944L, + -3997559675475377347L, + -5939431505669672858L, + 2077103722387383456L, + -6188261335534632204L, + 8772504603740967633L, + -1653698997940568281L, + 1676948989756529271L, + 2377579815165102226L, + -2667481192445387240L, + -5498860615033631762L, + -2490865541169744469L, + -1233441883399707566L, + 5445263795307566596L, + 2288458809413275798L, + -5908274826918996877L, + 2909363406069168415L, + 2376032171261335687L, + -5215189045919902574L, + -6083327007632847329L, + 2462785604224107327L, + -6684045035730714275L, + 2409356208468676804L, + 2814747114160772803L, + -4529204412661254980L, + -8437511853472556883L, + 1819323657613892915L, + 6862685309651627151L, + -9210337863564319258L, + -3641041551811494963L, + -6791020794026796740L, + -5261661996953805298L, + -1953516254626596632L, + -5901591005960707793L, + -7413695905040596911L, + 2952256922297384020L, + -8427771021447591769L, + -6920139339436245233L, + 2967149838604559395L, + -3253499104068010353L, + -8473804925120692039L, + -3561285603521886085L, + -4453849179065102447L, + 2050092642498054323L, + -5626434133619314199L, + 7995075368278704248L, + 7685996432951370136L, + -8037783900933102779L, + 4601459625295412851L, + -4491938778497306775L, + -9089886217821142309L, + -3947191644612298897L, + 1364225714229764884L, + 2580394324892542249L, + -3765315378396862242L, + 6023794482194323576L, + -662753714084561214L, + 3080495347149127717L, + 911710215008202776L, + -803705685664586056L, + -6101059689379533503L, + -2122356322512227634L, + 8012110874513406695L, + -4158551223425336367L, + 8282080141813519654L, + 4172879384244246799L, + 708522065347490110L, + -6997269001146828181L, + 1887955086977822594L, + 8014460039616323415L + }; + + private static final long[] HASHES_OF_LOOPING_BYTES_WITH_SEED_42 = { + -7444071767201028348L, + -8959994473701255385L, + 7116559933691734543L, + 6019482000716350659L, + -6625277557348586272L, + -5507563483608914162L, + 1540412690865189709L, + 4522324563441226749L, + -7143238906056518746L, + -7989831429045113014L, + -7103973673268129917L, + -2319060423616348937L, + -7576144055863289344L, + -8903544572546912743L, + 6376815151655939880L, + 5913754614426879871L, + 6466567997237536608L, + -869838547529805462L, + -2416009472486582019L, + -3059673981515537339L, + 4211239092494362041L, + 1414635639471257331L, + 166863084165354636L, + -3761330575439628223L, + 3524931906845391329L, + 6070229753198168844L, + -3740381894759773016L, + -1268276809699008557L, + 1518581707938531581L, + 7988048690914090770L, + -4510281763783422346L, + -8988936099728967847L, + -8644129751861931918L, + 2046936095001747419L, + 339737284852751748L, + -8493525091666023417L, + -3962890767051635164L, + -5799948707353228709L, + -6503577434416464161L, + 7718729912902936653L, + 191197390694726650L, + -2677870679247057207L, + 20411540801847004L, + 2738354376741059902L, + -3754251900675510347L, + -3208495075154651980L, + 5505877218642938179L, + 6710910171520780908L, + -9060809096139575515L, + 6936438027860748388L, + -6675099569841255629L, + -5358120966884144380L, + -4970515091611332076L, + -1810965683604454696L, + -516197887510505242L, + 1240864593087756274L, + 6033499571835033332L, + 7223146028771530185L, + 909128106589125206L, + 1567720774747329341L, + -1867353301780159863L, + 4655107429511759333L, + 5356891185236995950L, + 182631115370802890L, + -3582744155969569138L, + 595148673029792797L, + 495183136068540256L, + 5536689004903505647L, + -8472683670935785889L, + -4335021702965928166L, + 7306662983232020244L, + 4285260837125010956L, + 8288813008819191181L, + -3442351913745287612L, + 4883297703151707194L, + 9135546183059994964L, + 123663780425483012L, + 509606241253238381L, + 5940344208569311369L, + -2650142344608291176L, + 3232776678942440459L, + -922581627593772181L, + 7617977317085633049L, + 7154902266379028518L, + -5806388675416795571L, + 4368003766009575737L, + -2922716024457242064L, + 4771160713173250118L, + 3275897444752647349L, + -297220751499763878L, + 5095659287766176401L, + 1181843887132908826L, + 9058283605301070357L, + 3984713963471276643L, + 6050484112980480005L, + 1551535065359244224L, + 565337293533335618L, + 7412521035272884309L, + -4735469481351389369L, + 6998597101178745656L, + -9107075101236275961L, + 5879828914430779796L, + 6034964979406620806L, + 5666406915264701514L, + -4666218379625258428L, + 2749972203764815656L, + -782986256139071446L, + 6830581400521008570L, + 2588852022632995043L, + -5484725487363818922L, + -3319556935687817112L, + 6481961252981840893L, + 2204492445852963006L, + -5301091763401031066L, + -2615065677047206256L, + -6769817545131782460L, + -8421640685322953142L, + -3669062629317949176L, + -9167016978640750490L, + 2783671191687959562L, + -7599469568522039782L, + -7589134103255480011L, + -5932706841188717592L, + -8689756354284562694L, + -3934347391198581249L, + -1344748563236040701L, + 2172701592984478834L, + -5322052340624064417L, + -8493945390573620511L, + 3349021988137788403L, + -1806262525300459538L, + -8091524448239736618L, + 4022306289903960690L, + -8346915997379834224L, + -2106001381993805461L, + -5784123934724688161L, + 6775158099649720388L, + -3869682756870293568L, + 4356490186652082006L, + 8469371446702290916L, + -2972961082318458602L, + -7188106622222784561L, + -4961006366631572412L, + 3199991182014172900L, + 2917435868590434179L, + 8385845305547872127L, + 7706824402560674655L, + -1587379863634865277L, + -4212156212298809650L, + -1305209322000720233L, + -7866728337506665880L, + 8195089740529247049L, + -4876930125798534239L, + 798222697981617129L, + -2441020897729372845L, + -3926158482651178666L, + -1254795122048514130L, + 5192463866522217407L, + -5426289318796042964L, + -3267454004443530826L, + 471043133625225785L, + -660956397365869974L, + -6149209189144999161L, + -2630977660039166559L, + 8512219789663151219L, + -3309844068134074620L, + -6211275327487847132L, + -2130171729366885995L, + 6569302074205462321L, + 4855778342281619706L, + 3867211421508653033L, + -3002480002418725542L, + -8297543107467502696L, + 8049642289208775831L, + -5439825716055425635L, + 7251760070798756432L, + -4774526021749797528L, + -3892389575184442548L, + 5162451061244344424L, + 6000530226398686578L, + -5713092252241819676L, + 8740913206879606081L, + -8693282419677309723L, + 1576205127972543824L, + 5760354502610401246L, + 3173225529903529385L, + 1785166236732849743L, + -1024443476832068882L, + -7389053248306187459L, + 1171021620017782166L, + 1471572212217428724L, + 7720766400407679932L, + -8844781213239282804L, + -7030159830170200877L, + 2195066352895261150L, + 1343620937208608634L, + 9178233160016731645L, + -757883447602665223L, + 3303032934975960867L, + -3685775162104101116L, + -4454903657585596656L, + -5721532367620482629L, + 8453227136542829644L, + 5397498317904798888L, + 7820279586106842836L, + -2369852356421022546L, + 3910437403657116169L, + 6072677490463894877L, + -2651044781586183960L, + 5173762670440434510L, + -2970017317595590978L, + -1024698859439768763L, + -3098335260967738522L, + -1983156467650050768L, + -8132353894276010246L, + -1088647368768943835L, + -3942884234250555927L, + 7169967005748210436L, + 2870913702735953746L, + -2207022373847083021L, + 1104181306093040609L, + 5026420573696578749L, + -5874879996794598513L, + -4777071762424874671L, + -7506667858329720470L, + -2926679936584725232L, + -5530649174168373609L, + 5282408526788020384L, + 3589529249264153135L, + -6220724706210580398L, + -7141769650716479812L, + 5142537361821482047L, + -7029808662366864423L, + -6593520217660744466L, + 1454581737122410695L, + -139542971769349865L, + 1727752089112067235L, + -775001449688420017L, + -5011311035350652032L, + -8671171179275033159L, + -2850915129917664667L, + -5258897903906998781L, + -6954153088230718761L, + -4070351752166223959L, + -6902592976462171099L, + -7850366369290661391L, + -4562443925864904705L, + 3186922928616271015L, + 2208521081203400591L, + -2727824999830592777L, + -3817861137262331295L, + 2236720618756809066L, + -4888946967413746075L, + -446884183491477687L, + -43021963625359034L, + -5857689226703189898L, + -2156533592262354883L, + -2027655907961967077L, + 7151844076490292500L, + -5029149124756905464L, + 526404452686156976L, + 8741076980297445408L, + 7962851518384256467L, + -105985852299572102L, + -2614605270539434398L, + -8265006689379110448L, + 8158561071761524496L, + -6923530157382047308L, + 5551949335037580397L, + 565709346370307061L, + -4780869469938333359L, + 6931895917517004830L, + 565234767538051407L, + -8663136372880869656L, + 1427340323685448983L, + 6492705666640232290L, + 1481585578088475369L, + -1712711110946325531L, + 3281685342714380741L, + 6441384790483098576L, + -1073539554682358394L, + 5704050067194788964L, + -5495724689443043319L, + -5425043165837577535L, + 8349736730194941321L, + -4123620508872850061L, + 4687874980541143573L, + -468891940172550975L, + -3212254545038049829L, + -6830802881920725628L, + 9033050533972480988L, + 4204031879107709260L, + -677513987701096310L, + -3286978557209370155L, + 1644111582609113135L, + 2040089403280131741L, + 3323690950628902653L, + -7686964480987925756L, + -4664519769497402737L, + 3358384147145476542L, + -4699919744264452277L, + -4795197464927839170L, + 5051607253379734527L, + -8987703459734976898L, + 8993686795574431834L, + -2688919474688811047L, + 375938183536293311L, + 1049459889197081920L, + -1213022037395838295L, + 4932989235110984138L, + -6647247877090282452L, + -7698817539128166242L, + -3264029336002462659L, + 6487828018122309795L, + -2660821091484592878L, + 7104391069028909121L, + -1765840012354703384L, + 85428166783788931L, + -6732726318028261938L, + 7566202549055682933L, + 229664898114413280L, + -1474237851782211353L, + -1571058880058007603L, + -7926453582850712144L, + 2487148368914275243L, + 8740031015380673473L, + 1908345726881363169L, + -2510061320536523178L, + 7854780026906019630L, + -6023415596650016493L, + -6264841978089051107L, + 4024998278016087488L, + -4266288992025826072L, + -3222176619422665563L, + -1999258726038299316L, + 1715270077442385636L, + 6764658837948099754L, + -8646962299105812577L, + -51484064212171546L, + -1482515279051057493L, + -8663965522608868414L, + -256555202123523670L, + 1973279596140303801L, + -7280796173024508575L, + -5691760367231354704L, + -5915786562256300861L, + -3697715074906156565L, + 3710290115318541949L, + 6796151623958134374L, + -935299482515386356L, + -7078378973978660385L, + 5379481350768846927L, + -9011221735308556302L, + 5936568631579608418L, + -6060732654964511813L, + -4243141607840017809L, + 3198488845875349355L, + -7809288876010447646L, + 4371587872421472389L, + -1304197371105522943L, + 7389861473143460103L, + -1892352887992004024L, + 2214828764044713398L, + 6347546952883613388L, + 1275694314105480954L, + -5262663163358903733L, + 1524757505892047607L, + 1474285098416162746L, + -7976447341881911786L, + 4014100291977623265L, + 8994982266451461043L, + -7737118961020539453L, + -2303955536994331092L, + 1383016539349937136L, + 1771516393548245271L, + -5441914919967503849L, + 5449813464890411403L, + -3321280356474552496L, + 4084073849712624363L, + 4290039323210935932L, + 2449523715173349652L, + 7494827882138362156L, + 9035007221503623051L, + 5722056230130603177L, + -5443061851556843748L, + -7554957764207092109L, + 447883090204372074L, + 533916651576859197L, + -3104765246501904165L, + -4002281505194601516L, + -8402008431255610992L, + -408273018037005304L, + 214196458752109430L, + 6458513309998070914L, + 2665048360156607904L, + 96698248584467992L, + -3238403026096269033L, + 6759639479763272920L, + -4231971627796170796L, + -2149574977639731179L, + -1437035755788460036L, + -6000005629185669767L, + 145244292800946348L, + -3056352941404947199L, + 3748284277779018970L, + 7328354565489106580L, + -2176895260373660284L, + 3077983936372755601L, + 1215485830019410079L, + 683050801367331140L, + -3173237622987755212L, + -1951990779107873701L, + -4714366021269652421L, + 4934690664256059008L, + 1674823104333774474L, + -3974408282362828040L, + 2001478896492417760L, + -4115105568354384199L, + -2039694725495941666L, + -587763432329933431L, + -391276713546911316L, + -5543400904809469053L, + 1882564440421402418L, + -4991793588968693036L, + 3454088185914578321L, + 2290855447126188424L, + 3027910585026909453L, + 2136873580213167431L, + -6243562989966916730L, + 5887939953208193029L, + -3491821629467655741L, + -3138303216306660662L, + 8572629205737718669L, + 4154439973110146459L, + 5542921963475106759L, + -2025215496720103521L, + -4047933760493641640L, + -169455456138383823L, + -1164572689128024473L, + -8551078127234162906L, + -7247713218016599028L, + 8725299775220778242L, + 6263466461599623132L, + 7931568057263751768L, + 7365493014712655238L, + -7343740914722477108L, + 8294118602089088477L, + 7677867223984211483L, + -7052188421655969232L, + -3739992520633991431L, + 772835781531324307L, + 881441588914692737L, + 6321450879891466401L, + 5682516032668315027L, + 8493068269270840662L, + -3895212467022280567L, + -3241911302335746277L, + -7199586338775635848L, + -4606922569968527974L, + -806850906331637768L, + 2433670352784844513L, + -5787982146811444512L, + 7852193425348711165L, + 8669396209073850051L, + -6898875695148963118L, + 6523939610287206782L, + -8084962379210153174L, + 8159432443823995836L, + -2631068535470883494L, + -338649779993793113L, + 6514650029997052016L, + 3926259678521802094L, + 5443275905907218528L, + 7312187582713433551L, + -2993773587362997676L, + -1068335949405953411L, + 4499730398606216151L, + 8538015793827433712L, + -4057209365270423575L, + -1504284818438273559L, + -6460688570035010846L, + 1765077117408991117L, + 8278320303525164177L, + 8510128922449361533L, + 1305722765578569816L, + 7250861238779078656L, + -576624504295396147L, + -4363714566147521011L, + -5932111494795524073L, + 1837387625936544674L, + -4186755953373944712L, + -7657073597826358867L, + 140408487263951108L, + 5578463635002659628L, + 3400326044813475885L, + -6092804808386714986L, + -2410324417287268694L, + 3222007930183458970L, + 4932471983280850419L, + 3554114546976144528L, + -7216067928362857082L, + -6115289896923351748L, + -6769646077108881947L, + 4263895947722578066L, + 2939136721007694271L, + 1426030606447416658L, + -1316192446807442076L, + 5366182640480055129L, + 6527003877470258527L, + 5849680119000207603L, + 5263993237214222328L, + -6936533648789185663L, + -9063642143790846605L, + 3795892210758087672L, + 4987213125282940176L, + 2505500970421590750L, + -1014022559552365387L, + -3574736245968367770L, + 1180676507127340259L, + -2261908445207512503L, + -8416682633172243509L, + 1114990703652673283L, + 7753746660364401380L, + 1874908722469707905L, + 2033421444403047677L, + 21412168602505589L, + 385957952615286205L, + 2053171460074727107L, + 1915131899400103774L, + 6680879515029368390L, + 568807208929724162L, + -6211541450459087674L, + -5026690733412145448L, + 1384781941404886235L, + -98027820852587266L, + 1806580495924249669L, + 6322077317403503963L, + 9078162931419569939L, + -2809061215428363978L, + 7697867577577415733L, + -5270063855897737274L, + 5649864555290587388L, + -6970990547695444247L, + 579684606137331754L, + 3871931565451195154L, + 2030008578322050218L, + -5012357307111799829L, + -2271365921756144065L, + 4551962665158074190L, + -3385474923040271312L, + -7647625164191633577L, + 6634635380316963029L, + -5201190933687061585L, + 8864818738548593973L, + 2855828214210882907L, + 9154512990734024165L, + -6945306719789457786L, + 1200243352799481087L, + 875998327415853787L, + 1275313054449881011L, + -6105772045375948736L, + -2926927684328291437L, + 9200050852144954779L, + 5188726645765880663L, + 5197037323312705176L, + 3434926231010121611L, + -5054013669361906544L, + 2582959199749224670L, + -6053757512723474059L, + -5016308176846054473L, + -2509827316698626133L, + 7700343644503853204L, + -1997627249894596731L, + 3993168688325352290L, + -8181743677541277704L, + 3719056119682565597L, + -7264411659282947790L, + 7177028972346484464L, + -5460831176884283278L, + 1799904662416293978L, + -6549616005092764514L, + 5472403994001122052L, + 8683463751708388502L, + -7873363037838316398L, + 689134758256487260L, + -1287443614028696450L, + 4452712919702709507L, + 762909374167538893L, + 6594302592326281411L, + 1183786629674781984L, + 5021847859620133476L, + -2490098069181538915L, + 5105145136026716679L, + 4437836948098585718L, + 1987270426215858862L, + 6170312798826946249L, + 634297557126003407L, + -1672811625495999581L, + 6282971595586218191L, + 4549149305727581687L, + -5652165370435317782L, + 1064501550023753890L, + -5334885527127139723L, + -6904378001629481237L, + -1807576691784201230L, + -205688432992053911L, + 7621619053293393289L, + 6258649161313982470L, + -1111634238359342096L, + -8044260779481691987L, + 400270655839010807L, + -7806833581382890725L, + -2970563349459508036L, + -7392591524816802798L, + 2918924613160219805L, + -6444161627929149002L, + 6096497501321778876L, + -1477975665655830038L, + 1690651307597306138L, + -2364076888826085362L, + -6521987420014905821L, + -4419193480146960582L, + 3538587780233092477L, + 8374665961716940404L, + 7492412312405424500L, + 6311662249091276767L, + -1240235198282023566L, + 5478559631401166447L, + 3476714419313462133L, + 377427285984503784L, + 2570472638778991109L, + -2741381313777447835L, + -7123472905503039596L, + 2493658686946955193L, + 1024677789035847585L, + -2916713904339582981L, + -4532003852004642304L, + -2202143560366234111L, + 5832267856442755135L, + -261740607772957384L, + 239435959690278014L, + 5755548341947719409L, + 6138795458221887696L, + -7709506987360146385L, + -6657487758065140444L, + -7006376793203657499L, + 6544409861846502033L, + 3171929352014159247L, + 1051041925048792869L, + 2617300158375649749L, + 952652799620095175L, + -576661730162168147L, + -1634191369221345988L, + 4833656816115993519L, + 647566759700005786L, + 2473810683785291822L, + 3005977181064745326L, + -3321881966853149523L, + 7595337666427588699L, + 6004093624251057224L, + -563917505657690279L, + 6117428527147449302L, + -6287297509522976113L, + -4527219334756214406L, + 742626429298092489L, + 3057351806086972041L, + 645967551210272605L, + -4428701157828864227L, + 3236379103879435414L, + -8477089892132066300L, + -6127365537275859058L, + -4052490484706946358L, + -8004854976625046469L, + -3679456917426613424L, + -8212793762082595299L, + -818288739465424130L, + 1358812099481667095L, + 7835987612195254310L, + -3663247409614323059L, + -2931105150130396604L, + 7296136776835614792L, + -2014557408985889628L, + 7267662411237959788L, + 3699280615819277743L, + -212010675469091396L, + -6518374332458360120L, + 145026010541628849L, + 1879297324213501001L, + -7146296067751816833L, + -5002958800391379931L, + 6060682439924517608L, + -432234782921170964L, + -6669688947353256956L, + 7728943532792041267L, + 830911367341171721L, + 3396934884314289432L, + -779464156662780749L, + 2330041851883352285L, + -4783350380736276693L, + -5758476056890049254L, + -7551552301614791791L, + 1253334187723911710L, + -2685018208308798978L, + 5379636036360946454L, + 6154668487114681217L, + -8641287462255458898L, + 4676087643800649558L, + -2405142641398691475L, + 1088685126864246881L, + 6431149082338374041L, + -607357695335069155L, + -720970692129524140L, + 2648766932394044468L, + 8408344790179354573L, + -6193808387735667350L, + 7722524628524697419L, + -6975433852560238120L, + -2925851029234475295L, + -4274458387165211028L, + -8355836377702147319L, + 5278146397877332061L, + 8502098812383680707L, + 2292836642336580326L, + -6127608082651070062L, + 2222301962240611208L, + -1930887695854799378L, + 7640503480494894592L, + 1162652186586436094L, + -1918002592943761683L, + 7648998601717261840L, + -8472603250832757057L, + -988877663117552456L, + 2368458128168026494L, + -6480813811998475245L, + -5896967824416018967L, + -2593783161701820446L, + 6950098417530252598L, + 6362589545555771236L, + 7981389665448567125L, + 3954017080198558850L, + 1626078615050230622L, + 6650159066527969109L, + 697345338922935394L, + -1226816215461768626L, + 8740408765973837440L, + -4194155864629568323L, + 7016680023232424746L, + 6043281358142429469L, + -4201005667174376809L, + 1216727117859013155L, + 6367202436544203935L, + 35414869396444636L, + 3715622794033998412L, + 488654435687670554L, + -2503747297224687460L, + 3147101919441470388L, + -8248611218693190922L, + 970697264481229955L, + 3411465763826851418L, + 9117405004661599969L, + -5204346498331519734L, + -19637460819385174L, + -5039124225167977219L, + 2990108874601696668L, + -2623857460235459202L, + 4256291692861397446L, + 6724147860870760443L, + 3558616688507246537L, + 6487680097936412800L, + -6470792832935928161L, + 4314814550912237614L, + -1292878983006062345L, + 6791915152630414174L, + 5971652079925815310L, + 2557529546662864312L, + 466175054322801580L, + -585216717310746872L, + -2486640422147349036L, + 7212029603994220134L, + 3958995069888972500L, + 4950471855791412790L, + -3721948842035712763L, + -6184503487488243051L, + 4079570444585775332L, + -3952156172546996872L, + 4543894231118208322L, + -1739995588466209963L, + 9155948355455935530L, + 5821980345462207860L, + -2431287667309520417L, + -3890108130519441316L, + -558124689277030490L, + 6079823537335801717L, + 5409742395192364262L, + -2329885777717160453L, + -7332804342513677651L, + 1466490574975950555L, + -420549419907427929L, + -5249909814389692516L, + -5145692168206210661L, + 5934113980649113921L, + 3241618428555359661L, + -6622110266160980250L, + 5048250878669516223L, + 5747219637359976174L, + 2975906212588223728L, + 5730216838646273215L, + -176713127129024690L, + 6734624279336671146L, + 5127866734316017180L, + 7111761230887705595L, + 3457811808274317235L, + 3362961434604932375L, + -1877869936854991246L, + 7171428594877765665L, + -8252167178400462374L, + -6306888185035821047L, + -6684702191247683887L, + -7754928454824190529L, + -1902605599135704386L, + -4037319846689421239L, + 8493746058123583457L, + -8156648963857047193L, + 2051510355149839497L, + -1256416624177218909L, + -3344927996254072010L, + -1838853051925943568L, + 316927471680974556L, + -1502257066700798003L, + -5836095610125837606L, + -1594125583615895424L, + 1442211486559637962L, + -144295071206619569L, + 5159850900959273410L, + 4589139881166423678L, + -7038726987463097509L, + 2886082400772974595L, + 2780759114707171916L, + 5694649587906297495L, + 1260349041268169667L, + 4921517488271434890L, + 644696475796073018L, + 6262811963753436289L, + -6128198676595868773L, + -3625352083004760261L, + -8751453332943236675L, + 8749249479868749221L, + -2450808199545048250L, + -6517435817046180917L, + -3433321727429234998L, + -2591586258908763451L, + 3847750870868804507L, + 6603614438546398643L, + -7598682191291031287L, + 8710261565627204971L, + 4753389483755344355L, + -4645333069458786881L, + -6742695046613492214L, + 643070478568866643L, + -7543096104151965610L, + 7171495384655926161L, + 595063872610714431L, + 3292310150781130424L, + 4326847806055440904L, + -4580020566072794152L, + 3142286571820373678L, + 5530356537440155930L, + 546372639737516181L, + 7401214477400367500L, + 7406531960402873109L, + 3287639667219172570L, + 4977301681213633671L, + 5253257820925174498L, + 2906216636104297878L, + 6142955758238347523L, + -3498651268741727235L, + -5875053958265588593L, + 3896719087169993883L, + -910904726885775073L, + 380107493197368177L, + -4993591912695447004L, + 2970487257212582761L, + 2551762717569548774L, + 953061649962736812L, + 8949739538606589463L, + -2962839167079475801L, + -1375673191272573835L, + 3761793818361866390L, + -389577789190726878L, + 5661262051502180269L, + -6558556411143987683L, + -702798336372315031L, + -336662820551371779L, + 998576401126580155L, + -5945021269112582755L, + 6108533925730179871L, + 2207095297001999618L, + -9042779159998880435L, + -6177868444342118372L, + 6775965402605895077L, + -3788428885163306576L, + 7790055010527190387L, + 3581587652196995358L, + -6176354155561607694L, + -5859381340906321207L, + 395898765763528395L, + 8132967590863909348L, + -3329092504090544483L, + -6785855381158040247L, + 1497218517051796750L, + -5352392845588925911L, + -6271364901230559194L, + 2314830370653350118L, + -7617588269001325450L, + 1423166885758213795L, + 8538612578307869519L, + -61918791718295474L, + -8177103503192338593L, + -4740086042584326695L, + 3677931948215558698L, + 6558856291580149558L, + 2674975452453336335L, + 5133796555646930522L, + 5139252693299337100L, + 7949476871295347205L, + 4407815324662880678L, + -3758305875280581215L, + 6066309507576587415L, + -7368508486398350973L, + -3181640264332856492L, + 6905100869343314145L, + 3677177673848733417L, + 8862933624870506941L, + -8575223195813810568L, + 9178470351355678144L, + 4677809017145408358L, + -1194833416287894989L, + 3436364743255571183L, + -5204770725795363579L, + 560599448536335263L, + -3192077522964776200L, + -751575299648803575L, + 6334581746534596579L, + -8358187891202563300L, + -1462480609823525055L, + 5605961062646987941L, + 4968399805931440889L, + 7968693270782626653L, + -5868205923557518188L, + 1830234928743560617L, + -8435261076693154407L, + 2138416970728681332L, + 8088740745199685138L, + 806532400344230520L, + 1800590379902909333L, + -8909128842071238901L, + -7357495566969170860L, + 3679766664126940553L, + 2060050474865839094L, + 2363972840121763414L, + 525695004292982714L, + -1224842191746529593L, + 7011317848855545003L, + -6337167558180299938L, + -5184688833363785939L, + -8426673387248359061L, + -5035438815930785229L, + 3521810320608058994L, + 4803742557254962242L, + 6623527039545786598L, + -1221475882122634738L, + -3344794405518401087L, + 6510298498414053658L, + 2844753907937720338L, + 90502309714994895L, + -750403235344282494L, + -4825474181021465833L, + -3405519947983849510L, + 3503875590944089793L, + 7286294700691822468L, + 7828126881500292486L, + 8437899353709338096L, + 136052254470293480L, + 1113259077339995086L, + -8244887265606191121L, + 8089569503800461649L, + -1429698194850157567L, + 1575595674002364989L, + 3576095286627428675L, + -7653655285807569222L, + -6053506977362539111L, + -3923855345805787169L, + -8001149080454232377L, + -4382867706931832271L, + 4212860258835896297L, + 4207674254247034014L, + 5519424058779519159L, + -754483042161434654L, + 1434113479814210082L, + -6416645032698336896L, + 5624329676066514819L, + -8229557208322175959L, + 3922640911653270376L, + 7826932478782081910L, + -4862787164488635842L, + 1449234668827944573L, + -1781657689570106327L, + 5442827552725289699L, + 3589862161007644641L, + 4787115581650652778L, + -3512152721942525726L, + -6750103117958685206L, + 5012970446659949261L, + 6797752795961689017L, + 5086454597639943700L, + -7616068364979994076L, + 1492846825433110217L, + 2967476304433704510L, + -8413824338284112078L, + -1319049442043273974L, + -1756090916806844109L, + -9061091728950139525L, + -6864767830358160810L, + 4879532090226251157L, + 5528644708740739488L + }; +} From 9536fcded0defe8b9ff92da8fcc5ae942f2b1143 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 20 Nov 2025 20:14:33 +0000 Subject: [PATCH 04/15] Add architectural decision records and project requirements documentation --- src/main/docs/decision-log.adoc | 68 +++++++++++++++++++++ src/main/docs/project-requirements.adoc | 81 +++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/main/docs/decision-log.adoc create mode 100644 src/main/docs/project-requirements.adoc diff --git a/src/main/docs/decision-log.adoc b/src/main/docs/decision-log.adoc new file mode 100644 index 00000000..584bbe91 --- /dev/null +++ b/src/main/docs/decision-log.adoc @@ -0,0 +1,68 @@ += Architectural Decision Log: Chronicle-Algorithms +:toc: left +:icons: font + +== ADR-001: Abstraction of Memory Access via `Access` Interface + +* **Status:** Accepted +* **Context:** The library needs to perform operations (Hashing, Locking, BitSet manipulation) on data that may reside on the Java Heap (byte arrays), in Direct Memory (ByteBuffers), or at raw memory addresses (off-heap). Implementing algorithms separately for each data source leads to code duplication and maintenance issues. +* **Decision:** Introduce a generic `Access` interface (extending `ReadAccess` and `WriteAccess`). +* **Details:** +** The `Access` interface defines primitive read/write methods (e.g., `readLong`, `writeInt`) and atomic operations (`compareAndSwap`). +** Implementations are created for specific sources: `NativeAccess` (Unsafe), `ByteBufferAccess`, `ArrayAccessors`. +** Algorithms accept an `Access` instance and a handle `T`, allowing the same logic to run regardless of where the data lives. +* **Consequences:** +** (+) Algorithms are written once and reused for all memory types. +** (+) Zero-overhead abstraction in JIT-compiled code (hot paths inline the accessors). +** (-) Slightly higher complexity in method signatures (passing Accessors and Handles). + +== ADR-002: Stateless Hash Function Design + +* **Status:** Accepted +* **Context:** Standard Java `MessageDigest` or object `hashCode` implementations often require object allocation or maintain internal state, which causes GC pressure in high-frequency trading environments. +* **Decision:** Implement `LongHashFunction` as immutable, stateless singletons (or simple data holders for seeds). +* **Details:** +** Methods like `hashBytes` or `hashMemory` take the input data directly and return a `long`. +** No objects are allocated during the hashing process. +** Implementations (City, Murmur, xxHash) are exposed via static factory methods on `LongHashFunction`. +* **Consequences:** +** (+) Zero allocation hashing suitable for latency-critical paths. +** (+) Thread-safe by design. + +== ADR-003: Three-Tier Locking Strategy (Read-Write-Update) + +* **Status:** Accepted +* **Context:** Standard `ReentrantReadWriteLock` is insufficient for scenarios requiring an "Update" lock—a state where a thread intends to write but can still read, preventing other writers but allowing other readers until the actual write occurs. Furthermore, standard locks cannot easily be stored in off-heap shared memory for IPC. +* **Decision:** Implement `ReadWriteUpdateLockingStrategy` interfaces that operate over the `Access` abstraction. +* **Details:** +** Locks are represented by state words (integers/longs) in memory. +** Supports an `Update` lock state which is mutually exclusive with other Update/Write locks but allows concurrent Readers. +** Supports atomic upgrades (Read -> Update -> Write) and downgrades. +* **Consequences:** +** (+) Enables complex concurrency patterns not possible with standard JDK locks. +** (+) Locks can be placed in shared memory mapped files for inter-process synchronization. + +== ADR-004: Fixed-Size "Flat" BitSets + +* **Status:** Accepted +* **Context:** `java.util.BitSet` is dynamic and heap-based. We require BitSets that map to fixed memory regions (e.g., hardware registers, shared memory buffers) with deterministic memory layout. +* **Decision:** Implement `BitSetFrame` and `ReusableBitSet`. +* **Details:** +** "Flat" implies the bitset is a contiguous block of memory without dynamic expansion. +** Provided implementations for Single-Threaded (non-atomic ops) and Concurrent (atomic CAS ops) usage. +* **Consequences:** +** (+) Deterministic memory usage. +** (+) Can overlay a BitSet onto arbitrary memory (e.g., network packets, shared memory). +** (-) Cannot resize dynamically; strictly bounded by the initialization size. + +== ADR-005: Native Byte Order Optimization + +* **Status:** Accepted +* **Context:** Hashing algorithms often process data in 4 or 8-byte chunks. Converting bytes to integers/longs requires handling Endianness. Java is Big-Endian by convention, but x86 hardware is Little-Endian. +* **Decision:** Detect `ByteOrder.nativeOrder()` and provide specialized implementations. +* **Details:** +** Classes like `CityHash_1_1` and `MurmurHash_3` have internal static subclasses for Big/Little endian. +** The implementation delegates to the version matching the architecture at runtime. +* **Consequences:** +** (+) Maximal performance on the host architecture (avoiding byte swapping). +** (-) Hash results may differ between Little-Endian and Big-Endian platforms for the same byte input (unless specifically handled to normalize, which varies per algorithm implementation). diff --git a/src/main/docs/project-requirements.adoc b/src/main/docs/project-requirements.adoc new file mode 100644 index 00000000..8635371b --- /dev/null +++ b/src/main/docs/project-requirements.adoc @@ -0,0 +1,81 @@ += Project Requirements: Chronicle-Algorithms +:toc: left +:icons: font + +== 1. Overview + +The **Chronicle-Algorithms** project aims to provide a library of high-performance, zero-allocation algorithms designed for low-latency Java applications. The primary focus is on efficiency, off-heap memory capabilities, and minimizing Garbage Collection (GC) pressure. + +The library encompasses four main functional areas: +. Hashing +. Bit Set Operations +. Memory Access (Bytes) +. Off-Heap Locking + +== 2. Functional Requirements + +=== 2.1. Hashing +The system must provide efficient, non-cryptographic hash functions capable of processing various inputs producing 64-bit hash values. + +* **Algorithms:** +** Must implement **CityHash 1.1**. +** Must implement **MurmurHash3**. +** Must implement **xxHash r39**. +* **Input Support:** +** Must support hashing of Java primitives (`long`, `int`, `short`, `char`, `byte`, `boolean`). +** Must support hashing of byte arrays (`byte[]`), `ByteBuffer`, `String`, and `StringBuilder`. +** Must support hashing of raw memory addresses (off-heap memory). +* **Configuration:** +** Must allow hashing with and without seed values. +** Must handle Endianness (Little-Endian vs Big-Endian) correctly, optimizing for native byte order where possible. + +=== 2.2. Bit Set Operations +The system must provide a `BitSet` implementation that operates efficiently on contiguous memory regions, including off-heap memory. + +* **Core Operations:** +** Support standard bit manipulations: `set`, `clear`, `flip`, `get`. +** Support range operations: `setRange`, `clearRange`, `flipRange`. +** Support search operations: `nextSetBit`, `nextClearBit`, `previousSetBit`, `previousClearBit`. +** Support continuous block operations: finding and setting/clearing `N` continuous bits. +* **Concurrency:** +** Must provide a single-threaded implementation (`SingleThreadedFlatBitSetFrame`) for maximum raw performance. +** Must provide a thread-safe, concurrent implementation (`ConcurrentFlatBitSetFrame`) using atomic operations (CAS). +* **Storage:** +** Must abstract storage to allow BitSets to reside on Heap (arrays, ByteBuffers) or Off-Heap (Direct ByteBuffers, raw pointers). + +=== 2.3. Memory Access (Bytes) +The system must provide a unified abstraction layer for accessing memory to decouple algorithms from the underlying storage mechanism. + +* **Access API:** +** Define generic `ReadAccess` and `WriteAccess` interfaces. +** Provide concrete implementations for: +*** `NativeAccess` (using `Unsafe` for raw memory/arrays). +*** `ByteBufferAccess` (for `java.nio.ByteBuffer`). +*** `BytesStore` (integration with Chronicle-Bytes). +*** `RandomDataInput`/`RandomDataOutput`. +** Support reading/writing of all Java primitive types and unsigned variants at arbitrary offsets. +** Support atomic Compare-And-Swap (CAS) operations for concurrency primitives. + +=== 2.4. Locking Strategies +The system must provide locking mechanisms designed for shared memory and inter-process communication (IPC) scenarios. + +* **Lock Types:** +** **Read-Write Locks:** Allow multiple readers or one writer. +** **Read-Write-Update Locks:** Introduce an "Update" state allowing atomic upgrade from Read to Write. +* **Features:** +** Locks must be implementable over the generic `Access` interface (enabling off-heap locks). +** Support for "Wait" strategies to handle contention. +** Must provide `tryLock` capabilities for non-blocking attempts. +** Support for lock state upgrades (Read -> Update -> Write) and downgrades. + +== 3. Non-Functional Requirements + +* **Performance:** +** Algorithms must generate zero garbage (Zero Allocation) during steady-state operation. +** Hash functions must be optimized for native byte order execution. +* **Architecture:** +** The library must be modular, with a clear separation between the Algorithm logic and the Memory Access logic. +* **Compatibility:** +** Must support Java 8 and newer (implied by usage of `java.util.function` and diamond operators). +* **Safety:** +** While prioritizing performance, interfaces should provide mechanisms to validate inputs (e.g., array bounds) where feasible, though "Unsafe" implementations are expected to assume valid inputs for speed. From cdda0069b26209e39ba760461e2fa11098f38980 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Thu, 20 Nov 2025 20:15:06 +0000 Subject: [PATCH 05/15] Update .gitignore to include additional IDE and temporary files --- .gitignore | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c2c9b499..c361c527 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,8 @@ *.iml *.ipr *.iws -.idea +.idea/ +.claude/ compat_reports # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml @@ -25,4 +26,4 @@ target # tests *.bin -*.deleteme \ No newline at end of file +*.deleteme From e3b9066fa92b3321566394d34e3a7e17eb2e2817 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Fri, 21 Nov 2025 10:29:39 +0000 Subject: [PATCH 06/15] Code Analysis fixes --- .../net/openhft/chronicle/algo/bitset/ReusableBitSet.java | 2 +- .../algo/bitset/SingleThreadedFlatBitSetFrame.java | 2 +- .../net/openhft/chronicle/algo/hashing/CityHash_1_1.java | 5 ++--- .../net/openhft/chronicle/algo/hashing/MurmurHash_3.java | 3 +-- .../openhft/chronicle/algo/locks/TryAcquireOperations.java | 2 -- .../java/net/openhft/chronicle/algo/MemoryUnitTest.java | 3 +-- .../VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java | 6 ++---- .../locks/VanillaReadWriteWithWaitsLockingStrategyTest.java | 1 - 8 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java b/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java index 4ae834a4..ea286057 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java @@ -206,7 +206,7 @@ public Bits setBits() { * for iterating over set bits in the bit set. */ protected class Bits implements BitSet.Bits { - protected BitSetFrame.Bits frameBits; + protected final BitSetFrame.Bits frameBits; /** * Constructs a new Bits instance with the specified frame bits. diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java b/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java index ea522022..4cab4a26 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java @@ -1451,7 +1451,7 @@ public long next(Access access, T handle, long offset) { currentWord = (l >>> trailingZeros) >>> 1; return bitIndex += trailingZeros + 1; } - for (long i = byteIndex, lim = byteLength; (i += 8) < lim; ) { + for (long i = byteIndex; (i += 8) < byteLength; ) { if ((l = access.readLong(handle, i)) != 0) { byteIndex = i; int trailingZeros = numberOfTrailingZeros(l); diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java b/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java index 33980a07..ef36b768 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java @@ -452,9 +452,8 @@ public long hashShort(short input) { @Override public long hashChar(char input) { - int unsignedInput = input; - int firstByte = (unsignedInput >> FIRST_SHORT_BYTE_SHIFT) & FIRST_SHORT_BYTE_MASK; - int secondByte = (unsignedInput >> SECOND_SHORT_BYTE_SHIFT) & SECOND_SHORT_BYTE_MASK; + int firstByte = ((int) input >> FIRST_SHORT_BYTE_SHIFT) & FIRST_SHORT_BYTE_MASK; + int secondByte = ((int) input >> SECOND_SHORT_BYTE_SHIFT) & SECOND_SHORT_BYTE_MASK; long hash = hash1To3Bytes(2, firstByte, secondByte, secondByte); return finalizeHash(hash); } diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java b/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java index 08d7ff68..39741f1a 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/MurmurHash_3.java @@ -409,8 +409,7 @@ long seed() { long hashNativeLong(long nativeLong, long len) { long seed = this.seed; long h1 = seed ^ mixK1(nativeLong); - long h2 = seed; - return MurmurHash_3.finalize(len, h1, h2); + return MurmurHash_3.finalize(len, h1, seed); } @Override diff --git a/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java b/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java index a4b0d343..b9d9c133 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperations.java @@ -3,8 +3,6 @@ */ package net.openhft.chronicle.algo.locks; -import net.openhft.chronicle.algo.bytes.Access; - /** * Utility class providing various {@link TryAcquireOperation} implementations * for different locking strategies. diff --git a/src/test/java/net/openhft/chronicle/algo/MemoryUnitTest.java b/src/test/java/net/openhft/chronicle/algo/MemoryUnitTest.java index a5e2bfb4..ce225b47 100644 --- a/src/test/java/net/openhft/chronicle/algo/MemoryUnitTest.java +++ b/src/test/java/net/openhft/chronicle/algo/MemoryUnitTest.java @@ -46,8 +46,7 @@ static Stream alignmentPairs() { @DisplayName("align throws for invalid granularity combinations") void alignRejectsFinerOrEqualUnits() { for (MemoryUnit unit : MemoryUnit.values()) { - MemoryUnit finalUnit = unit; - assertThrows(IllegalStateException.class, () -> finalUnit.align(1, finalUnit)); + assertThrows(IllegalStateException.class, () -> unit.align(1, unit)); for (int coarser = unit.ordinal() + 1; coarser < MemoryUnit.values().length; coarser++) { MemoryUnit coarserUnit = MemoryUnit.values()[coarser]; assertThrows(IllegalStateException.class, () -> unit.align(1, coarserUnit)); diff --git a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java index 4cbaaeac..b0ee7177 100644 --- a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java +++ b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java @@ -95,8 +95,7 @@ void testCheckWaitWordForIncrement() { int waitWord = MAX_WAIT - 1; assertDoesNotThrow(() -> checkWaitWordForIncrement(waitWord)); - int maxWaitWord = MAX_WAIT; - assertThrows(IllegalMonitorStateException.class, () -> checkWaitWordForIncrement(maxWaitWord)); + assertThrows(IllegalMonitorStateException.class, () -> checkWaitWordForIncrement(MAX_WAIT)); } @Test @@ -122,8 +121,7 @@ void testTryWriteLockAndDeregisterWait0() { @Test void testCheckExclusiveUpdateLocked() { - int countWord = UPDATE_PARTY; - assertTrue(checkExclusiveUpdateLocked(countWord)); + assertTrue(checkExclusiveUpdateLocked(UPDATE_PARTY)); int nonExclusiveUpdateCountWord = UPDATE_PARTY + 1; assertFalse(checkExclusiveUpdateLocked(nonExclusiveUpdateCountWord)); diff --git a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java index 9dae9caf..a9d9ca1f 100644 --- a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java +++ b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteWithWaitsLockingStrategyTest.java @@ -4,7 +4,6 @@ package net.openhft.chronicle.algo.locks; import net.openhft.chronicle.algo.bytes.Access; -import net.openhft.chronicle.algo.bytes.ReadAccess; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; From 84963476bd9f8e151a2bea7cdc036f4928ec9233 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 08:53:33 +0000 Subject: [PATCH 07/15] Enhance documentation for AddressWrapper and related classes, adding detailed method descriptions and clarifying purpose --- .../algorithms/measures/AddressWrapper.java | 17 +++++++++- .../algorithms/measures/AddressWrappers.java | 31 ++++++++++++++++++- .../algorithms/measures/AvalancheScore.java | 14 +++++---- .../algorithms/measures/CheckMain.java | 12 +++++++ .../algorithms/measures/MainBytes.java | 12 +++++++ .../algorithms/measures/MaskHashScore.java | 9 +++--- .../measures/OrtogonalBitsScore.java | 11 ++++++- .../algorithms/measures/package-info.java | 16 ++++++++++ 8 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrapper.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrapper.java index f33235cc..b553b876 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrapper.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrapper.java @@ -4,10 +4,25 @@ package net.openhft.chronicle.algorithms.measures; /** - * Created by peter on 21/08/15. + * Minimal adapter that exposes a contiguous block of memory so hashing strategies can be compared + * without caring about the backing implementation. + *

+ * Implementations typically wrap off-heap memory and feed it into a hash function that operates on + * raw addresses instead of Java arrays. */ public interface AddressWrapper { + /** + * Point the wrapper at the supplied address range. + * + * @param address start address of the readable data + * @param length number of readable bytes from that address + */ void setAddress(long address, long length); + /** + * Hash the currently configured address range. + * + * @return hash value calculated over the configured memory region + */ long hash(); } diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrappers.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrappers.java index 9cdd6e8b..cc4bf2f1 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrappers.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AddressWrappers.java @@ -14,9 +14,16 @@ import java.util.Random; /** - * Created by peter on 21/08/15. + * Collection of {@link AddressWrapper} implementations used to exercise hashing strategies over + * native memory. + *

+ * Each constant implements {@link #setAddress(long, long)} and {@link #hash()} using a different + * hashing approach so quality and performance can be compared by the score harnesses. */ public enum AddressWrappers implements AddressWrapper { + /** + * Returns a random {@code long} irrespective of the provided address. + */ RANDOM { Random rand = new Random(); @@ -29,6 +36,9 @@ public long hash() { return rand.nextLong(); } }, + /** + * Uses {@link SecureRandom} to return unpredictable values. + */ SECURE_RANDOM { SecureRandom rand = new SecureRandom(); @@ -42,6 +52,9 @@ public long hash() { } }, + /** + * Wraps the address as a {@link Bytes} and hashes using {@link OptimisedBytesStoreHash}. + */ VANILLA { int length; Bytes bytes; @@ -59,6 +72,9 @@ public long hash() { return OptimisedBytesStoreHash.applyAsLong32bytesMultiple(bytes, length); } }, + /** + * Hashes the memory region using {@link LongHashFunction#city_1_1()}. + */ CITY_1_1 { long address,length; @@ -73,6 +89,9 @@ public long hash() { return LongHashFunction.city_1_1().hash((Object) null, NativeAccess.instance(), address, length); } }, + /** + * Hashes the memory region using {@link LongHashFunction#murmur_3()}. + */ MURMUR_3 { long address,length; @@ -87,6 +106,10 @@ public long hash() { return LongHashFunction.murmur_3().hash((Object) null, NativeAccess.instance(), address, length); } }, + /** + * Builds a 32-bit hash by iterating over bytes as characters and applying the JDK + * {@link java.util.HashMap} agitation function to reduce collisions. + */ STRING32 { Bytes bytes; @@ -115,6 +138,9 @@ int hash(int h) { return h ^ (h >>> 7) ^ (h >>> 4); } }, + /** + * Builds a 64-bit hash using a similar approach to {@link #STRING32} but keeping more entropy. + */ STRING64 { Bytes bytes; @@ -139,6 +165,9 @@ long hash(long h) { return h ^ (h >>> 14) ^ (h >>> 7); } }, + /** + * Generates the raw 32-bit polynomial hash without the extra agitation step. + */ STRING32_WITHOUT_AGITATE { Bytes bytes; diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AvalancheScore.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AvalancheScore.java index 3478ccc0..3183aaff 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AvalancheScore.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/AvalancheScore.java @@ -9,16 +9,18 @@ import java.util.Arrays; /** - * Created by peter on 22/08/15. + * Measures the avalanche behaviour of a hash function using a SMHasher inspired workload. + *

+ * The test repeatedly flips individual input bits and observes how close the output comes to the + * ideal 50/50 bit flip distribution. A lower returned value indicates better avalanche properties. */ public class AvalancheScore { /** - * Based on the SMHasher Avalanche test - *

- * search for biases bits. - * when flipping a single bit of the input, the output should have a 49% - 51% chance of flipping. Some randomness is expected. + * Runs the avalanche test and reports the 99th percentile drift from the ideal 50 percent flip + * rate. * - * @return the worst flip bias. + * @param wrapper implementation used to hash raw memory + * @return 99th percentile deviation from the ideal bit flip percentage */ public static double score(AddressWrapper wrapper) { int runs = 1000; diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/CheckMain.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/CheckMain.java index 89cf190a..4e9373e7 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/CheckMain.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/CheckMain.java @@ -38,6 +38,18 @@ Mask of Hash: 99%tile collisions: 1816 */ public class CheckMain { + + /** + * Command line harness that runs the hash quality measures for all configured address wrapper + * variants and prints summary statistics. + * + *

For each {@link AddressWrappers} entry this tool evaluates orthogonal bit scores, + * avalanche behaviour, and masked hash collisions using {@link OrtogonalBitsScore}, + * {@link AvalancheScore}, and {@link MaskHashScore}. The output is intended for manual + * inspection when comparing hash implementations, not for use on application hot paths. + * + * @param args ignored + */ public static void main(String[] args) { for (AddressWrappers aw : AddressWrappers.values()) { System.out.println(aw); diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MainBytes.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MainBytes.java index 50a588a6..99b8c556 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MainBytes.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MainBytes.java @@ -19,6 +19,18 @@ import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; +/** + * JMH microbenchmark that compares different hashing strategies over {@link Bytes} payloads. + * + *

The benchmark fills a direct {@link Bytes} instance with pseudo random 64 bit values and + * measures the throughput and latency of several hashing functions, including + * {@link OptimisedBytesStoreHash}, {@link LongHashFunction#city_1_1()}, {@link LongHashFunction#murmur_3()}, + * and {@link LongHashFunction#xx_r39()}. Payload size is controlled by the {@link #size} parameter. + * + *

When run under a debugger ({@link Jvm#isDebug()} is true) the benchmark methods are invoked + * directly. In normal operation the {@link Runner} entry point is used to execute the configured + * JMH benchmarks. + */ @State(Scope.Thread) public class MainBytes { static final LongHashFunction city_1_1 = LongHashFunction.city_1_1(); diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MaskHashScore.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MaskHashScore.java index 99815b09..ac6078cd 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MaskHashScore.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/MaskHashScore.java @@ -11,13 +11,14 @@ import java.util.Set; /** - * Created by peter on 22/08/15. + * Evaluates how evenly the low bits of a hash function are distributed. + *

+ * The routine hashes many one-bit variations of an input buffer and counts collisions after + * applying a bitmask, highlighting bias in the lower bits of the hash output. */ public class MaskHashScore { /** - * This test looks at how many collision you get in the lower bits. - * It generates 8K hashes, for 8Kbit input and look at at the lower 14 bits (for 16K values) - * The ideal is 8K unique hashes after mask. + * Run the masked hash collision test and return the 99th percentile number of collisions. */ public static double score(AddressWrapper wrapper) { int runs = 2000; diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/OrtogonalBitsScore.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/OrtogonalBitsScore.java index 277362cb..f5d73e3b 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/OrtogonalBitsScore.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/OrtogonalBitsScore.java @@ -9,9 +9,18 @@ import java.util.Arrays; /** - * Created by peter on 21/08/15. + * Scores how orthogonal the outputs of a hash function are when single input bits flip. + *

+ * The metric penalises pairs of outputs whose Hamming distance is too small, providing a measure of + * output independence across nearby inputs. */ public class OrtogonalBitsScore { + /** + * Execute the orthogonality test and return the 99th percentile penalty score. + * + * @param wrapper implementation used to hash a native memory block + * @return high percentile cumulative penalty; lower values indicate better independence + */ public static long score(AddressWrapper wrapper) { int runs = 1000; long[] scores = new long[runs]; diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java new file mode 100644 index 00000000..129db537 --- /dev/null +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java @@ -0,0 +1,16 @@ +/** + * Hash function quality measures and related tooling. + * + *

This package contains small utilities and command line tools used to + * evaluate the statistical properties of hash functions, for example + * avalanche behaviour and bit flip bias. It is primarily intended for + * benchmarking and research, not for use on application hot paths. + * + *

The contents of this package are considered internal test support for + * Chronicle Algorithms and may change without notice. Applications should + * depend on the hashing and bytes abstractions in + * {@code net.openhft.chronicle.algo.hashing} and + * {@code net.openhft.chronicle.algo.bytes} instead. + */ +package net.openhft.chronicle.algorithms.measures; + From 0f94d374386193573b1ba1e4810031d4a27443fb Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 08:53:44 +0000 Subject: [PATCH 08/15] Add architecture overview, decision log, requirements, security review, and testing strategy documentation --- src/main/docs/architecture-overview.adoc | 26 ++ src/main/docs/decision-log.adoc | 290 +++++++++++++++++------ src/main/docs/project-requirements.adoc | 270 ++++++++++++++++----- src/main/docs/security-review.adoc | 23 ++ src/main/docs/testing-strategy.adoc | 30 +++ 5 files changed, 507 insertions(+), 132 deletions(-) create mode 100644 src/main/docs/architecture-overview.adoc create mode 100644 src/main/docs/security-review.adoc create mode 100644 src/main/docs/testing-strategy.adoc diff --git a/src/main/docs/architecture-overview.adoc b/src/main/docs/architecture-overview.adoc new file mode 100644 index 00000000..9d10791b --- /dev/null +++ b/src/main/docs/architecture-overview.adoc @@ -0,0 +1,26 @@ += Chronicle-Algorithms Architecture Overview +:toc: +:sectnums: +:lang: en-GB +:source-highlighter: rouge + +== Purpose +Chronicle-Algorithms provides zero-allocation, low-latency primitives for hashing, bit set operations, byte access abstractions, and lightweight lock strategies used across Chronicle libraries. + +== Module Scope +- Public packages: `net.openhft.chronicle.algo`, `.bitset`, `.bytes`, `.hashing`, `.locks` +- Internal packages: `net.openhft.chronicle.algo.internal` (do not use directly) +- Test/analysis utilities: `net.openhft.chronicle.algorithms.measures` (hash quality evaluations) + +== Design Points +- Off-heap friendly APIs: operate on Chronicle Bytes and direct buffers without allocation. +- Stable surface area: keep public interfaces stable within a major version; allow internal evolution. +- Performance focus: cache-friendly flat data structures and branch-light hashing paths. + +== Interactions +- Depends on Chronicle Core/Bytes for low-level buffer access. +- Consumed by higher-level Chronicle components that require hashing, bit set, and lock primitives. + +== Usage Notes +- Treat `internal` packages as implementation details. +- Prefer Chronicle Bytes-backed accessors where off-heap or zero-copy is required. diff --git a/src/main/docs/decision-log.adoc b/src/main/docs/decision-log.adoc index 584bbe91..df36e636 100644 --- a/src/main/docs/decision-log.adoc +++ b/src/main/docs/decision-log.adoc @@ -1,68 +1,222 @@ -= Architectural Decision Log: Chronicle-Algorithms -:toc: left -:icons: font - -== ADR-001: Abstraction of Memory Access via `Access` Interface - -* **Status:** Accepted -* **Context:** The library needs to perform operations (Hashing, Locking, BitSet manipulation) on data that may reside on the Java Heap (byte arrays), in Direct Memory (ByteBuffers), or at raw memory addresses (off-heap). Implementing algorithms separately for each data source leads to code duplication and maintenance issues. -* **Decision:** Introduce a generic `Access` interface (extending `ReadAccess` and `WriteAccess`). -* **Details:** -** The `Access` interface defines primitive read/write methods (e.g., `readLong`, `writeInt`) and atomic operations (`compareAndSwap`). -** Implementations are created for specific sources: `NativeAccess` (Unsafe), `ByteBufferAccess`, `ArrayAccessors`. -** Algorithms accept an `Access` instance and a handle `T`, allowing the same logic to run regardless of where the data lives. -* **Consequences:** -** (+) Algorithms are written once and reused for all memory types. -** (+) Zero-overhead abstraction in JIT-compiled code (hot paths inline the accessors). -** (-) Slightly higher complexity in method signatures (passing Accessors and Handles). - -== ADR-002: Stateless Hash Function Design - -* **Status:** Accepted -* **Context:** Standard Java `MessageDigest` or object `hashCode` implementations often require object allocation or maintain internal state, which causes GC pressure in high-frequency trading environments. -* **Decision:** Implement `LongHashFunction` as immutable, stateless singletons (or simple data holders for seeds). -* **Details:** -** Methods like `hashBytes` or `hashMemory` take the input data directly and return a `long`. -** No objects are allocated during the hashing process. -** Implementations (City, Murmur, xxHash) are exposed via static factory methods on `LongHashFunction`. -* **Consequences:** -** (+) Zero allocation hashing suitable for latency-critical paths. -** (+) Thread-safe by design. - -== ADR-003: Three-Tier Locking Strategy (Read-Write-Update) - -* **Status:** Accepted -* **Context:** Standard `ReentrantReadWriteLock` is insufficient for scenarios requiring an "Update" lock—a state where a thread intends to write but can still read, preventing other writers but allowing other readers until the actual write occurs. Furthermore, standard locks cannot easily be stored in off-heap shared memory for IPC. -* **Decision:** Implement `ReadWriteUpdateLockingStrategy` interfaces that operate over the `Access` abstraction. -* **Details:** -** Locks are represented by state words (integers/longs) in memory. -** Supports an `Update` lock state which is mutually exclusive with other Update/Write locks but allows concurrent Readers. -** Supports atomic upgrades (Read -> Update -> Write) and downgrades. -* **Consequences:** -** (+) Enables complex concurrency patterns not possible with standard JDK locks. -** (+) Locks can be placed in shared memory mapped files for inter-process synchronization. - -== ADR-004: Fixed-Size "Flat" BitSets - -* **Status:** Accepted -* **Context:** `java.util.BitSet` is dynamic and heap-based. We require BitSets that map to fixed memory regions (e.g., hardware registers, shared memory buffers) with deterministic memory layout. -* **Decision:** Implement `BitSetFrame` and `ReusableBitSet`. -* **Details:** -** "Flat" implies the bitset is a contiguous block of memory without dynamic expansion. -** Provided implementations for Single-Threaded (non-atomic ops) and Concurrent (atomic CAS ops) usage. -* **Consequences:** -** (+) Deterministic memory usage. -** (+) Can overlay a BitSet onto arbitrary memory (e.g., network packets, shared memory). -** (-) Cannot resize dynamically; strictly bounded by the initialization size. - -== ADR-005: Native Byte Order Optimization - -* **Status:** Accepted -* **Context:** Hashing algorithms often process data in 4 or 8-byte chunks. Converting bytes to integers/longs requires handling Endianness. Java is Big-Endian by convention, but x86 hardware is Little-Endian. -* **Decision:** Detect `ByteOrder.nativeOrder()` and provide specialized implementations. -* **Details:** -** Classes like `CityHash_1_1` and `MurmurHash_3` have internal static subclasses for Big/Little endian. -** The implementation delegates to the version matching the architecture at runtime. -* **Consequences:** -** (+) Maximal performance on the host architecture (avoiding byte swapping). -** (-) Hash results may differ between Little-Endian and Big-Endian platforms for the same byte input (unless specifically handled to normalize, which varies per algorithm implementation). += Chronicle-Algorithms Decision Log +:toc: +:sectnums: +:lang: en-GB +:source-highlighter: rouge + +Chronicle-Algorithms records architectural and design decisions using two ID streams: + +* `ALGO-DEC-*` for module-level decisions aligned to requirements. +* `ADR-*` for architectural decision records that may cut across multiple features. + +Both sets are captured in this unified decision log. + +[[ALGO-DEC-001]] +== Decision ALGO-DEC-001: Non-Cryptographic Hash Focus +*Status:* Accepted +*Linked requirements:* <>, <>, <> + +=== Context +The module supplies hashes for data structures and indexing, where throughput and distribution matter more than cryptographic strength. + +=== Decision +Provide fast 64-bit non-cryptographic hashes (Murmur3, CityHash, xxHash) as the default set. + +=== Alternatives Considered + +* Cryptographic hashes: rejected due to higher latency and unnecessary security properties for this module's scope. + +=== Consequences + +* High throughput and good distribution for Chronicle data structures. +* Callers must not rely on these hashes for integrity or confidentiality; security-sensitive uses must choose other algorithms. + +[[ALGO-DEC-002]] +== Decision ALGO-DEC-002: Flat Bit Set Representation +*Status:* Accepted +*Linked requirements:* <>, <> + +=== Context +Bit sets back Chronicle structures that need predictable latency and cache-friendly scans. + +=== Decision +Represent bit sets as flat arrays of machine words with single-writer-friendly algorithms. + +=== Alternatives Considered + +* Hierarchical or segmented bit sets: rejected for higher traversal overhead and cache cost in target workloads. + +=== Consequences + +* Excellent sequential performance and memory locality. +* Extremely sparse large spaces may need additional upstream structures to avoid wasted memory. + +[[ALGO-DEC-003]] +== Decision ALGO-DEC-003: Zero-Copy Byte Access Abstractions +*Status:* Accepted +*Linked requirements:* <>, <>, <> + +=== Context +Hashing and related algorithms must read bytes from varied backings (on-heap, direct buffers, Chronicle Bytes) with minimal overhead and safe bounds. + +=== Decision +Provide accessor interfaces that wrap caller-owned storage without copying, while enforcing bounds checks at API edges. + +=== Alternatives Considered + +* Copy inputs into owned buffers: rejected to avoid allocation and duplicate storage. + +=== Consequences + +* Minimal allocation and no implicit copies. +* Callers remain responsible for storage lifecycle and for ensuring buffers stay valid during use. + +[[ADR-001]] +== Decision ADR-001: Abstraction of Memory Access via `Access` Interface +*Status:* Accepted + +=== Context +The library must perform operations (hashing, locking, bit set manipulation) on data that may reside: + +* On the Java heap (byte arrays), +* In direct memory (`ByteBuffer`), +* At raw memory addresses (off-heap). + +Implementing algorithms separately for each data source leads to code duplication and maintenance issues. + +=== Decision +Introduce a generic `Access` interface (extending `ReadAccess` and `WriteAccess`) to abstract memory access. + +=== Details + +* The `Access` interface defines primitive read and write methods (for example, `readLong`, `writeInt`) and atomic operations (for example, `compareAndSwap`). +* Implementations are created for specific sources, such as: + +* `NativeAccess` (Unsafe-backed), +* `ByteBufferAccess`, +* Array-backed accessors. +* Algorithms accept an `Access` instance and a handle `T`, allowing the same logic to run regardless of where the data lives. + +=== Consequences + +* Algorithms are written once and reused for all memory types. +* JIT-compilation can inline accessor calls, giving near zero-overhead abstraction in hot paths. +* Slightly higher complexity in method signatures (passing accessors and handles). + +[[ADR-002]] +== Decision ADR-002: Stateless Hash Function Design +*Status:* Accepted + +=== Context +Standard Java `MessageDigest` and many object `hashCode` implementations: + +* Often require object allocation, +* Maintain internal mutable state, + +which increases GC pressure in high-frequency trading and other latency-sensitive environments. + +=== Decision +Implement `LongHashFunction` as immutable, stateless singletons (or simple data holders for seeds). + +=== Details + +* Methods such as `hashBytes` or `hashMemory` take the input data directly and return a `long`. +* No heap objects are allocated during the hashing process. +* Concrete implementations (City, Murmur, xxHash) are exposed via static factory methods on `LongHashFunction`. + +=== Consequences + +* Zero-allocation hashing suitable for latency-critical paths. +* Thread-safe by design since the functions are stateless and immutable. + +[[ADR-003]] +== Decision ADR-003: Three-Tier Locking Strategy (Read-Write-Update) +*Status:* Accepted + +=== Context +Standard `ReentrantReadWriteLock` does not support an "Update" lock state where: + +* A thread intends to write but can still read, +* Other writers are blocked, +* Other readers may still proceed until the actual write. + +Standard JDK locks also cannot easily be stored in off-heap shared memory for inter-process coordination. + +=== Decision +Implement `ReadWriteUpdateLockingStrategy` interfaces that operate over the `Access` abstraction to support a three-tier lock model: Read, Update, and Write. + +=== Details + +* Locks are represented by state words (integers or longs) in memory. +* The Update lock state is: + +* Mutually exclusive with other Update and Write locks, +* Compatible with concurrent Readers. +* Supports atomic upgrades and downgrades: + +* Read -> Update -> Write, +* Write -> Read (and similar patterns as required). +* Lock state can be stored in shared memory mapped files or off-heap regions via `Access`. + +=== Consequences + +* Enables concurrency patterns not possible with standard JDK locks (for example, optimistic read with reserved write intent). +* Locks can be placed in shared memory for inter-process synchronisation. +* Complexity of reasoning about lock states is higher and must be carefully documented and tested. + +[[ADR-004]] +== Decision ADR-004: Fixed-Size Flat Bit Sets +*Status:* Accepted + +=== Context +`java.util.BitSet` is dynamic and heap-based. Chronicle-Algorithms requires bit sets that: + +* Map onto fixed memory regions (for example, hardware registers, shared memory buffers), +* Offer deterministic memory layout and size. + +This aligns with and elaborates on <>. + +=== Decision +Implement `BitSetFrame` and `ReusableBitSet` as fixed-size, "flat" bit set abstractions. + +=== Details + +* "Flat" means the bit set is a contiguous block of memory without dynamic expansion. +* Implementations are provided for: + +* Single-threaded usage (non-atomic operations), +* Concurrent usage (atomic CAS operations). +* Bit sets can be overlaid onto arbitrary memory regions (for example, network packets, shared memory segments). + +=== Consequences + +* Deterministic memory usage and layout. +* Bit sets can be used directly over hardware-facing or shared memory structures. +* Cannot resize dynamically; capacity is strictly bounded by the initial configuration, so upstream code must size correctly. + +[[ADR-005]] +== Decision ADR-005: Native Byte Order Optimisation +*Status:* Accepted + +=== Context +Hashing algorithms frequently process data in 4- or 8-byte chunks. Converting byte sequences to integers or longs must respect endianness: + +* Java's abstract view is big-endian, +* Common hardware (for example, x86) is little-endian. + +Naive implementations that always normalise to a single byte order can pay unnecessary byte-swapping costs. + +=== Decision +Detect `ByteOrder.nativeOrder()` at runtime and provide specialised implementations per native endianness. + +=== Details + +* Classes such as `CityHash_1_1` and `MurmurHash_3` have internal static subclasses or strategy variants for big-endian and little-endian. +* A small indirection on first use chooses the implementation matching the architecture. +* Subsequent calls are dispatched directly to the chosen variant. + +=== Consequences + +* Maximises performance on the host architecture by avoiding unnecessary byte-swapping. +* Hash results may differ between little-endian and big-endian platforms for the same byte input unless normalisation is explicitly added. +* Cross-platform consistency must be considered explicitly by callers that depend on identical hash values across architectures. diff --git a/src/main/docs/project-requirements.adoc b/src/main/docs/project-requirements.adoc index 8635371b..b75600ee 100644 --- a/src/main/docs/project-requirements.adoc +++ b/src/main/docs/project-requirements.adoc @@ -1,81 +1,223 @@ = Project Requirements: Chronicle-Algorithms :toc: left +:sectnums: +:lang: en-GB +:source-highlighter: rouge :icons: font == 1. Overview -The **Chronicle-Algorithms** project aims to provide a library of high-performance, zero-allocation algorithms designed for low-latency Java applications. The primary focus is on efficiency, off-heap memory capabilities, and minimizing Garbage Collection (GC) pressure. +The **Chronicle-Algorithms** project provides a library of high-performance, zero-allocation algorithms designed for low-latency Java applications. The primary focus is on: + +* efficiency and predictable latency, +* off-heap memory capabilities, +* minimising Garbage Collection (GC) pressure. The library encompasses four main functional areas: + . Hashing -. Bit Set Operations -. Memory Access (Bytes) -. Off-Heap Locking +. Bit set operations +. Memory access (Bytes and related abstractions) +. Off-heap locking strategies + +The remainder of this document captures both a concise requirements matrix (with IDs for traceability) and detailed narrative requirements for each area. == 2. Functional Requirements -=== 2.1. Hashing -The system must provide efficient, non-cryptographic hash functions capable of processing various inputs producing 64-bit hash values. - -* **Algorithms:** -** Must implement **CityHash 1.1**. -** Must implement **MurmurHash3**. -** Must implement **xxHash r39**. -* **Input Support:** -** Must support hashing of Java primitives (`long`, `int`, `short`, `char`, `byte`, `boolean`). -** Must support hashing of byte arrays (`byte[]`), `ByteBuffer`, `String`, and `StringBuilder`. -** Must support hashing of raw memory addresses (off-heap memory). -* **Configuration:** -** Must allow hashing with and without seed values. -** Must handle Endianness (Little-Endian vs Big-Endian) correctly, optimizing for native byte order where possible. - -=== 2.2. Bit Set Operations -The system must provide a `BitSet` implementation that operates efficiently on contiguous memory regions, including off-heap memory. - -* **Core Operations:** -** Support standard bit manipulations: `set`, `clear`, `flip`, `get`. -** Support range operations: `setRange`, `clearRange`, `flipRange`. -** Support search operations: `nextSetBit`, `nextClearBit`, `previousSetBit`, `previousClearBit`. -** Support continuous block operations: finding and setting/clearing `N` continuous bits. -* **Concurrency:** -** Must provide a single-threaded implementation (`SingleThreadedFlatBitSetFrame`) for maximum raw performance. -** Must provide a thread-safe, concurrent implementation (`ConcurrentFlatBitSetFrame`) using atomic operations (CAS). -* **Storage:** -** Must abstract storage to allow BitSets to reside on Heap (arrays, ByteBuffers) or Off-Heap (Direct ByteBuffers, raw pointers). - -=== 2.3. Memory Access (Bytes) +=== 2.1 Summary Matrix + +[%autowidth,cols="1,3,2"] +|=== +| ID | Requirement | Verification + +| [[ALGO-FN-001]]ALGO-FN-001 +| Provide high-throughput non-cryptographic hash functions (Murmur3, CityHash, xxHash) for Chronicle data structures. +| Unit tests, property tests for avalanche and distribution, JMH baselines. + +| [[ALGO-FN-002]]ALGO-FN-002 +| Offer flat, cache-friendly bit set implementations suitable for dense and sparse cases. +| Boundary and unit tests for indices and density extremes; property tests for set and scan operations. + +| [[ALGO-FN-003]]ALGO-FN-003 +| Expose byte access abstractions that unify on-heap arrays, direct buffers, and Chronicle Bytes inputs without copies. +| Compatibility tests across backings; fuzz tests for bounds and offset handling. + +| [[ALGO-FN-004]]ALGO-FN-004 +| Supply lightweight lock models tailored to Chronicle data structures without full `java.util.concurrent` overhead. +| Concurrency unit tests for state transitions and contention; microbenchmarks for hot paths. +|=== + +The following sub-sections elaborate these requirements. + +=== 2.2 Hashing (details for <>) + +The system must provide efficient, non-cryptographic hash functions capable of processing various inputs and producing 64-bit hash values. + +*Algorithms* + +* Must implement **CityHash 1.1**. +* Must implement **MurmurHash3**. +* Must implement **xxHash r39**. + +*Input support* + +* Must support hashing of Java primitives: `long`, `int`, `short`, `char`, `byte`, `boolean`. +* Must support hashing of: +** byte arrays (`byte[]`), +** `ByteBuffer`, +** `String`, +** `StringBuilder`. +* Must support hashing of raw memory addresses (off-heap memory). + +*Configuration and semantics* + +* Must allow hashing with and without seed values. +* Must handle endianness (little-endian versus big-endian) correctly, optimising for native byte order where possible (see performance requirement <>). +* Hash functions are non-cryptographic and must not be positioned or documented as suitable for integrity or confidentiality guarantees. + +=== 2.3 Bit Set Operations (details for <>) + +The system must provide bit set implementations that operate efficiently on contiguous memory regions, including off-heap memory, and are suitable for dense and sparse cases. + +*Core operations* + +* Support standard bit manipulations: `set`, `clear`, `flip`, `get`. +* Support range operations: `setRange`, `clearRange`, `flipRange`. +* Support search operations: `nextSetBit`, `nextClearBit`, `previousSetBit`, `previousClearBit`. +* Support continuous block operations: finding and setting or clearing `N` continuous bits. + +*Concurrency* + +* Must provide a single-threaded implementation (for example, `SingleThreadedFlatBitSetFrame`) for maximum raw performance. +* Must provide a thread-safe, concurrent implementation (for example, `ConcurrentFlatBitSetFrame`) using atomic operations (CAS). + +*Storage model* + +* Must abstract storage so that bit sets can reside: +** on-heap (arrays, `ByteBuffer`), and +** off-heap (direct `ByteBuffer`, raw pointers). +* Implementations must be flat and cache-friendly (contiguous machine words) to support predictable scans and low tail latency. + +=== 2.4 Memory Access (Bytes) (details for <>) + The system must provide a unified abstraction layer for accessing memory to decouple algorithms from the underlying storage mechanism. -* **Access API:** -** Define generic `ReadAccess` and `WriteAccess` interfaces. -** Provide concrete implementations for: -*** `NativeAccess` (using `Unsafe` for raw memory/arrays). -*** `ByteBufferAccess` (for `java.nio.ByteBuffer`). -*** `BytesStore` (integration with Chronicle-Bytes). -*** `RandomDataInput`/`RandomDataOutput`. -** Support reading/writing of all Java primitive types and unsigned variants at arbitrary offsets. -** Support atomic Compare-And-Swap (CAS) operations for concurrency primitives. - -=== 2.4. Locking Strategies -The system must provide locking mechanisms designed for shared memory and inter-process communication (IPC) scenarios. - -* **Lock Types:** -** **Read-Write Locks:** Allow multiple readers or one writer. -** **Read-Write-Update Locks:** Introduce an "Update" state allowing atomic upgrade from Read to Write. -* **Features:** -** Locks must be implementable over the generic `Access` interface (enabling off-heap locks). -** Support for "Wait" strategies to handle contention. -** Must provide `tryLock` capabilities for non-blocking attempts. -** Support for lock state upgrades (Read -> Update -> Write) and downgrades. +*Access API* + +* Define generic `ReadAccess` and `WriteAccess` interfaces. +* Provide concrete implementations for: +** `NativeAccess` (using `Unsafe` for raw memory and arrays). +** `ByteBufferAccess` (for `java.nio.ByteBuffer`). +** `BytesStore`-backed access (integration with Chronicle-Bytes). +** `RandomDataInput` and `RandomDataOutput`. +* Support reading and writing of all Java primitive types and unsigned variants at arbitrary offsets. + +*Concurrency primitives* + +* Support atomic compare-and-swap (CAS) operations for fields used by locks and other concurrency primitives. +* Respect the off-heap safety constraints in <> by providing bounds enforcement where appropriate. + +=== 2.5 Locking Strategies (details for <>) + +The system must provide locking mechanisms designed for shared memory and inter-process communication (IPC) scenarios and tuned for Chronicle data structures. + +*Lock types* + +* *Read-write locks*: allow multiple readers or one writer. +* *Read-write-update locks*: introduce an "Update" state allowing atomic upgrade from Read to Write while still permitting concurrent readers until commit. + +*Features* + +* Locks must be implementable over the generic `Access` interface, enabling off-heap or shared-memory lock placement. +* Must support "wait" strategies (for example, spin, yield, back-off) to handle contention without forcing specific policy into the algorithm layer. +* Must provide `tryLock` capabilities for non-blocking attempts. +* Must support lock state upgrades and downgrades: +** Read -> Update -> Write, +** Write -> Read (and other safe transitions as defined in the locking strategy). == 3. Non-Functional Requirements -* **Performance:** -** Algorithms must generate zero garbage (Zero Allocation) during steady-state operation. -** Hash functions must be optimized for native byte order execution. -* **Architecture:** -** The library must be modular, with a clear separation between the Algorithm logic and the Memory Access logic. -* **Compatibility:** -** Must support Java 8 and newer (implied by usage of `java.util.function` and diamond operators). -* **Safety:** -** While prioritizing performance, interfaces should provide mechanisms to validate inputs (e.g., array bounds) where feasible, though "Unsafe" implementations are expected to assume valid inputs for speed. +=== 3.1 Summary Matrix + +[%autowidth,cols="1,3,2"] +|=== +| ID | Requirement | Verification + +| [[ALGO-NF-P-001]]ALGO-NF-P-001 +| Performance: minimise allocation; hot-path methods avoid copying and favour predictable branches. +| JMH regression suite; allocation profiling on representative payloads. + +| [[ALGO-NF-S-001]]ALGO-NF-S-001 +| Off-heap safety: enforce bounds checks for any direct or Bytes-backed accessors and reject overflow sizes. +| Negative and bounds tests; fuzz inputs near overflow; SpotBugs and Checkstyle for unsafe patterns. + +| [[ALGO-NF-O-001]]ALGO-NF-O-001 +| Compatibility: maintain API stability within a major version; document any breaking changes. +| API compatibility review per release; deprecation notices; release notes. + +| [[ALGO-NF-O-002]]ALGO-NF-O-002 +| Observability: primitives remain deterministic with no hidden threads or background work; signal misuse explicitly. +| Unit tests asserting deterministic results and explicit exceptions; static analysis for thread creation or logging in hot paths. +|=== + +=== 3.2 Performance (details for <>) + +* Algorithms must generate zero garbage (zero allocation) during steady-state operation. +* Hash functions must be optimised for native byte order execution and must avoid unnecessary byte swapping. +* Bit set and locking operations must minimise branches and favour predictable branching where possible. +* Performance characteristics must be validated with: +** JMH regression suites over representative payload sizes and distributions. +** Allocation profiling to confirm zero or near-zero allocation in hot paths. + +=== 3.3 Safety and Off-Heap Access (details for <>) + +* Any direct or off-heap accessors must enforce bounds checks at API edges and reject overflow sizes. +* Unsafe or `Unsafe`-based implementations may assume valid inputs in some internal methods for speed, but public APIs must provide mechanisms for validation. +* Safety guarantees must be backed by: +** Negative tests and bounds tests that probe underflow and overflow scenarios. +** Fuzz tests that exercise offsets and lengths near boundaries. +** Static analysis (SpotBugs, Checkstyle) to detect unsafe usage patterns. + +=== 3.4 Compatibility (details for <>) + +* The library must be modular, with a clear separation between algorithm logic and memory access logic. +* Must support Java 8 and newer (for example, usage of `java.util.function` and diamond operators). +* Within a major version: +** Public APIs should remain stable. +** Any breaking change must be explicitly documented with: +*** Deprecation periods where feasible. +*** Clear notes in release documentation. +*** Migration hints for downstream users. + +=== 3.5 Observability and Determinism (details for <>) + +* Algorithms and primitives must be deterministic: +** No hidden background threads. +** No implicit scheduling or asynchronous tasks started from hot paths. +* Hot paths must avoid logging; any logging present must be clearly outside latency-critical sections. +* Misuse must be surfaced through explicit exceptions (for example, bounds violations) rather than silent coercion or truncation. +* Metrics or telemetry concerns are delegated to upstream Chronicle components; APIs should, however, be straightforward to wrap with metrics or tracing. + +== 4. Testing and Validation Expectations + +These expectations apply across all functional and non-functional requirements. + +* Keep Checkstyle and SpotBugs clean; justify any suppressions inline and tie them to specific requirements where relevant. +* Prefer deterministic unit and property tests for: +** Boundary indices (start, end, and out-of-range). +** Empty inputs and minimal sizes. +** Dense and sparse bit set cases. +** Hashing avalanche and distribution characteristics. +* Maintain performance baselines for representative workloads when changing algorithms; capture any material regression and document trade-offs. +* Log seeds on property test failures to aid exact reproduction of issues. + +== 5. Observability Expectations (expanded guidance for <>) + +* No background services or implicit threads may be created by this library without explicit opt-in API calls. +* Behaviour must remain deterministic across runs for the same inputs, excluding documented sources of non-determinism (for example, native CPU features). +* Signal misuse via: +** Clear, specific exception types and messages. +** Avoiding silent data truncation, wrap-around, or out-of-range coercion unless explicitly documented. +* Leave metrics and telemetry emission to upstream components, but: +** Keep APIs simple to decorate with metrics, tracing, or logging. +** Avoid patterns that make wrapping difficult (for example, extensive use of statics with hidden state). diff --git a/src/main/docs/security-review.adoc b/src/main/docs/security-review.adoc new file mode 100644 index 00000000..4d542af0 --- /dev/null +++ b/src/main/docs/security-review.adoc @@ -0,0 +1,23 @@ += Chronicle-Algorithms Security Review (Initial) +:toc: +:sectnums: +:lang: en-GB +:source-highlighter: rouge + +== Scope +Hashing, bit set, byte access, and lock primitives; includes off-heap friendly code paths. + +== Threat Considerations +- Bounds safety: validate indices and lengths for on/off-heap accesses to avoid memory corruption. +- Input handling: hashing APIs accept untrusted data; ensure size checks and avoid integer overflows. +- Concurrency: lock and bit set operations must not expose torn state or races when used as documented. +- Cryptography: only non-cryptographic hashes are included; do not use for confidentiality or integrity. + +== Current Posture +- No network or IO entry points in this module. +- No embedded secrets or key material. +- Static analysis (Checkstyle/SpotBugs) reports clean; rerun in CI on changes. + +== Follow-Ups +- Document any additional fuzz/security testing for hashing and bounds checks. +- Record any deviations or suppressions alongside rationale in future reviews. diff --git a/src/main/docs/testing-strategy.adoc b/src/main/docs/testing-strategy.adoc new file mode 100644 index 00000000..39489bcb --- /dev/null +++ b/src/main/docs/testing-strategy.adoc @@ -0,0 +1,30 @@ += Chronicle-Algorithms Testing Strategy +:toc: +:sectnums: +:lang: en-GB +:source-highlighter: rouge + +== Scope +Testing guidance for hashing, bit set, byte access, and lock primitives in Chronicle-Algorithms. + +== Unit and Property Testing +- Hashing: verify avalanche/distribution properties with randomised inputs and seeded property tests. +- Bit sets: cover empty, dense, and sparse cases; test boundary indices and concurrency assumptions where applicable. +- Bytes accessors: validate bounds checks, slice/offset handling, and behaviour with on-heap vs direct vs Chronicle Bytes backings. +- Locks: assert state transitions and contention paths without relying on `java.util.concurrent` locks. + +== Fuzz and Negative Testing +- Feed random and malformed inputs through hashing and bounds-sensitive paths to catch overflows and index errors. +- Include adversarial cases (large lengths, near-overflow sizes) for off-heap friendly accessors. + +== Performance Regression +- Maintain microbenchmarks (e.g., JMH) for hot paths: hash computation on typical payload sizes, bit set set/get/scan operations. +- Track baseline metrics; flag regressions when latency/throughput deviates beyond agreed thresholds. + +== Static Analysis and Checks +- Keep Checkstyle and SpotBugs clean; document any suppression rationale inline. +- Prefer deterministic tests with fixed seeds; log seeds on failure when randomness is involved. + +== Observability Expectations +- No hidden threads or background tasks in tests; keep measurements isolated. +- Fail fast on misuse (bounds violations) rather than silently truncating or wrapping inputs. From 3a888fee6749997722505deaa27025c319f88623 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 08:53:56 +0000 Subject: [PATCH 09/15] Improve documentation for BitSet algorithms and access strategies, clarifying purpose and usage --- .../openhft/chronicle/algo/MemoryUnit.java | 19 ++---- .../algo/bitset/BitSetAlgorithm.java | 8 +-- .../chronicle/algo/bitset/BitSetFrame.java | 9 ++- .../bitset/ConcurrentFlatBitSetFrame.java | 7 +- .../algo/bitset/FlatBitSetAlgorithm.java | 6 +- .../chronicle/algo/bitset/ReusableBitSet.java | 2 +- .../bitset/SingleThreadedFlatBitSetFrame.java | 7 +- .../chronicle/algo/bitset/package-info.java | 15 +++++ .../openhft/chronicle/algo/bytes/Access.java | 34 +++------- .../chronicle/algo/bytes/AccessCommon.java | 2 +- .../chronicle/algo/bytes/ArrayAccessors.java | 15 +++-- .../algo/bytes/ByteBufferAccess.java | 5 +- .../chronicle/algo/bytes/BytesAccessors.java | 10 +-- .../algo/bytes/RandomDataInputAccess.java | 4 +- .../algo/bytes/RandomDataOutputAccess.java | 6 +- .../chronicle/algo/bytes/ZeroAccess.java | 6 +- .../chronicle/algo/bytes/package-info.java | 15 +++++ .../chronicle/algo/hashing/CityHash_1_1.java | 65 ++++--------------- .../chronicle/algo/hashing/XxHash_r39.java | 22 ++----- .../chronicle/algo/hashing/package-info.java | 14 ++++ .../locks/AbstractReadWriteLockState.java | 4 +- .../algo/locks/AcquisitionStrategies.java | 3 +- .../algo/locks/AcquisitionStrategy.java | 2 +- .../chronicle/algo/locks/LockState.java | 6 +- .../chronicle/algo/locks/LockingStrategy.java | 5 +- .../algo/locks/ReadWriteLockState.java | 7 +- .../algo/locks/ReadWriteLockingStrategy.java | 7 +- .../algo/locks/ReadWriteUpdateLockState.java | 8 +-- .../locks/ReadWriteUpdateLockingStrategy.java | 7 +- .../ReadWriteUpdateWithWaitsLockState.java | 5 +- ...adWriteUpdateWithWaitsLockingStrategy.java | 5 +- .../locks/ReadWriteWithWaitsLockState.java | 5 +- .../algo/locks/TryAcquireOperation.java | 2 +- ...adWriteUpdateWithWaitsLockingStrategy.java | 48 +++----------- .../chronicle/algo/locks/package-info.java | 16 +++++ .../openhft/chronicle/algo/package-info.java | 14 ++++ 36 files changed, 201 insertions(+), 214 deletions(-) create mode 100644 src/main/java/net/openhft/chronicle/algo/bitset/package-info.java create mode 100644 src/main/java/net/openhft/chronicle/algo/bytes/package-info.java create mode 100644 src/main/java/net/openhft/chronicle/algo/hashing/package-info.java create mode 100644 src/main/java/net/openhft/chronicle/algo/locks/package-info.java create mode 100644 src/main/java/net/openhft/chronicle/algo/package-info.java diff --git a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java index ef06d4df..a08f1225 100644 --- a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java +++ b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java @@ -13,20 +13,11 @@ import java.util.concurrent.TimeUnit; /** - * A {@code MemoryUnit} represents memory amounts at a given unit of - * granularity and provides utility methods to convert across units. A - * {@code MemoryUnit} does not maintain memory information, but only - * helps organize and use memory amounts representations that may be maintained - * separately across various contexts. - * - *

Note than in this class kilo-, mega- and giga- prefixes means 2^10 = 1024 multiplexing, - * that is more common in low-level programming, CPU and operation system contexts, - * not 1000 as defined by International System of Units (SI). - * - *

A {@code MemoryUnit} is mainly used to inform memory amount-based methods - * how a given memory amount parameter should be interpreted. - * - *

API of {@code MemoryUnit} is copied from {@link TimeUnit} enum. + * Memory unit conversion enum modelled after {@link TimeUnit}. + *

+ * Encapsulates the conversions between bits, bytes, longs, cache lines and larger units using + * binary prefixes (Ki/Mi/Gi). Alignment helpers round values up to the nearest boundary for the + * target unit. */ public enum MemoryUnit { diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/BitSetAlgorithm.java b/src/main/java/net/openhft/chronicle/algo/bitset/BitSetAlgorithm.java index 58253e58..55dc9142 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/BitSetAlgorithm.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/BitSetAlgorithm.java @@ -4,10 +4,10 @@ package net.openhft.chronicle.algo.bitset; /** - * The {@code BitSetAlgorithm} interface defines the contract for algorithms - * that handle operations related to bit sets. Implementations of this interface - * provide methods to calculate the size in bytes required for a given logical size in bits - * and to determine the maximum logical size that fits within the same size in bytes. + * Strategy interface describing how logical bitset sizes map to physical storage requirements. + *

+ * Algorithms can account for padding or metadata and can also report the largest logical size that + * still fits into a previously allocated storage block. */ public interface BitSetAlgorithm { diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/BitSetFrame.java b/src/main/java/net/openhft/chronicle/algo/bitset/BitSetFrame.java index 6b0d347b..01d59def 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/BitSetFrame.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/BitSetFrame.java @@ -6,9 +6,12 @@ import net.openhft.chronicle.algo.bytes.Access; /** - * The {@code BitSetFrame} interface defines a set of operations for manipulating bits within a bit set. - * It provides methods to set, clear, flip, and check the state of bits at specified indices. - * The operations are parameterized with an {@code Access} object, a handle, and an offset for flexibility. + * Low-level API for working with a bit set stored in an arbitrary memory container. + *

+ * Implementations encapsulate the bit layout and arithmetic, while callers supply an + * {@link Access} strategy, an opaque handle to the underlying storage and an offset into it. This + * separation allows the same bitset logic to be reused across on-heap arrays, {@link + * net.openhft.chronicle.bytes.BytesStore BytesStore} or raw native memory. */ public interface BitSetFrame { /** diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrame.java b/src/main/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrame.java index dd032797..87cc824f 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrame.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/ConcurrentFlatBitSetFrame.java @@ -13,8 +13,11 @@ import static net.openhft.chronicle.algo.bitset.SingleThreadedFlatBitSetFrame.*; /** - * DirectBitSet with input validations and thread-safe memory access. - * This class provides a concurrent implementation of a BitSet frame. + * Direct bit set frame that mirrors {@link SingleThreadedFlatBitSetFrame} operations but performs + * all mutations with CAS, making it safe to share across threads. + *

+ * Bounds checks mirror the single threaded implementation, while read/modify/write loops use + * volatile reads and compare-and-swap to protect against concurrent updates. */ public final class ConcurrentFlatBitSetFrame implements BitSetFrame { private final long longLength; diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithm.java b/src/main/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithm.java index 79f67837..75c12f12 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithm.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/FlatBitSetAlgorithm.java @@ -6,9 +6,9 @@ import static net.openhft.chronicle.algo.MemoryUnit.BITS; /** - * The {@code FlatBitSetAlgorithm} enum implements the {@link BitSetAlgorithm} interface - * providing concrete implementations for the methods defined in the interface. - * This enum represents a singleton instance of the algorithm used for BitSet operations. + * Basic {@link BitSetAlgorithm} backed by a flat array of 64-bit words. Byte sizing is a straight + * bits-to-bytes conversion, and the maximum logical size that fits the same byte length is the + * logical size itself because no headers or metadata are stored. */ enum FlatBitSetAlgorithm implements BitSetAlgorithm { INSTANCE; diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java b/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java index ea286057..ced02dfc 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/ReusableBitSet.java @@ -30,7 +30,7 @@ public ReusableBitSet( } /** - * Reuses the current ReusableBitSet with the specified frame, access, handle, and offset. + * Point this instance at a new backing store without allocating a fresh wrapper. * * @param frame the bit set frame to use * @param access the access interface for reading/writing bits diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java b/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java index 4cab4a26..411cd071 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/SingleThreadedFlatBitSetFrame.java @@ -11,9 +11,10 @@ import static net.openhft.chronicle.algo.MemoryUnit.LONGS; /** - * This is the SingleThreadedFlatBitSetFrame class implementing BitSetFrame. - * It provides methods for bit manipulation with input validations. - * This class is not thread-safe. + * Flat bit set frame that performs unchecked memory access via {@link Access} for a single thread. + *

+ * All bounds validation is performed up front, but operations themselves assume exclusive access to + * the underlying storage and therefore avoid CAS or volatile reads for speed. */ public final class SingleThreadedFlatBitSetFrame implements BitSetFrame { diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java b/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java new file mode 100644 index 00000000..a96b2d23 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java @@ -0,0 +1,15 @@ +/** + * High performance bit set implementations and algorithms. + * + *

Classes in this package provide single threaded and concurrent bit set + * abstractions backed by flat arrays of machine words. They are designed for + * low latency, cache friendly operations in Chronicle components that work + * with large sparse sets of indices or flags. + * + *

This package is part of the public Chronicle Algorithms API. The overall + * bit set model and key operations are intended to remain stable, although + * concrete implementations and internal layout details may change between + * releases. + */ +package net.openhft.chronicle.algo.bitset; + diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/Access.java b/src/main/java/net/openhft/chronicle/algo/bytes/Access.java index 62836a50..cde1d392 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/Access.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/Access.java @@ -9,9 +9,11 @@ import java.nio.ByteBuffer; /** - * The Access interface combines read and write access capabilities for a given type {@code T}. - * It provides various utility methods for native access, byte buffer access, and bytes store access, - * as well as methods for copying and checking equivalence between different access types. + * Combines {@link ReadAccess} and {@link WriteAccess} for a given handle type. + *

+ * Provides factory methods for common access strategies (native memory, {@link ByteBuffer}, + * {@link net.openhft.chronicle.bytes.BytesStore}) and utility helpers for copying or comparing + * regions using arbitrary access implementations. * * @param the type of the object to be accessed */ @@ -58,17 +60,8 @@ static ReadAccess checkedRandomDataInputAccess() { } /** - * Copies data from the source to the target using the provided access interfaces. - * - * @param sourceAccess the source access interface - * @param source the source handle - * @param sourceOffset the source offset - * @param targetAccess the target access interface - * @param target the target handle - * @param targetOffset the target offset - * @param len the length of data to copy - * @param the source type - * @param the target type + * Copy bytes between two addressable regions using their respective access strategies. + * Performs minimal work by moving data in 8/4/2/1 byte chunks. */ static void copy(final ReadAccess sourceAccess, final S source, @@ -99,18 +92,9 @@ static void copy(final ReadAccess sourceAccess, } /** - * Checks if the data in two different access types are equivalent. + * Compare bytes between two regions, using the provided {@link ReadAccess} strategies. * - * @param access1 the first access interface - * @param handle1 the first handle - * @param offset1 the first offset - * @param access2 the second access interface - * @param handle2 the second handle - * @param offset2 the second offset - * @param len the length of data to compare - * @param the type of the first handle - * @param the type of the second handle - * @return true if the data is equivalent, false otherwise + * @return true if all bytes in the range match */ static boolean equivalent(final ReadAccess access1, final T handle1, diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/AccessCommon.java b/src/main/java/net/openhft/chronicle/algo/bytes/AccessCommon.java index 9260b9e6..acee8a08 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/AccessCommon.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/AccessCommon.java @@ -6,7 +6,7 @@ import java.nio.ByteOrder; /** - * A functional interface that defines a common access method for determining the byte order of a given handle. + * Common contract for determining the byte order of a readable/writable handle. * * @param the type of the handle */ diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/ArrayAccessors.java b/src/main/java/net/openhft/chronicle/algo/bytes/ArrayAccessors.java index 854bfc94..e5228530 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/ArrayAccessors.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/ArrayAccessors.java @@ -6,9 +6,10 @@ import static net.openhft.chronicle.core.UnsafeMemory.MEMORY; /** - * Utility class for providing array accessors for various primitive array types. - * This class includes enums that implement {@link Accessor.Full} for different primitive types, - * facilitating access to elements of arrays. + * Unsafe-backed {@link Accessor} implementations for primitive arrays. + *

+ * Each nested enum captures the base offset for its array type and reuses {@link NativeAccess} + * to provide fast indexed access without intermediate bounds checks. */ final class ArrayAccessors { @@ -40,7 +41,7 @@ private ArrayAccessors() { } /** - * Enum providing full Accessor implementation for boolean arrays. + * Accessor for {@code boolean[]} using native memory offsets. */ enum Boolean implements Accessor.Full { INSTANCE; @@ -80,7 +81,7 @@ public long offset(boolean[] source, long index) { } /** - * Enum providing full Accessor implementation for byte arrays. + * Accessor for {@code byte[]} using native memory offsets. */ enum Byte implements Accessor.Full { INSTANCE; @@ -120,7 +121,7 @@ public long offset(byte[] source, long index) { } /** - * Enum providing full Accessor implementation for char arrays. + * Accessor for {@code char[]} using native memory offsets. */ enum Char implements Accessor.Full { INSTANCE; @@ -171,7 +172,7 @@ public long size(long size) { } /** - * Enum providing full Accessor implementation for short arrays. + * Accessor for {@code short[]} using native memory offsets. */ enum Short implements Accessor.Full { INSTANCE; diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/ByteBufferAccess.java b/src/main/java/net/openhft/chronicle/algo/bytes/ByteBufferAccess.java index a962af82..f4aee83b 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/ByteBufferAccess.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/ByteBufferAccess.java @@ -7,8 +7,9 @@ import java.nio.ByteOrder; /** - * Provides an implementation of the {@link Access} interface for {@link ByteBuffer} instances. - * This class provides methods to read and write various data types to and from a {@link ByteBuffer}. + * {@link Access} implementation that reads and writes directly against a {@link ByteBuffer}. + *

+ * Offsets are treated as absolute positions; callers should configure buffer order as required. */ final class ByteBufferAccess implements Access { diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/BytesAccessors.java b/src/main/java/net/openhft/chronicle/algo/bytes/BytesAccessors.java index dbd13605..7da4a89a 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/BytesAccessors.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/BytesAccessors.java @@ -6,7 +6,7 @@ import net.openhft.chronicle.bytes.BytesStore; /** - * Utility class for providing accessor implementations for {@link BytesStore}. + * Accessor helpers for bridging {@link BytesStore} into the Chronicle algorithms access model. */ final class BytesAccessors { @@ -15,7 +15,7 @@ private BytesAccessors() { } /** - * Generic accessor implementation for {@link BytesStore}. + * Generic accessor implementation for {@link BytesStore} instances. * * @param the type of BytesStore */ @@ -25,8 +25,6 @@ static class Generic> implements Accessor.Full /** * Returns the access implementation for the BytesStore. - * - * @return the access implementation for the BytesStore */ @SuppressWarnings("unchecked") @Override @@ -47,10 +45,6 @@ public S handle(S source) { /** * Converts the index in the source domain to an access offset. - * - * @param source the source BytesStore - * @param index the index in the source type domain - * @return the offset for access corresponding to the given index */ @Override public long offset(S source, long index) { diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccess.java b/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccess.java index ad075345..604089a6 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccess.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataInputAccess.java @@ -8,8 +8,8 @@ import java.nio.ByteOrder; /** - * Provides a default implementation for reading various primitive types and - * volatile values from a {@link RandomDataInput} handle at a specified offset. + * {@link ReadAccess} adapter for {@link RandomDataInput} so Chronicle algorithms can treat data + * sources uniformly. * * @param the type of the object being accessed, extending {@link RandomDataInput} */ diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccess.java b/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccess.java index 3446277b..580693f9 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccess.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/RandomDataOutputAccess.java @@ -8,8 +8,10 @@ import java.nio.ByteOrder; /** - * Provides a default implementation for writing various primitive types - * and volatile values to a {@link RandomDataOutput} handle at a specified offset. + * Default {@link WriteAccess} adapter for {@link RandomDataOutput} implementations. + *

+ * Bridges Chronicle Bytes write operations to the {@link WriteAccess} contract so the same bitset + * and hashing utilities can operate over {@link RandomDataOutput} without bespoke code. * * @param the type of the object being accessed, extending {@link RandomDataOutput} */ diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/ZeroAccess.java b/src/main/java/net/openhft/chronicle/algo/bytes/ZeroAccess.java index 778f59ee..26410643 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/ZeroAccess.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/ZeroAccess.java @@ -6,8 +6,10 @@ import java.nio.ByteOrder; /** - * A {@link ReadAccess} implementation that always returns zero or false for read operations. - * This is a singleton implementation, accessed via the {@code INSTANCE} enum constant. + * A {@link ReadAccess} implementation that always returns zero-equivalent values. + *

+ * Useful in tests or as a safe default when a handle is absent but callers still expect a fully + * defined {@link ReadAccess} contract. */ enum ZeroAccess implements ReadAccess { INSTANCE; diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java b/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java new file mode 100644 index 00000000..671b9ded --- /dev/null +++ b/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java @@ -0,0 +1,15 @@ +/** + * Abstractions for zero copy access to bytes like data structures. + * + *

The types in this package model readable and writable views over a range + * of backing stores, including on heap arrays, direct {@code ByteBuffer} + * instances, and Chronicle Bytes. They provide a common interface for hash + * functions and other algorithms that need uniform, low overhead access to + * raw bytes. + * + *

Callers are expected to respect the documented bounds and lifetime of + * the underlying storage. Implementations are tuned for minimal allocation + * and are suitable for use in hot paths across Chronicle libraries. + */ +package net.openhft.chronicle.algo.bytes; + diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java b/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java index ef36b768..41e7fa05 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/CityHash_1_1.java @@ -11,8 +11,11 @@ import static net.openhft.chronicle.algo.hashing.LongHashFunction.NATIVE_LITTLE_ENDIAN; /** - * Adapted from the C++ CityHash implementation from Google at - * http://code.google.com/p/cityhash/source/browse/trunk/src/city.cc. + * Endian-independent CityHash64 v1.1 implementation adapted from Google's reference. + *

+ * Exposes hash functions via {@link LongHashFunction} and consumes data through {@link ReadAccess} + * so any addressable source can be hashed without copying. On big-endian platforms values are + * byte-swapped to maintain consistent output. */ class CityHash_1_1 { @@ -34,21 +37,14 @@ private static CityHash_1_1 nativeCity() { } /** - * Applies a bitwise shift and mix operation to the given value. - * - * @param val the value to be shifted and mixed - * @return the result of the shift and mix operation + * Applies the CityHash shift/mix primitive. */ private static long shiftMix(long val) { return val ^ (val >>> 47); } /** - * Hashes two long values using a default multiplier. - * - * @param u the first value - * @param v the second value - * @return the hashed result + * Hashes two long values using the default multiplier. */ private static long hashLen16(long u, long v) { return hashLen16(u, v, K_MUL); @@ -56,11 +52,6 @@ private static long hashLen16(long u, long v) { /** * Hashes two long values using the specified multiplier. - * - * @param u the first value - * @param v the second value - * @param mul the multiplier - * @return the hashed result */ private static long hashLen16(long u, long v, long mul) { long a = shiftMix((u ^ v) * mul); @@ -68,23 +59,14 @@ private static long hashLen16(long u, long v, long mul) { } /** - * Computes the multiplier based on the length. - * - * @param len the length - * @return the multiplier + * Compute the mixing multiplier based on input length. */ private static long mul(long len) { return K2 + (len << 1); } /** - * Hashes a length of 1 to 3 bytes. - * - * @param len the length - * @param firstByte the first byte - * @param midOrLastByte the middle or last byte - * @param lastByte the last byte - * @return the hashed result + * Hash for inputs of 1-3 bytes. */ private static long hash1To3Bytes(int len, int firstByte, int midOrLastByte, int lastByte) { int y = firstByte + (midOrLastByte << 8); @@ -93,12 +75,7 @@ private static long hash1To3Bytes(int len, int firstByte, int midOrLastByte, int } /** - * Hashes a length of 4 to 7 bytes. - * - * @param len the length - * @param first4Bytes the first 4 bytes - * @param last4Bytes the last 4 bytes - * @return the hashed result + * Hash for inputs of 4-7 bytes. */ private static long hash4To7Bytes(long len, long first4Bytes, long last4Bytes) { long mul = mul(len); @@ -106,12 +83,7 @@ private static long hash4To7Bytes(long len, long first4Bytes, long last4Bytes) { } /** - * Hashes a length of 8 to 16 bytes. - * - * @param len the length - * @param first8Bytes the first 8 bytes - * @param last8Bytes the last 8 bytes - * @return the hashed result + * Hash for inputs of 8-16 bytes. */ private static long hash8To16Bytes(long len, long first8Bytes, long last8Bytes) { long mul = mul(len); @@ -122,30 +94,21 @@ private static long hash8To16Bytes(long len, long first8Bytes, long last8Bytes) } /** - * Provides an instance of LongHashFunction without a seed. - * - * @return an instance of LongHashFunction without a seed + * Seedless CityHash64 {@link LongHashFunction}. */ public static LongHashFunction asLongHashFunctionWithoutSeed() { return AsLongHashFunction.INSTANCE; } /** - * Provides an instance of LongHashFunction with a seed. - * - * @param seed the seed - * @return an instance of LongHashFunction with the seed + * Seeded CityHash64 {@link LongHashFunction}. */ public static LongHashFunction asLongHashFunctionWithSeed(long seed) { return new AsLongHashFunctionSeeded(K2, seed); } /** - * Provides an instance of LongHashFunction with two seeds. - * - * @param seed0 the first seed - * @param seed1 the second seed - * @return an instance of LongHashFunction with the seeds + * CityHash64 {@link LongHashFunction} seeded with two values. */ public static LongHashFunction asLongHashFunctionWithTwoSeeds(long seed0, long seed1) { return new AsLongHashFunctionSeeded(seed0, seed1); diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java b/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java index 43897b76..4b6a86c6 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/XxHash_r39.java @@ -9,10 +9,10 @@ import static net.openhft.chronicle.algo.hashing.LongHashFunction.NATIVE_LITTLE_ENDIAN; /** - * Adapted version of xxHash implementation from - * https://github.com/Cyan4973/xxHash/releases/tag/r39, which is fully compatible with r40 though. - * This implementation provides endian-independant hash values, - * but it's slower on big-endian platforms. + * Endian-independent xxHash64 implementation based on r39 (compatible with r40). + *

+ * Converts inputs via {@link ReadAccess} so hashing can be applied to any addressable source. + * Uses little-endian mixing internally; big-endian platforms pay a small penalty. */ class XxHash_r39 { private static final XxHash_r39 INSTANCE = new XxHash_r39(); @@ -33,10 +33,7 @@ private static XxHash_r39 nativeXx() { } /** - * Finalizes the hash value with additional mixing of bits. - * - * @param hash The initial hash value to finalize - * @return The finalized hash value + * Final mixing step used by xxHash64. */ private static long finalize(long hash) { hash ^= hash >>> 33; @@ -48,19 +45,14 @@ private static long finalize(long hash) { } /** - * Returns a LongHashFunction instance implementing xxHash without a seed. - * - * @return A LongHashFunction instance + * Returns a seedless xxHash64 {@link LongHashFunction}. */ public static LongHashFunction asLongHashFunctionWithoutSeed() { return AsLongHashFunction.SEEDLESS_INSTANCE; } /** - * Returns a LongHashFunction instance implementing xxHash with the given seed. - * - * @param seed The seed value for the hash function - * @return A LongHashFunction instance + * Returns a seeded xxHash64 {@link LongHashFunction}. */ public static LongHashFunction asLongHashFunctionWithSeed(long seed) { return new AsLongHashFunctionSeeded(seed); diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java b/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java new file mode 100644 index 00000000..7e36877a --- /dev/null +++ b/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java @@ -0,0 +1,14 @@ +/** + * Non cryptographic hash functions and helpers. + * + *

This package provides a collection of 64 bit hash implementations such + * as Murmur3, CityHash, and xxHash, together with convenience utilities for + * hashing primitive values, byte sequences, and composite keys. + * + *

The focus is on high throughput, high quality hashing suitable for use + * in off heap data structures and Chronicle components. Algorithm classes + * are part of the public API, but their internal constants and helper + * methods are considered implementation details. + */ +package net.openhft.chronicle.algo.hashing; + diff --git a/src/main/java/net/openhft/chronicle/algo/locks/AbstractReadWriteLockState.java b/src/main/java/net/openhft/chronicle/algo/locks/AbstractReadWriteLockState.java index 27d225f1..b8d0b230 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/AbstractReadWriteLockState.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/AbstractReadWriteLockState.java @@ -4,8 +4,8 @@ package net.openhft.chronicle.algo.locks; /** - * Abstract base class for managing read-write lock state. - * Implements common behavior for acquiring and releasing write locks. + * Base implementation for {@link ReadWriteLockState} that routes generic lock/unlock to write + * semantics. Concrete subclasses supply the read/write state handling. */ public abstract class AbstractReadWriteLockState implements ReadWriteLockState { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategies.java b/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategies.java index cc3fa555..07ddec96 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategies.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategies.java @@ -9,7 +9,8 @@ import java.util.concurrent.TimeUnit; /** - * Provides various acquisition strategies for locking mechanisms. + * Factory for common lock acquisition strategies including spin loops and wait-registration + * helpers. Designed to be combined with {@link LockingStrategy} implementations. */ public final class AcquisitionStrategies { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategy.java b/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategy.java index 2ea2666d..6eece8fd 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategy.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/AcquisitionStrategy.java @@ -6,7 +6,7 @@ import net.openhft.chronicle.algo.bytes.Access; /** - * Interface representing an acquisition strategy for locking mechanisms. + * Pluggable strategy for acquiring locks using a {@link LockingStrategy} and {@link Access}. * * @param the type of the locking strategy * @param the type of exception that might be thrown during the acquisition process diff --git a/src/main/java/net/openhft/chronicle/algo/locks/LockState.java b/src/main/java/net/openhft/chronicle/algo/locks/LockState.java index 3a56f83f..be51d4cf 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/LockState.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/LockState.java @@ -4,8 +4,10 @@ package net.openhft.chronicle.algo.locks; /** - * Interface representing the state of a lock. - * Provides methods for attempting to acquire the lock, releasing the lock, and resetting the lock state. + * Abstraction over a lock's backing state that can be stored and manipulated via {@link LockingStrategy}. + *

+ * Implementations hide whether the state lives in memory, on-heap structures or elsewhere; the + * strategy knows how to interpret {@link #getState()}. */ public interface LockState { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/LockingStrategy.java b/src/main/java/net/openhft/chronicle/algo/locks/LockingStrategy.java index 15d75def..1d742b30 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/LockingStrategy.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/LockingStrategy.java @@ -7,7 +7,10 @@ import net.openhft.chronicle.algo.bytes.ReadAccess; /** - * Interface representing a locking strategy for managing locks on resources. + * Strategy for managing lock state stored in arbitrary addressable resources. + *

+ * Provides low-level operations that are composed by higher-level acquisition strategies to + * implement spin locks, read/write locks and other primitives. */ public interface LockingStrategy { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockState.java b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockState.java index 8e63f8ca..e2f27dba 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockState.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockState.java @@ -4,9 +4,10 @@ package net.openhft.chronicle.algo.locks; /** - * Interface representing the state of a read-write lock. - * Provides methods for acquiring and releasing read and write locks, - * as well as upgrading and downgrading lock states. + * Abstraction over the mutable state of a read-write lock. + *

+ * Exposes operations to acquire/release read and write ownership, perform upgrades/downgrades and + * exposes the associated {@link ReadWriteLockingStrategy}. */ public interface ReadWriteLockState extends LockState { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockingStrategy.java b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockingStrategy.java index 36d94051..49074b55 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockingStrategy.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteLockingStrategy.java @@ -6,9 +6,10 @@ import net.openhft.chronicle.algo.bytes.Access; /** - * Interface representing a read-write locking strategy. - * Provides methods for acquiring and releasing read and write locks, - * as well as upgrading and downgrading lock states. + * Strategy for manipulating read/write lock state stored in an addressable resource. + *

+ * Supplies primitives for read/write acquisition, upgrades, downgrades, and introspection of the + * current state; higher-level code composes these to implement lock protocols. */ public interface ReadWriteLockingStrategy extends LockingStrategy { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockState.java b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockState.java index fbeb4498..3bcbb836 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockState.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockState.java @@ -4,11 +4,11 @@ package net.openhft.chronicle.algo.locks; /** - * Interface representing the state and operations of a read-write-update lock. + * Mutable view of a read/write/update lock's state. *

- * A read lock allows multiple concurrent reads. - * An update lock allows concurrent reads but not multiple update locks. - * A write lock is exclusive. + * Supports acquiring and releasing the intermediate update state, upgrading from read to update, + * then to write, and downgrading in the opposite direction. The associated strategy handles the + * low-level storage representation. */ public interface ReadWriteUpdateLockState extends ReadWriteLockState { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockingStrategy.java b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockingStrategy.java index a5672eca..962bb474 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockingStrategy.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateLockingStrategy.java @@ -6,11 +6,10 @@ import net.openhft.chronicle.algo.bytes.Access; /** - * Interface defining the logic of read-write-update lock state transitions. + * Strategy covering the additional "update" state layered on a read/write lock. *

- * A read lock allows multiple concurrent reads. - * An update lock allows concurrent reads but not multiple update locks. - * A write lock is exclusive. + * Update locks block other updaters but still allow readers, providing a staging point before + * upgrading to an exclusive write lock. */ public interface ReadWriteUpdateLockingStrategy extends ReadWriteLockingStrategy { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockState.java b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockState.java index 59f79935..502d927c 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockState.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockState.java @@ -4,10 +4,9 @@ package net.openhft.chronicle.algo.locks; /** - * Interface representing a read-write-update lock state with wait registration capabilities. + * Read/write/update lock state that also tracks registered waiters. *

- * This interface extends both {@link ReadWriteUpdateLockState} and {@link ReadWriteWithWaitsLockState}, - * adding the capability to upgrade an update lock to a write lock while deregistering the wait state. + * Adds an operation to upgrade from update to write while removing the wait registration. */ public interface ReadWriteUpdateWithWaitsLockState extends ReadWriteUpdateLockState, ReadWriteWithWaitsLockState { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockingStrategy.java b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockingStrategy.java index 451872a6..a61ae256 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockingStrategy.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteUpdateWithWaitsLockingStrategy.java @@ -6,10 +6,9 @@ import net.openhft.chronicle.algo.bytes.Access; /** - * Interface representing a read-write-update lock with wait registration capabilities. + * Read/write/update locking strategy that also tracks wait registrations. *

- * This interface extends both {@link ReadWriteUpdateLockingStrategy} and {@link ReadWriteWithWaitsLockingStrategy}, - * adding the capability to upgrade an update lock to a write lock while deregistering the wait state. + * Adds a helper to upgrade an update lock to a write lock while deregistering an outstanding wait. */ public interface ReadWriteUpdateWithWaitsLockingStrategy extends ReadWriteUpdateLockingStrategy, ReadWriteWithWaitsLockingStrategy { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteWithWaitsLockState.java b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteWithWaitsLockState.java index e454f93f..505da5f7 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteWithWaitsLockState.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/ReadWriteWithWaitsLockState.java @@ -4,10 +4,9 @@ package net.openhft.chronicle.algo.locks; /** - * Interface representing a read-write lock state with wait registration capabilities. + * Read/write lock state that also tracks waiting threads for coordination purposes. *

- * This interface extends {@link ReadWriteLockState}, adding methods to register and - * deregister waits, and to manage write locks with wait deregistration. + * Adds wait registration, wait-aware acquisition helpers, and a specialised strategy link. */ public interface ReadWriteWithWaitsLockState extends ReadWriteLockState { diff --git a/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperation.java b/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperation.java index c2db7dae..6a62b774 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperation.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/TryAcquireOperation.java @@ -6,7 +6,7 @@ import net.openhft.chronicle.algo.bytes.Access; /** - * Represents an operation that attempts to acquire a lock using a given locking strategy. + * Callback invoked by {@link AcquisitionStrategy} implementations to attempt lock acquisition. * * @param the type of the locking strategy */ diff --git a/src/main/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategy.java b/src/main/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategy.java index b3445039..5eb7eacb 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategy.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategy.java @@ -10,8 +10,10 @@ import static java.nio.ByteOrder.nativeOrder; /** - * Vanilla implementation of a read-write-update lock with waits. - * This class provides the locking mechanism to handle read, write, and update operations with wait strategies. + * Vanilla implementation of a read/write/update lock that also tracks waiters. + *

+ * Encodes counts, update and write ownership, and wait flags into two words and exposes CAS helpers + * so callers can embed the lock state in arbitrary addressable memory. */ public final class VanillaReadWriteUpdateWithWaitsLockingStrategy extends AbstractReadWriteLockingStrategy @@ -48,13 +50,7 @@ public static ReadWriteUpdateWithWaitsLockingStrategy instance() { } /** - * Retrieves the lock word from the given ReadAccess. - * - * @param access The ReadAccess instance - * @param t The input handle - * @param offset The offset within the input - * @param The type of the input handle - * @return The lock word read from the input + * Retrieves the volatile lock word (count + wait packed). */ private static long getLockWord(ReadAccess access, T t, long offset) { // Reads the lock word from the specified offset @@ -62,15 +58,7 @@ private static long getLockWord(ReadAccess access, T t, long offset) { } /** - * Performs a compare-and-swap operation on the lock word. - * - * @param access The Access instance - * @param t The input handle - * @param offset The offset within the input - * @param expected The expected value - * @param x The new value - * @param The type of the input handle - * @return True if the operation was successful, false otherwise + * Compare-and-swap the combined lock word. */ public static boolean casLockWord( Access access, T t, long offset, long expected, long x) { @@ -79,10 +67,7 @@ public static boolean casLockWord( } /** - * Extracts the count word from the given lock word. - * - * @param lockWord The lock word - * @return The count word + * Extracts the count word (reads/update/write) from the packed lock word. */ private static int countWord(long lockWord) { // Extracts the count word from the lock word @@ -90,10 +75,7 @@ private static int countWord(long lockWord) { } /** - * Extracts the wait word from the given lock word. - * - * @param lockWord The lock word - * @return The wait word + * Extracts the wait word from the packed lock word. */ private static int waitWord(long lockWord) { // Extracts the wait word from the lock word @@ -101,11 +83,7 @@ private static int waitWord(long lockWord) { } /** - * Constructs a lock word from the given count and wait words. - * - * @param countWord The count word - * @param waitWord The wait word - * @return The constructed lock word + * Pack count and wait words into a single long. */ public static long lockWord(int countWord, int waitWord) { // Combines the count and wait words into a single lock word @@ -114,13 +92,7 @@ public static long lockWord(int countWord, int waitWord) { } /** - * Retrieves the count word from the given Access instance. - * - * @param access The Access instance - * @param t The input handle - * @param offset The offset within the input - * @param The type of the input handle - * @return The count word read from the input + * Read the volatile count word component. */ private static int getCountWord(Access access, T t, long offset) { // Reads the count word from the specified offset diff --git a/src/main/java/net/openhft/chronicle/algo/locks/package-info.java b/src/main/java/net/openhft/chronicle/algo/locks/package-info.java new file mode 100644 index 00000000..09debbb0 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/algo/locks/package-info.java @@ -0,0 +1,16 @@ +/** + * Locking strategies and state machines for low latency code. + * + *

Classes in this package model read write and update locks together with + * the associated acquisition strategies and lock states. They are intended + * for use by Chronicle data structures that need fine grained control over + * contention behaviour without depending directly on {@code java.util.concurrent} + * locks. + * + *

The abstractions here describe lock semantics and usage patterns rather + * than specific synchronisation primitives. They are part of the public + * Chronicle Algorithms API, but callers should not rely on the internal + * representation of lock states. + */ +package net.openhft.chronicle.algo.locks; + diff --git a/src/main/java/net/openhft/chronicle/algo/package-info.java b/src/main/java/net/openhft/chronicle/algo/package-info.java new file mode 100644 index 00000000..c6c1a730 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/algo/package-info.java @@ -0,0 +1,14 @@ +/** + * Core algorithm utilities shared across Chronicle libraries. + * + *

This root package provides general purpose low level primitives such + * as {@code MemoryUnit} together with access to sub-packages that implement + * bit set operations, hashing functions, byte access abstractions, and lock + * strategies. + * + *

This package forms part of the public Chronicle Algorithms API. We aim + * to keep the exposed types stable within a major version, while allowing + * individual algorithms and internal implementations to evolve over time. + */ +package net.openhft.chronicle.algo; + From 75dfc2c179fe8d6a56b06b1c4656c8a1322f76a4 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 08:54:10 +0000 Subject: [PATCH 10/15] Add initial documentation for AGENTS, CLAUDE, GEMINI, and README files, outlining project overview, build commands, code architecture, and development conventions --- CLAUDE.md | 306 +++++++++++++++++++++++++++++++++++++++++----------- GEMINI.md | 30 ++++++ README.adoc | 215 +++++++++++++++++++++++------------- 3 files changed, 414 insertions(+), 137 deletions(-) create mode 100644 GEMINI.md diff --git a/CLAUDE.md b/CLAUDE.md index dff4e186..755b7790 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,106 +2,286 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. -## Project Overview +--- -Chronicle-Algorithms is a zero-allocation, high-performance Java library providing efficient algorithms for: -- Hashing (CityHash, MurmurHash, XxHash) -- Bit set operations -- Raw byte access to data types -- Off-heap locking mechanisms +## Repository Overview -Part of the OpenHFT Chronicle suite, this library focuses on performance-critical operations with minimal memory allocation. +Chronicle-Algorithms is a zero-allocation, high-performance Java library providing low-latency primitives for: + +* Fast non-cryptographic hashing (Murmur3, CityHash, xxHash) for data structures and indexing +* Cache-friendly bit set implementations for dense and sparse scenarios +* Unified byte accessors for on-heap arrays, direct buffers, Chronicle Bytes, and raw memory without hidden copying +* Lightweight, off-heap-capable lock strategies tuned for Chronicle primitives + +It is a foundational Chronicle library that: + +* Depends on **Chronicle-Core** and **Chronicle-Bytes** +* Is consumed by higher-level components like **Chronicle-Map** and **Chronicle-Queue** +* Is part of the wider **OpenHFT Chronicle** suite, focusing on performance-critical operations with minimal memory allocation + +--- ## Build and Test Commands ### Building + ```bash +# Full build with tests +mvn clean verify + +# Quiet mode (suppress Maven info logs) +mvn -q clean verify + +# Build without tests (faster iteration) +mvn -DskipTests clean install + +# Simple install (equivalent to full build unless customised) mvn clean install ``` ### Running Tests + ```bash # Run all tests mvn test # Run a single test class +mvn -Dtest=LongHashFunctionTest test mvn test -Dtest=BitSetTest # Run a specific test method +mvn -Dtest=LongHashFunctionTest#testSpecificMethod test mvn test -Dtest=BitSetTest#testFlip ``` ### Code Coverage -The project uses JaCoCo for code coverage with targets defined in pom.xml: -- Line coverage: 57.9% -- Branch coverage: 36.4% -## Architecture +* Code coverage is measured with **JaCoCo**, configured in `pom.xml`. +* Current targets: + + * Line coverage: **57.9%** + * Branch coverage: **36.4%** + +When adding or modifying code, aim to keep coverage at or above these thresholds, and improve them where practical. + +--- + +## Code Architecture ### Package Structure -The codebase is organized into four main functional areas under `net.openhft.chronicle.algo`: - -#### 1. Hashing (`algo.hashing`) -- **LongHashFunction**: Abstract base class for all hash function implementations. Subclasses should implement methods for single primitives, `hashVoid()`, and the core `hash(Object, ReadAccess, long, long)` method. All other methods delegate to these. -- Hash implementations: `CityHash_1_1`, `MurmurHash_3`, `XxHash_r39` -- All hash functions produce cross-platform consistent results (same output on little-endian and big-endian systems), though performance favors little-endian platforms - -#### 2. Bytes Access (`algo.bytes`) -- **Access Pattern**: The core abstraction for reading/writing raw bytes from various data sources - - `ReadAccess`: Read operations on type T - - `WriteAccess`: Write operations on type T - - `Access`: Combines both read and write capabilities - - `AccessCommon`: Base interface with common metadata operations -- **Accessor Pattern**: Converts between source types and Access handles - - `Accessor`: Maps source type S to target type T with access strategy A - - Implementations for arrays, ByteBuffer, BytesStore, CharSequence -- **Key implementations**: - - `NativeAccess`: Direct native memory access - - `ByteBufferAccess`: Access ByteBuffer contents - - `BytesAccesses`: Access Chronicle Bytes BytesStore - - Array accessors for all primitive types -- The Access/Accessor pattern enables uniform byte-level operations across heterogeneous data sources (heap arrays, direct buffers, off-heap memory) - -#### 3. Bit Sets (`algo.bitset`) -- **BitSet**: Main interface with rigid `logicalSize()` (unlike java.util.BitSet which has dynamic capacity) -- **BitSetAlgorithm**: Static utility methods operating on raw memory via Access pattern -- **BitSetFrame**: Combines BitSet interface with Access-based implementation - - `SingleThreadedFlatBitSetFrame`: Optimized for single-threaded use - - `ConcurrentFlatBitSetFrame`: Thread-safe implementation with atomic operations -- **ReusableBitSet**: Adapter for reusing BitSet instances with different underlying storage -- All operations throw IndexOutOfBoundsException for out-of-bounds access - -#### 4. Locks (`algo.locks`) -- Off-heap locking strategies for concurrent access control -- **LockingStrategy**: Base interface for lock/unlock/reset operations via Access pattern -- **Lock state interfaces**: Separate state from strategy - - `ReadWriteLockState` / `ReadWriteLockingStrategy` - - `ReadWriteUpdateLockState` / `ReadWriteUpdateLockingStrategy` (adds update locks) - - `ReadWriteUpdateWithWaitsLockState` / corresponding strategy (tracks waiting threads) -- **AcquisitionStrategy**: Defines try/lock behaviors (`TryAcquireOperation`, `TryAcquireOperations`) -- Vanilla implementations: `VanillaReadWriteUpdateWithWaitsLockingStrategy`, `VanillaReadWriteWithWaitsLockingStrategy` -- All locking is managed through the Access abstraction, enabling off-heap lock storage +The codebase is organised under `net.openhft.chronicle.algo` into four main functional areas. + +**Public API packages:** + +* `net.openhft.chronicle.algo` + Core utilities (for example, `MemoryUnit`). + +* `net.openhft.chronicle.algo.hashing` + Non-cryptographic hash functions: + + * `LongHashFunction` (abstract base for hash implementations) + * `MurmurHash_3` + * `CityHash_1_1` + * `XxHash_r39` + +* `net.openhft.chronicle.algo.bytes` + Unified byte access abstractions: + + * `Access` / `ReadAccess` / `WriteAccess` / `AccessCommon` + * Accessors for arrays, `ByteBuffer`, `BytesStore`, `CharSequence` + * Key implementations: `NativeAccess`, `ByteBufferAccess`, `BytesAccesses`, array accessors + +* `net.openhft.chronicle.algo.bitset` + Bit set implementations: + + * `BitSet` (rigid `logicalSize()` unlike `java.util.BitSet`) + * `BitSetAlgorithm` (static utilities on raw memory via Access pattern) + * `BitSetFrame`, `SingleThreadedFlatBitSetFrame`, `ConcurrentFlatBitSetFrame` + * `ReusableBitSet` for reusing instances over different storage + +* `net.openhft.chronicle.algo.locks` + Lightweight locking strategies: + + * `LockingStrategy` and lock state interfaces + * `ReadWriteLockState` / `ReadWriteLockingStrategy` + * `ReadWriteUpdateLockState` / `ReadWriteUpdateLockingStrategy` + * `ReadWriteUpdateWithWaitsLockState` / corresponding strategy + * `AcquisitionStrategy`, `TryAcquireOperation`, `TryAcquireOperations` + * Vanilla implementations such as `VanillaReadWriteUpdateWithWaitsLockingStrategy`, `VanillaReadWriteWithWaitsLockingStrategy` + +**Internal/non-public packages:** + +* `net.openhft.chronicle.algo.internal` + Implementation details; not supported for external use and may change without notice. + +* `net.openhft.chronicle.algorithms.measures` + Hash quality evaluation tools and support tooling; not part of the stable public API. ### Key Design Patterns -1. **Access/Accessor Abstraction**: Unified interface for byte-level operations on diverse data sources. Access defines operations on a handle type T, while Accessor converts sources to Access handles with offset calculations. +1. **Access / Accessor Abstraction** + + The bytes package uses a two-level abstraction: + + * `Access` / `ReadAccess` / `WriteAccess` / `AccessCommon` + Define the primitive operations to read and write bytes (and primitives) for a handle type `T`. + + * `Accessor` + Converts a source type `S` (arrays, `ByteBuffer`, `BytesStore`, `CharSequence`) into an `Access` handle `T` using strategy `A`. + + This enables uniform, zero-copy operations over heterogeneous storage (heap arrays, direct buffers, off-heap memory) while keeping algorithms storage-agnostic. + +2. **Flyweight Pattern for Bit Sets** + + * `BitSetFrame` and `ReusableBitSet` act as views over underlying storage. + * Frames overlay contiguous memory (on-heap or off-heap) and provide `set/clear/flip` operations without additional allocation. + * All operations enforce `IndexOutOfBoundsException` for invalid indices. -2. **Zero-Allocation**: Algorithms are designed to avoid object allocation in hot paths. Prefer primitive types, reuse objects (e.g., ReusableBitSet), and operate directly on raw memory. +3. **Lock State and Strategy Separation** -3. **Off-Heap Support**: All core algorithms work via the Access pattern, allowing operations on off-heap memory without GC pressure. + * Lock state (`ReadWriteLockState`, `ReadWriteUpdateLockState`, etc.) is separated from acquisition strategy (`LockingStrategy`, `AcquisitionStrategy`). + * This allows different lock behaviours (with/without waits, with update locks, etc.) to reuse the same state encoding and memory layout. -4. **Strategy Pattern**: Locking and hashing use strategy interfaces to allow algorithm selection and customization. +4. **Zero-Allocation and Off-Heap Focus** + + * Core algorithms are designed to avoid allocations in hot paths. + * Operations work via the Access pattern on both heap and off-heap memory, minimising GC pressure. + * Reusable structures (for example, `ReusableBitSet`) and primitive-based APIs are preferred. + +5. **Strategy Pattern** + + * Hashing and locking algorithms use strategy interfaces to allow algorithm selection and customisation without changing call sites. + * This is particularly important for choosing different lock implementations or hash functions in performance-sensitive code. + +--- ## Dependencies -Core Chronicle dependencies: -- `chronicle-core`: Foundation utilities -- `chronicle-bytes`: Byte buffer abstractions +This module depends on: + +* **chronicle-core** + Low-level utilities (`Jvm`, `OS`, resource management, etc.). + +* **chronicle-bytes** + Off-heap memory access and buffer management. + +* **slf4j-api** + Logging facade (if used, should be minimal in hot paths). + +* **JetBrains annotations** (`annotations`) + For nullability and other code annotations. + +Version management is driven by BOMs: + +* `chronicle-bom` (for Chronicle artefacts, e.g. `2.27ea-SNAPSHOT`) +* `third-party-bom` (for third-party libraries, e.g. `3.27ea7`) + +Test dependencies: + +* JUnit 4 and JUnit 5 (Jupiter) +* Mockito +* Guava testlib + +--- + +## Testing + +* Frameworks: **JUnit 4** and **JUnit 5** +* Naming convention: test classes end with `*Test.java`. + +Typical commands: + +```bash +# Run all tests +mvn test + +# Run a specific package's tests +mvn -Dtest="net.openhft.chronicle.algo.hashing.*Test" test + +# Run a single test class +mvn -Dtest=LongHashFunctionTest test +mvn test -Dtest=BitSetTest + +# Run a specific test method +mvn -Dtest=LongHashFunctionTest#testSpecificMethod test +mvn test -Dtest=BitSetTest#testFlip +``` + +Guidance for changes: + +* Prefer deterministic tests for hashing (distribution/avalanche) and bit sets (boundary indices, dense/sparse cases). +* Keep tests compatible with both JUnit 4 and JUnit 5 where applicable. +* Ensure new tests integrate cleanly with existing Maven Surefire configuration and JaCoCo coverage rules. + +--- + +## Documentation + +Documentation is maintained in `src/main/docs/` using AsciiDoc: + +* `architecture-overview.adoc` – High-level architecture +* `project-requirements.adoc` – Functional/non-functional requirements with Nine-Box tags +* `decision-log.adoc` – Architecture Decision Records (ADRs) +* `testing-strategy.adoc` – Testing approach +* `security-review.adoc` – Security analysis + +**Documentation standards:** + +* Format: AsciiDoc (`.adoc`) +* Language: British English +* Character set: ISO-8859-1 +* Source highlighter: `:source-highlighter: rouge` + +When updating code, keep these docs in sync, especially requirements and decision logs. + +--- + +## Code Quality + +The repository follows Chronicle ecosystem quality standards: + +* Keep **Checkstyle** and **SpotBugs** clean; justify any suppressions inline. +* Avoid allocations in hot paths; maintain zero-allocation behaviour for core algorithms. +* Maintain off-heap bounds checks in all changes involving direct or Bytes-based access. +* Prefer deterministic property-based tests for hashing and bit set operations. +* Respect existing JaCoCo coverage thresholds; if they are temporarily reduced, document and justify the trade-off. + +See `AGENTS.md` for module-specific quality guidelines and Nine-Box requirement mappings. + +--- + +## Important Notes + +1. **Non-cryptographic Hashes Only** + Murmur3, CityHash, and xxHash are designed for speed and distribution, not security. + Do **not** use them for integrity checking, authentication, or confidentiality. + +2. **Internal Packages** + Anything under `net.openhft.chronicle.algo.internal` or `net.openhft.chronicle.algorithms.measures` is **not** public API. + Do not reference these from external code; treat them as implementation details. + +3. **Off-Heap Focus and Safety** + APIs are designed for zero-allocation operation with off-heap memory. + Changes must preserve: + + * Memory safety (bounds checking at API boundaries), + * Clear ownership and lifetime semantics for underlying storage. + +4. **Stable API Surface** + Public interfaces and classes under documented API packages should remain stable within a major version. + Internal implementations may evolve freely, but public behaviour must remain consistent with requirements and ADRs. + +5. **Nine-Box Requirements** + Code and comments may reference requirement IDs such as `ALGO-FN-010`, `ALGO-NF-P-001`, etc. + When modifying behaviour: + + * Preserve or update these tags as appropriate. + * Keep `project-requirements.adoc` and `decision-log.adoc` in sync with code changes. -Test framework uses both JUnit 4 and JUnit 5 (Jupiter), plus Mockito for mocking. +--- ## License -Apache 2.0 (SPDX-License-Identifier: Apache-2.0) -Copyright 2013-2025 chronicle.software +* **License:** Apache 2.0 (SPDX-License-Identifier: Apache-2.0) +* **Copyright:** 2013–2025 chronicle.software diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 00000000..1943c4fc --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,30 @@ +# Chronicle-Algorithms + +## Project Overview + +Chronicle-Algorithms is a Java library providing zero-allocation, efficient algorithms for hashing, bit set operations, raw byte access, and lightweight off-heap-friendly locking. It is designed for high-performance, low-latency applications and is part of the OpenHFT/Chronicle ecosystem. + +The project is built with Maven and has dependencies on `chronicle-core` and `chronicle-bytes`. The public APIs are located in the `net.openhft.chronicle.algo` package and its subpackages: `.bitset`, `.bytes`, `.hashing`, and `.locks`. + +## Building and Running + +To build the project and run all tests, use the following Maven command: + +```sh +mvn -q clean verify +``` + +To build the project without running tests, you can use: + +```sh +mvn -pl Chronicle-Algorithms -am -DskipTests install +``` + +## Development Conventions + +* **Off-heap friendly:** APIs are designed to work with `Chronicle Bytes` and direct buffers, minimizing allocations. +* **Performance-focused:** The library prioritizes cache-friendly data structures and efficient algorithms. +* **Stable APIs:** Public interfaces are intended to be stable within a major version. +* **Clear Separation:** Internal packages (`net.openhft.chronicle.algo.internal`) are not meant for external use. +* **Testing:** The project uses JUnit and Mockito for testing. It also includes performance and benchmark tests using JMH. +* **Code Style:** The code follows standard Java conventions with clear Javadoc documentation. diff --git a/README.adoc b/README.adoc index 7236bab1..d36f9a29 100644 --- a/README.adoc +++ b/README.adoc @@ -2,74 +2,126 @@ :license: Apache 2.0 :toc: macro :toclevels: 3 +:lang: en-GB +:source-highlighter: rouge -image:https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms/badge.svg[link="https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms"] -image:https://javadoc.io/badge2/net.openhft/chronicle-algorithms/javadoc.svg[link="https://javadoc.io/doc/net.openhft/chronicle-algorithms"] -image:https://img.shields.io/badge/License-Apache%202.0-blue.svg[link="https://opensource.org/licenses/Apache-2.0"] +image:[https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms/badge.svg[link="https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms](https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms/badge.svg[link=%22https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-algorithms)"] +image:[https://javadoc.io/badge2/net.openhft/chronicle-algorithms/javadoc.svg[link="https://javadoc.io/doc/net.openhft/chronicle-algorithms](https://javadoc.io/badge2/net.openhft/chronicle-algorithms/javadoc.svg[link=%22https://javadoc.io/doc/net.openhft/chronicle-algorithms)"] +image:[https://img.shields.io/badge/License-Apache%202.0-blue.svg[link="https://opensource.org/licenses/Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg[link=%22https://opensource.org/licenses/Apache-2.0)"] Chronicle-Algorithms is a Java library providing zero-allocation, high-performance algorithms for hashing, bit set operations, off-heap locking, and low-level memory access. It is designed for latency-sensitive systems where garbage collection pauses are critical concerns. +Zero-allocation, efficient algorithms for hashing, bit set operations, raw byte access, and lightweight off-heap-friendly locking. + toc::[] == Features -* **Hashing**: Non-cryptographic 64-bit hash functions including CityHash, MurmurHash3, and xxHash -* **Bit Sets**: High-performance, rigid-capacity bit sets with both single-threaded and concurrent implementations -* **Bytes Access**: Unified abstractions for accessing raw bytes from diverse sources (arrays, ByteBuffers, Strings, off-heap memory) with zero allocation -* **Locking**: Off-heap read-write-update locking strategies for concurrent access control +* **Hashing** +** Non-cryptographic 64-bit hash functions including CityHash 1.1, MurmurHash3, and xxHash r39. +** Optimised for performance and zero allocation, with consistent results across big-endian and little-endian platforms. + +* **Bit Sets** +** High-performance, rigid-capacity bit sets with both single-threaded and concurrent implementations. +** Cache-friendly, flat representations suitable for dense and sparse scenarios. +** Operate over raw memory or byte stores with strict bounds checking. + +* **Bytes Access** +** Unified abstractions for accessing raw bytes from diverse sources (arrays, `ByteBuffer`s, `String`s, off-heap memory, Chronicle Bytes) with zero allocation. +** Unified accessors for on-heap arrays, direct buffers, and Chronicle Bytes without hidden copying. + +* **Locking** +** Off-heap read-write-update locking strategies for concurrent access control. +** Lightweight locks tuned for Chronicle primitives rather than `java.util.concurrent` abstractions. + +* **Hash-Quality Evaluation Helpers** +** Hash-quality evaluation tools in `net.openhft.chronicle.algorithms.measures` for benchmarking and analysis (support tooling, not public API). + +== Package Layout + +* **Public APIs** +`net.openhft.chronicle.algo` and subpackages: + +* `.bitset` +* `.bytes` +* `.hashing` +* `.locks` + +* **Internal-only code** +`net.openhft.chronicle.algo.internal` and hash-quality tooling in `net.openhft.chronicle.algorithms.measures` are not supported for external use and may change without notice. + +== Documentation + +Documentation is maintained under `src/main/docs/`: + +* Architecture overview: link:src/main/docs/architecture-overview.adoc[] +* Requirements: link:src/main/docs/project-requirements.adoc[] +* Decision log: link:src/main/docs/decision-log.adoc[] +* Testing strategy: link:src/main/docs/testing-strategy.adoc[] +* Security review: link:src/main/docs/security-review.adoc[] + +Additional online resources: + +* Javadoc: [https://javadoc.io/doc/net.openhft/chronicle-algorithms](https://javadoc.io/doc/net.openhft/chronicle-algorithms) +* Maven Central metadata: [https://search.maven.org/artifact/net.openhft/chronicle-algorithms](https://search.maven.org/artifact/net.openhft/chronicle-algorithms) == Hashing -The library provides a unified API for several non-cryptographic 64-bit hash functions through the `LongHashFunction` class. These implementations are optimized for performance, produce consistent results across platforms (big-endian and little-endian), and generate zero garbage. +The library provides a unified API for several non-cryptographic 64-bit hash functions through the `LongHashFunction` class. These implementations are optimised for performance, produce consistent results across platforms (big-endian and little-endian), and generate zero garbage. === Supported Algorithms -* **CityHash 1.1**: Based on Google's CityHash algorithm -* **MurmurHash3**: Based on the SMHasher suite implementation -* **xxHash r39**: Based on Cyan4973's xxHash (r39 revision) + +* **CityHash 1.1** – Based on Google's CityHash algorithm. +* **MurmurHash3** – Based on the SMHasher suite implementation. +* **xxHash r39** – Based on Cyan4973's xxHash (r39 revision). === Usage Examples -[source,java,opts=novalidate] ----- +## [source,java,opts=novalidate] + import net.openhft.chronicle.algo.hashing.LongHashFunction; public class HashingExample { - public static void main(String[] args) { - String input = "Hello World"; +public static void main(String[] args) { +String input = "Hello World"; - // Get an instance of the hash function - LongHashFunction xxHash = LongHashFunction.xx_r39(); +``` + // Get an instance of the hash function + LongHashFunction xxHash = LongHashFunction.xx_r39(); - // Hash a String - long hash = xxHash.hashChars(input); + // Hash a String + long hash = xxHash.hashChars(input); - // Hash a primitive - long longHash = xxHash.hashLong(123456789L); + // Hash a primitive + long longHash = xxHash.hashLong(123456789L); - // Hash a byte array - byte[] data = new byte[] {1, 2, 3, 4, 5}; - long bytesHash = LongHashFunction.city_1_1().hashBytes(data); + // Hash a byte array + byte[] data = new byte[] {1, 2, 3, 4, 5}; + long bytesHash = LongHashFunction.city_1_1().hashBytes(data); - // Hash off-heap memory (unsafe access) - // long address = ...; // unsafe memory address - // long length = 64; - // long memoryHash = LongHashFunction.murmur_3().hashMemory(address, length); - } + // Hash off-heap memory (unsafe access) + // long address = ...; // unsafe memory address + // long length = 64; + // long memoryHash = LongHashFunction.murmur_3().hashMemory(address, length); } ----- +``` + +## } == Bit Sets The `net.openhft.chronicle.algo.bitset` package provides `BitSet` implementations that operate over raw memory or byte stores. Unlike `java.util.BitSet`, which has dynamic capacity, Chronicle bit sets have a rigid logical size and throw `IndexOutOfBoundsException` for out-of-bounds access. === Implementations -* **SingleThreadedFlatBitSetFrame**: Not thread-safe, optimized for single-threaded access. -* **ConcurrentFlatBitSetFrame**: Thread-safe implementation using CAS (Compare-And-Swap) operations for concurrent access. + +* **SingleThreadedFlatBitSetFrame** – Not thread-safe, optimised for single-threaded access. +* **ConcurrentFlatBitSetFrame** – Thread-safe implementation using CAS (compare-and-swap) operations for concurrent access. +* **ReusableBitSet** – Adapter for reusing `BitSet` instances with different underlying storage. === Usage Examples -[source,java,opts=novalidate] ----- +## [source,java,opts=novalidate] + import net.openhft.chronicle.algo.bitset.BitSetFrame; import net.openhft.chronicle.algo.bitset.SingleThreadedFlatBitSetFrame; import net.openhft.chronicle.algo.bitset.ReusableBitSet; @@ -90,94 +142,109 @@ bitSet.set(1); bitSet.set(3); boolean isSet = bitSet.get(1); // true long nextSet = bitSet.nextSetBit(0); // 1 ----- +----------------------------------------- == Bytes Access The `net.openhft.chronicle.algo.bytes` package provides a unified `Access` and `Accessor` abstraction to read and write primitives from various underlying sources without creating objects. This enables zero-allocation operations across heterogeneous data types. === Supported Sources -* **Native Memory**: Direct access via `Unsafe` -* **ByteBuffer**: Both heap and direct ByteBuffers -* **Arrays**: All primitive array types (`byte[]`, `long[]`, `int[]`, etc.) -* **CharSequence/String**: Efficient access to String internals (supports compact strings in Java 9+) -* **BytesStore**: Chronicle Bytes abstractions -[source,java] ----- +* **Native memory** – Direct access via `Unsafe`. +* **ByteBuffer** – Both heap and direct `ByteBuffer`s. +* **Arrays** – All primitive array types (`byte[]`, `long[]`, `int[]`, etc.). +* **CharSequence/String** – Efficient access to `String` internals (including compact strings in Java 9+). +* **BytesStore** – Chronicle Bytes abstractions. + +## [source,java,opts=novalidate] + import net.openhft.chronicle.algo.bytes.Access; import net.openhft.chronicle.algo.bytes.NativeAccess; // Native access singleton Access unsafeAccess = NativeAccess.instance(); long value = unsafeAccess.readLong(object, offset); ----- +--------------------------------------------------- == Locking The `net.openhft.chronicle.algo.locks` package provides logic for read-write-update locks that can be stored off-heap or in shared memory. -* **Read Lock**: Multiple readers allowed. -* **Update Lock**: Only one update lock allowed, but allows concurrent readers. Can upgrade to Write Lock. -* **Write Lock**: Exclusive access. +* **Read lock** – Multiple readers allowed. +* **Update lock** – Only one update lock allowed, but allows concurrent readers. Can upgrade to write lock. +* **Write lock** – Exclusive access. === Locking Strategy + The primary implementation is `VanillaReadWriteUpdateWithWaitsLockingStrategy`, which supports: -* Lock upgrading (Read -> Update -> Write) -* Lock downgrading -* Waiting strategies -== Maven Dependency +* Lock upgrading (Read -> Update -> Write). +* Lock downgrading. +* Waiting strategies. -To include Chronicle-Algorithms in your project, add the following dependency to your `pom.xml`: +All locking is implemented through the `Access` abstraction, enabling the lock state to reside in off-heap or shared memory regions. -[source,xml] ----- - - net.openhft - chronicle-algorithms - 2.27ea1 - ----- +== Build and Test -NOTE: Check link:https://search.maven.org/artifact/net.openhft/chronicle-algorithms[Maven Central] for the latest available version. +Quick commands: -== Building from Source +* Full build and tests: `mvn -q clean verify` +* Standard build and install: `mvn clean install` +* Module-only build (skip tests): `mvn -pl Chronicle-Algorithms -am -DskipTests install` +* Run all tests: `mvn test` +* Run specific test: `mvn test -Dtest=BitSetTest` -To build the project locally: +=== Building from Source + +## [source,bash] -[source,bash] ----- # Clone the repository -git clone https://github.com/OpenHFT/Chronicle-Algorithms.git + +git clone [https://github.com/OpenHFT/Chronicle-Algorithms.git](https://github.com/OpenHFT/Chronicle-Algorithms.git) cd Chronicle-Algorithms # Build and run tests + mvn clean install # Run specific test -mvn test -Dtest=BitSetTest + +## mvn test -Dtest=BitSetTest + +== Maven Dependency + +To include Chronicle-Algorithms in your project, add the following dependency to your `pom.xml`: + +## [source,xml] + + + net.openhft + chronicle-algorithms + 2.27ea1 + ---- +NOTE: Check link:[https://search.maven.org/artifact/net.openhft/chronicle-algorithms[Maven](https://search.maven.org/artifact/net.openhft/chronicle-algorithms[Maven) Central] for the latest available version. + == Support For questions, issues, or feature requests: -* GitHub Issues: https://github.com/OpenHFT/Chronicle-Algorithms/issues -* Documentation: https://javadoc.io/doc/net.openhft/chronicle-algorithms -* Chronicle Software: https://chronicle.software +* GitHub Issues: [https://github.com/OpenHFT/Chronicle-Algorithms/issues](https://github.com/OpenHFT/Chronicle-Algorithms/issues) +* Documentation: [https://javadoc.io/doc/net.openhft/chronicle-algorithms](https://javadoc.io/doc/net.openhft/chronicle-algorithms) +* Chronicle Software: [https://chronicle.software](https://chronicle.software) == Related Projects Part of the OpenHFT Chronicle suite: -* link:https://github.com/OpenHFT/Chronicle-Core[Chronicle-Core] - Low-level utilities and memory management -* link:https://github.com/OpenHFT/Chronicle-Bytes[Chronicle-Bytes] - Zero-copy bytes abstractions -* link:https://github.com/OpenHFT/Chronicle-Queue[Chronicle-Queue] - Persisted low-latency messaging -* link:https://github.com/OpenHFT/Chronicle-Map[Chronicle-Map] - Off-heap key-value store +* link:[https://github.com/OpenHFT/Chronicle-Core[Chronicle-Core](https://github.com/OpenHFT/Chronicle-Core[Chronicle-Core)] – Low-level utilities and memory management. +* link:[https://github.com/OpenHFT/Chronicle-Bytes[Chronicle-Bytes](https://github.com/OpenHFT/Chronicle-Bytes[Chronicle-Bytes)] – Zero-copy bytes abstractions. +* link:[https://github.com/OpenHFT/Chronicle-Queue[Chronicle-Queue](https://github.com/OpenHFT/Chronicle-Queue[Chronicle-Queue)] – Persisted low-latency messaging. +* link:[https://github.com/OpenHFT/Chronicle-Map[Chronicle-Map](https://github.com/OpenHFT/Chronicle-Map[Chronicle-Map)] – Off-heap key-value store. == License Copyright 2013-2025 chronicle.software -Licensed under the Apache License, Version 2.0. See the link:LICENSE[LICENSE] file for details. +Licensed under the Apache License, Version 2.0. See the link:LICENSE file for details. From b59e95ff608934748180569704f0e950f1862aae Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 10:20:36 +0000 Subject: [PATCH 11/15] Refactor MemoryUnit and HashTestSupport classes; add package-info documentation for assertion utilities and benchmarks --- src/main/java/net/openhft/chronicle/algo/MemoryUnit.java | 1 - .../java/net/openhft/chronicle/algo/hashing/HashTestSupport.java | 1 - .../VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java | 1 - 3 files changed, 3 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java index a08f1225..717f91a2 100644 --- a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java +++ b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java @@ -1,7 +1,6 @@ /* * Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0 */ - /* * Based on java.util.concurrent.TimeUnit, which is * Written by Doug Lea with assistance from members of JCP JSR-166 diff --git a/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java b/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java index 60831a8d..c9f53881 100644 --- a/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java +++ b/src/test/java/net/openhft/chronicle/algo/hashing/HashTestSupport.java @@ -227,5 +227,4 @@ private static long[] toLongArray(ByteBuffer buffer, int len) { buffer.duplicate().order(nativeOrder()).asLongBuffer().get(longs); return longs; } - } diff --git a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java index b0ee7177..4eb9e126 100644 --- a/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java +++ b/src/test/java/net/openhft/chronicle/algo/locks/VanillaReadWriteUpdateWithWaitsLockingStrategyTest.java @@ -223,5 +223,4 @@ void testSizeInBytes() { int expectedSize = 8; assertEquals(expectedSize, strategy.sizeInBytes()); } - } From acf4dd7e7cd9a3c47cd67d6176c27a2c7465fb9d Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 10:53:48 +0000 Subject: [PATCH 12/15] Remove unnecessary blank lines in various classes for improved code readability --- .../net/openhft/chronicle/algorithms/measures/package-info.java | 1 - .../java/net/openhft/chronicle/algo/bitset/package-info.java | 1 - src/main/java/net/openhft/chronicle/algo/bytes/package-info.java | 1 - .../java/net/openhft/chronicle/algo/hashing/package-info.java | 1 - src/main/java/net/openhft/chronicle/algo/locks/package-info.java | 1 - src/main/java/net/openhft/chronicle/algo/package-info.java | 1 - 6 files changed, 6 deletions(-) diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java index 129db537..910c790f 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java @@ -13,4 +13,3 @@ * {@code net.openhft.chronicle.algo.bytes} instead. */ package net.openhft.chronicle.algorithms.measures; - diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java b/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java index a96b2d23..79029183 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java @@ -12,4 +12,3 @@ * releases. */ package net.openhft.chronicle.algo.bitset; - diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java b/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java index 671b9ded..29d930d5 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java @@ -12,4 +12,3 @@ * and are suitable for use in hot paths across Chronicle libraries. */ package net.openhft.chronicle.algo.bytes; - diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java b/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java index 7e36877a..7eb85fe5 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java @@ -11,4 +11,3 @@ * methods are considered implementation details. */ package net.openhft.chronicle.algo.hashing; - diff --git a/src/main/java/net/openhft/chronicle/algo/locks/package-info.java b/src/main/java/net/openhft/chronicle/algo/locks/package-info.java index 09debbb0..0481e88c 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/package-info.java @@ -13,4 +13,3 @@ * representation of lock states. */ package net.openhft.chronicle.algo.locks; - diff --git a/src/main/java/net/openhft/chronicle/algo/package-info.java b/src/main/java/net/openhft/chronicle/algo/package-info.java index c6c1a730..e879fd14 100644 --- a/src/main/java/net/openhft/chronicle/algo/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/package-info.java @@ -11,4 +11,3 @@ * individual algorithms and internal implementations to evolve over time. */ package net.openhft.chronicle.algo; - From d0df9ce76ad8f8217e8b48176372da83bdd49d11 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 24 Nov 2025 14:29:23 +0000 Subject: [PATCH 13/15] Remove commented-out import statement in ChronicleStampedLockTest for cleaner code --- .../openhft/chronicle/map/locks/ChronicleStampedLockTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/net/openhft/chronicle/map/locks/ChronicleStampedLockTest.java b/src/test/java/net/openhft/chronicle/map/locks/ChronicleStampedLockTest.java index 764b673b..30a2c11b 100644 --- a/src/test/java/net/openhft/chronicle/map/locks/ChronicleStampedLockTest.java +++ b/src/test/java/net/openhft/chronicle/map/locks/ChronicleStampedLockTest.java @@ -6,8 +6,6 @@ import org.junit.Assert; import org.junit.Test; -//import static org.junit.jupiter.api.Assertions.*; - public class ChronicleStampedLockTest { @Test From 7ec23595c2083edada7f9d93c612506e20cd37ee Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Wed, 6 May 2026 16:03:57 +0100 Subject: [PATCH 14/15] refactor: simplify alignment methods by removing unnecessary ise calls --- .../openhft/chronicle/algo/MemoryUnit.java | 78 ++++++++----------- 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java index 2a35309f..fea3cf77 100644 --- a/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java +++ b/src/main/java/net/openhft/chronicle/algo/MemoryUnit.java @@ -115,7 +115,7 @@ long alignToGigabytes(long a) { @Override public long align(long a, MemoryUnit u) { - return ise(u, this); + return a; } }, @@ -170,7 +170,7 @@ public long convert(long a, MemoryUnit u) { @Override long alignToBytes(long a) { - return ise(this, BYTES); + return a; } @Override @@ -261,12 +261,12 @@ public long convert(long a, MemoryUnit u) { @Override long alignToBytes(long a) { - return ise(this, BYTES); + return a; } @Override long alignToLongs(long a) { - return ise(this, LONGS); + return a; } @Override @@ -351,17 +351,17 @@ public long convert(long a, MemoryUnit u) { @Override long alignToBytes(long a) { - return ise(this, BYTES); + return a; } @Override long alignToLongs(long a) { - return ise(this, LONGS); + return a; } @Override long alignToCacheLines(long a) { - return ise(this, CACHE_LINES); + return a; } @Override @@ -441,22 +441,22 @@ public long convert(long a, MemoryUnit u) { @Override long alignToBytes(long a) { - return ise(this, BYTES); + return a; } @Override long alignToLongs(long a) { - return ise(this, LONGS); + return a; } @Override long alignToCacheLines(long a) { - return ise(this, CACHE_LINES); + return a; } @Override long alignToKilobytes(long a) { - return ise(this, KILOBYTES); + return a; } @Override @@ -531,27 +531,27 @@ public long convert(long a, MemoryUnit u) { @Override long alignToBytes(long a) { - return ise(this, BYTES); + return a; } @Override long alignToLongs(long a) { - return ise(this, LONGS); + return a; } @Override long alignToCacheLines(long a) { - return ise(this, CACHE_LINES); + return a; } @Override long alignToKilobytes(long a) { - return ise(this, KILOBYTES); + return a; } @Override long alignToPages(long a) { - return ise(this, PAGES); + return a; } @Override @@ -621,32 +621,32 @@ public long convert(long a, MemoryUnit u) { @Override long alignToBytes(long a) { - return ise(this, BYTES); + return a; } @Override long alignToLongs(long a) { - return ise(this, LONGS); + return a; } @Override long alignToCacheLines(long a) { - return ise(this, CACHE_LINES); + return a; } @Override long alignToKilobytes(long a) { - return ise(this, KILOBYTES); + return a; } @Override long alignToPages(long a) { - return ise(this, PAGES); + return a; } @Override long alignToMegabytes(long a) { - return ise(this, MEGABYTES); + return a; } @Override @@ -711,37 +711,37 @@ public long convert(long a, MemoryUnit u) { @Override long alignToBytes(long a) { - return ise(this, BYTES); + return a; } @Override long alignToLongs(long a) { - return ise(this, LONGS); + return a; } @Override long alignToCacheLines(long a) { - return ise(this, CACHE_LINES); + return a; } @Override long alignToKilobytes(long a) { - return ise(this, KILOBYTES); + return a; } @Override long alignToPages(long a) { - return ise(this, PAGES); + return a; } @Override long alignToMegabytes(long a) { - return ise(this, MEGABYTES); + return a; } @Override long alignToGigabytes(long a) { - return ise(this, GIGABYTES); + return a; } @Override @@ -787,23 +787,11 @@ static long y(long amount, long align) { return maxAlignedLong; } } else { - // amount is negative - long filled = amount - align + 1L; - if (filled < 0L) { - return filled & mask; - - } else { - long minAlignedLong = Long.MIN_VALUE & mask; - if (amount >= minAlignedLong) - return minAlignedLong; - } + return amount & mask; } throw new IllegalArgumentException("Couldn't align " + amount + " by " + align); } - static long ise(MemoryUnit unitToAlign, MemoryUnit alignmentUnit) { - throw new IllegalStateException("Couldn't align " + unitToAlign + " by " + alignmentUnit); - } // To maintain full signature compatibility with 1.5, and to improve the // clarity of the generated javadoc (see 6287639: Abstract methods in // enum classes should not be listed as abstract), method convert @@ -839,8 +827,7 @@ public long convert(long sourceAmount, MemoryUnit sourceUnit) { * @param amountToAlign the memory amount in the given {@code unit} * @param unit the unit of the {@code amountToAlign} argument * @return the aligned amount, still in the given unit - * @throws IllegalArgumentException if the given {@code unit} is finer than this unit, - * or if the aligned value overflows {@code long} bounds + * @throws IllegalArgumentException if the aligned value overflows {@code long} bounds */ public long align(long amountToAlign, MemoryUnit unit) { throw new AbstractMethodError(); @@ -852,8 +839,7 @@ public long align(long amountToAlign, MemoryUnit unit) { * @param sourceAmount the memory amount in the given {@code sourceUnit} * @param sourceUnit the unit of the {@code sourceAmount} argument * @return the saturated converted amount in this unit - * @throws IllegalArgumentException if the given {@code sourceUnit} is finer than this unit, - * or if the aligned value overflows {@code long} bounds + * @throws IllegalArgumentException if the aligned value overflows {@code long} bounds */ public long alignAndConvert(long sourceAmount, MemoryUnit sourceUnit) { return convert(align(sourceAmount, sourceUnit), sourceUnit); From f3abbab316f9cf2918bd3fd450b15834a02c4cd1 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Wed, 6 May 2026 16:04:04 +0100 Subject: [PATCH 15/15] docs: add copyright notice and SPDX license to package-info.java files --- .../openhft/chronicle/algorithms/measures/package-info.java | 3 +++ .../java/net/openhft/chronicle/algo/bitset/package-info.java | 3 +++ .../java/net/openhft/chronicle/algo/bytes/package-info.java | 3 +++ .../java/net/openhft/chronicle/algo/hashing/package-info.java | 3 +++ .../java/net/openhft/chronicle/algo/locks/package-info.java | 3 +++ src/main/java/net/openhft/chronicle/algo/package-info.java | 3 +++ 6 files changed, 18 insertions(+) diff --git a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java index 910c790f..0f6f9179 100644 --- a/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java +++ b/measures/src/main/java/net/openhft/chronicle/algorithms/measures/package-info.java @@ -1,3 +1,6 @@ +/* + * Copyright 2013-2026 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ /** * Hash function quality measures and related tooling. * diff --git a/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java b/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java index 79029183..45c5f202 100644 --- a/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/bitset/package-info.java @@ -1,3 +1,6 @@ +/* + * Copyright 2013-2026 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ /** * High performance bit set implementations and algorithms. * diff --git a/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java b/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java index 29d930d5..6b4ad026 100644 --- a/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/bytes/package-info.java @@ -1,3 +1,6 @@ +/* + * Copyright 2013-2026 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ /** * Abstractions for zero copy access to bytes like data structures. * diff --git a/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java b/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java index 7eb85fe5..a92a2381 100644 --- a/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/hashing/package-info.java @@ -1,3 +1,6 @@ +/* + * Copyright 2013-2026 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ /** * Non cryptographic hash functions and helpers. * diff --git a/src/main/java/net/openhft/chronicle/algo/locks/package-info.java b/src/main/java/net/openhft/chronicle/algo/locks/package-info.java index 0481e88c..c0df6f82 100644 --- a/src/main/java/net/openhft/chronicle/algo/locks/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/locks/package-info.java @@ -1,3 +1,6 @@ +/* + * Copyright 2013-2026 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ /** * Locking strategies and state machines for low latency code. * diff --git a/src/main/java/net/openhft/chronicle/algo/package-info.java b/src/main/java/net/openhft/chronicle/algo/package-info.java index e879fd14..f604add3 100644 --- a/src/main/java/net/openhft/chronicle/algo/package-info.java +++ b/src/main/java/net/openhft/chronicle/algo/package-info.java @@ -1,3 +1,6 @@ +/* + * Copyright 2013-2026 chronicle.software; SPDX-License-Identifier: Apache-2.0 + */ /** * Core algorithm utilities shared across Chronicle libraries. *