Skip to content

Commit ea05ede

Browse files
committed
fix gearhash test
1 parent 13c607a commit ea05ede

File tree

3 files changed

+81
-89
lines changed

3 files changed

+81
-89
lines changed

packages/gearhash-wasm/assembly/next-match.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,9 @@ export class MatchResult {
1212
export function nextMatch(buf: Uint8Array, mask: u64, hash: u64 = 0): MatchResult {
1313
for (let i = 0; i < buf.length; i++) {
1414
const b = buf[i];
15-
// Use proper unsigned operations to match Rust's wrapping_add behavior
16-
hash = ((hash << 1) as u64) + (DEFAULT_TABLE[b] as u64);
17-
18-
// console.log(
19-
// "hash " +
20-
// hash.toString(16) +
21-
// " " +
22-
// (hash << 1).toString(16) +
23-
// " " +
24-
// b.toString(16) +
25-
// " " +
26-
// (DEFAULT_TABLE[b] as u64).toString(16)
27-
// );
28-
// console.log("mask " + mask.toString(16));
29-
// console.log("hash & mask " + (hash & mask).toString(16));
15+
hash = (hash << 1) + DEFAULT_TABLE[b];
3016

3117
if ((hash & mask) == 0) {
32-
// console.log("match found at position " + (i + 1).toString());
3318
return { position: i + 1, hash };
3419
}
3520
}

packages/gearhash-wasm/tests/index.js

Lines changed: 68 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,23 @@
11
import { nextMatch, nextMatches } from "../build/debug.js";
22

3-
// Simple deterministic RNG for reproducible results (32-bit version)
3+
// Simple deterministic RNG for reproducible results (24-bit version)
44
class SimpleRng {
55
constructor(seed) {
6-
this.state = seed;
6+
this.state = seed & 0xffffff; // Keep only 24 bits
77
}
88

9-
nextU32() {
10-
// Simple 32-bit xorshift algorithm (same as Rust version)
11-
this.state ^= this.state << 13;
12-
this.state ^= this.state >> 17;
13-
this.state ^= this.state << 5;
9+
nextU24() {
10+
// Simple 24-bit linear congruential generator
11+
// Using 24-bit arithmetic to avoid overflow
12+
this.state = (this.state * 1111 + 12345) & 0xffffff;
1413
return this.state;
1514
}
1615

17-
nextU64() {
18-
// Generate two 32-bit values and combine them
19-
const low = this.nextU32();
20-
const high = this.nextU32();
21-
return (BigInt(high) << 32n) | BigInt(low);
22-
}
23-
2416
fillBytes(dest) {
25-
for (let i = 0; i < dest.length; i += 8) {
26-
const value = this.nextU64();
27-
for (let j = 0; j < 8 && i + j < dest.length; j++) {
28-
dest[i + j] = Number((value >> BigInt(j * 8)) & 0xffn);
17+
for (let i = 0; i < dest.length; i += 3) {
18+
const value = this.nextU24();
19+
for (let j = 0; j < 3 && i + j < dest.length; j++) {
20+
dest[i + j] = (value >> (j * 8)) & 0xff;
2921
}
3022
}
3123
}
@@ -61,7 +53,6 @@ function testGearhash() {
6153
const matches = [...result.matches, { position: result.remaining, hash: result.hash }];
6254

6355
for (const match of matches) {
64-
offset += match.position;
6556
totalProcessed += match.position;
6657
chunkCount += 1;
6758
hash = match.hash;
@@ -71,6 +62,7 @@ function testGearhash() {
7162
.toString()
7263
.padStart(4)} | 0x${match.hash.toString(16).padStart(16, "0")}`
7364
);
65+
offset += match.position;
7466
}
7567

7668
console.log("\nSummary:");
@@ -128,43 +120,53 @@ function parseExpectedResults(resultData) {
128120
return results;
129121
}
130122

131-
const resultData = `
132-
1 | 0 | 5919 | 0x17c402cb182c5718
133-
2 | 5919 | 265 | 0xe739063654888081
134-
3 | 6184 | 4855 | 0x38a82261e80810f9
135-
4 | 11039 | 1029 | 0x803f24c9ac20ddd5
136-
5 | 12068 | 583 | 0xb4b724e26824ace3
137-
6 | 12651 | 358 | 0x11bd22180c0c5ac5
138-
7 | 13009 | 3078 | 0x810a04be24846ffc
139-
8 | 16087 | 1207 | 0x5f940641d088dada
140-
9 | 17294 | 251 | 0xf09502d5f4acfb4e
141-
10 | 17545 | 3053 | 0xf0b120d014ace72d
142-
11 | 20598 | 9120 | 0xa458064aa82403e5
143-
12 | 29718 | 3288 | 0x9ccf04ecc000996b
144-
13 | 33006 | 590 | 0xd4ba00dd9408b6b5
145-
14 | 33596 | 1401 | 0xd42a2000a4a46d11
146-
15 | 34997 | 2573 | 0xc914022f9c28e722
147-
16 | 37570 | 1300 | 0xd63b0401a484c0bc
148-
17 | 38870 | 98 | 0x996f0499402c1e96
149-
18 | 38968 | 2802 | 0xf43406dfb42c9324
150-
19 | 41770 | 3237 | 0x1bd026252c0ccbe3
151-
20 | 45007 | 7368 | 0x7da400e8e0aca934
152-
21 | 52375 | 439 | 0xcd9b208f38201fa7
153-
22 | 52814 | 1477 | 0x9497226484a0a015
154-
23 | 54291 | 7158 | 0x5a3100fa9888dfe5
155-
24 | 61449 | 2168 | 0x21ed20bbf008a4ef
156-
25 | 63617 | 2475 | 0x7b0522392480392d
157-
26 | 66092 | 26 | 0xdfe6048a9c0c125f
158-
27 | 66118 | 7548 | 0xf8a72278802c1523
159-
28 | 73666 | 7826 | 0x5997242ba00cb3fd
160-
29 | 81492 | 215 | 0x489e26bd7c08ec4c
161-
30 | 81707 | 760 | 0x84d526f1542066b2
162-
31 | 82467 | 1929 | 0x085d02a31024d324
163-
32 | 84396 | 3947 | 0x8cc4240eb8a8b8e3
164-
33 | 88343 | 1511 | 0x98b1204ccc001231
165-
34 | 89854 | 2895 | 0x35402430a8a8d1f1
166-
35 | 92749 | 7025 | 0x52bd0269e8084b97
167-
36 | 99774 | 226 | 0xd86ff8f143fe10b4 `;
123+
const resultData = `Chunk | Offset | Size | Hash
124+
------|--------|------|------------------
125+
1 | 0 | 3598 | 0x033220f080ac5f77
126+
2 | 3598 | 3995 | 0xd06b22f324ac5f28
127+
3 | 7593 | 4708 | 0xa3a324f81808429c
128+
4 | 12301 | 484 | 0x12a5006aa4a4425b
129+
5 | 12785 | 1484 | 0x0b240413a4a4d5a2
130+
6 | 14269 | 563 | 0xc646022fbc848bc6
131+
7 | 14832 | 6663 | 0x7c7a2296e4a4c325
132+
8 | 21495 | 1220 | 0xbe1f2468f0841b68
133+
9 | 22715 | 1175 | 0xf87e2299e00c57d9
134+
10 | 23890 | 779 | 0x79ca2634d00cd6b9
135+
11 | 24669 | 2069 | 0xcb7a063594081a74
136+
12 | 26738 | 2623 | 0xdccc26b6c0acb733
137+
13 | 29361 | 596 | 0x4fb6201a1c20143e
138+
14 | 29957 | 622 | 0x81e726272020706f
139+
15 | 30579 | 3834 | 0x630622fca084a60a
140+
16 | 34413 | 2379 | 0x177b2240080810b1
141+
17 | 36792 | 3527 | 0x663b261bbc2451ed
142+
18 | 40319 | 1665 | 0xf94f06db94003e2f
143+
19 | 41984 | 1240 | 0xc5ca208c0c24cefc
144+
20 | 43224 | 1274 | 0x8139244f740cba39
145+
21 | 44498 | 3680 | 0x4440044520045a9d
146+
22 | 48178 | 1487 | 0xe00f2049a0a43a58
147+
23 | 49665 | 4293 | 0x366a26940408279d
148+
24 | 53958 | 1184 | 0x3a582683902cb3fe
149+
25 | 55142 | 383 | 0x002d0499e080702e
150+
26 | 55525 | 1206 | 0x34ba041aa4084fbd
151+
27 | 56731 | 506 | 0x0c53045c00a0a228
152+
28 | 57237 | 8019 | 0xf85b202d9c0813a5
153+
29 | 65256 | 1070 | 0x1c862295ac8863ba
154+
30 | 66326 | 3359 | 0x4e4804d7b82805c7
155+
31 | 69685 | 1744 | 0x75b7224cc8209457
156+
32 | 71429 | 152 | 0xb01e26b40c0cf7c0
157+
33 | 71581 | 11 | 0xc66002b7f48c0472
158+
34 | 71592 | 1209 | 0x0a33021dc4007363
159+
35 | 72801 | 1795 | 0xd0cc22ea708c921f
160+
36 | 74596 | 856 | 0x49e3007c9c2c5727
161+
37 | 75452 | 97 | 0xe0b422e3c40c89dc
162+
38 | 75549 | 1299 | 0xbd1806074024536a
163+
39 | 76848 | 131 | 0xd61104147c28928d
164+
40 | 76979 | 1987 | 0x31930627a080ebb0
165+
41 | 78966 | 11254 | 0x4c4400e65c24beff
166+
42 | 90220 | 868 | 0xa92400ca5ca02488
167+
43 | 91088 | 6279 | 0x5a3d0443f0a0d81a
168+
44 | 97367 | 969 | 0x7770042d140c7472
169+
45 | 98336 | 1664 | 0xe508202f55c46d2d`;
168170

169171
console.log("ok");
170172

@@ -217,6 +219,7 @@ for (let i = 0; i < totalChunks; i++) {
217219
console.log(`❌ Mismatch at chunk ${i + 1}:`);
218220
console.log(` Expected: offset=${expected.offset}, size=${expected.size}, hash=${expected.hash}`);
219221
console.log(` Actual: offset=${actual.offset}, size=${actual.size}, hash=${actual.hash}`);
222+
process.exitCode = 1;
220223
}
221224
}
222225

@@ -238,3 +241,12 @@ console.log(`Total bytes processed: ${testResults.totalProcessed}`);
238241
console.log(`Average chunk size: ${testResults.averageChunkSize.toFixed(1)} bytes`);
239242
console.log(`Matching chunks: ${matches}/${totalChunks}`);
240243
console.log(`Accuracy: ${((matches / totalChunks) * 100).toFixed(2)}%`);
244+
245+
const input = generateTestInput().slice(0, 100);
246+
247+
let output = "";
248+
for (let i = 0; i < input.length; i++) {
249+
output += input[i].toString(16).padStart(2, "0") + " ";
250+
}
251+
252+
console.log("First 100 bytes", output);

packages/gearhash-wasm/vendor/test_gearhash.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,27 @@
11
use gearhash::{Hasher, DEFAULT_TABLE};
22

3-
// Simple deterministic RNG for reproducible results (32-bit version)
3+
// Simple deterministic RNG for reproducible results (24-bit version)
44
struct SimpleRng {
55
state: u32,
66
}
77

88
impl SimpleRng {
99
fn new(seed: u32) -> Self {
10-
Self { state: seed }
10+
Self { state: seed & 0xFFFFFF } // Keep only 24 bits
1111
}
1212

13-
fn next_u32(&mut self) -> u32 {
14-
// Simple 32-bit xorshift algorithm
15-
self.state ^= self.state << 13;
16-
self.state ^= self.state >> 17;
17-
self.state ^= self.state << 5;
13+
fn next_u24(&mut self) -> u32 {
14+
// Simple 24-bit linear congruential generator
15+
// Using 24-bit arithmetic to avoid overflow
16+
self.state = (self.state.wrapping_mul(1111) + 12345) & 0xFFFFFF;
1817
self.state
1918
}
2019

21-
fn next_u64(&mut self) -> u64 {
22-
// Generate two 32-bit values and combine them
23-
let low = self.next_u32() as u64;
24-
let high = self.next_u32() as u64;
25-
(high << 32) | low
26-
}
27-
2820
fn fill_bytes(&mut self, dest: &mut [u8]) {
29-
for chunk in dest.chunks_mut(8) {
30-
let value = self.next_u64();
21+
for chunk in dest.chunks_mut(3) {
22+
let value = self.next_u24();
3123
for (i, byte) in chunk.iter_mut().enumerate() {
32-
*byte = (value >> (i * 8)) as u8;
24+
*byte = ((value >> (i * 8)) & 0xFF) as u8;
3325
}
3426
}
3527
}
@@ -111,4 +103,7 @@ fn test_gearhash() {
111103

112104
fn main() {
113105
test_gearhash();
106+
107+
let input_buf = generate_test_input();
108+
println!("First 100 bytes: {:02x?}", &input_buf[..100]);
114109
}

0 commit comments

Comments
 (0)