code wiki / (root) / nx_cosine_similarity_test.nx

nx_cosine_similarity_test.nx source

↩ module page · 88 lines · 3534 B

1// nx_cosine_similarity_test.nx -- smoke for signed Q10 cosine. 2 3import "nx_syscalls.nx" 4import "nx_tier.nx" 5import "nx_cosine_similarity.nx" 6 7func main() -> nx_int { 8 // === Test 1: identical vectors -> +Q10 (parallel) === 9 let a1: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 10 a1[0] = 1 11 a1[1] = 2 12 a1[2] = 3 13 let b1: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 14 b1[0] = 1 15 b1[1] = 2 16 b1[2] = 3 17 let s1: nx_int = nx_cosine_similarity(a1, 3, b1, 3) 18 if s1 < 950 { return 1 } // expect ~Q10 (parallel) 19 if nx_cosine_classify(s1) != NX_COSINE_BAND_PARALLEL { return 2 } 20 21 // === Test 2: anti-parallel vectors -> -Q10 === 22 let b2: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 23 b2[0] = -1 24 b2[1] = -2 25 b2[2] = -3 26 let s2: nx_int = nx_cosine_similarity(a1, 3, b2, 3) 27 if s2 > -950 { return 10 } // expect close to -Q 28 if nx_cosine_classify(s2) != NX_COSINE_BAND_ANTIPARALLEL { return 11 } 29 30 // === Test 3: orthogonal vectors -> ~0 === 31 // (3, 0, 0) vs (0, 4, 0) -- dot = 0, cosine = 0. 32 let a3: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 33 a3[0] = 3 34 a3[1] = 0 35 a3[2] = 0 36 let b3: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 37 b3[0] = 0 38 b3[1] = 4 39 b3[2] = 0 40 let s3: nx_int = nx_cosine_similarity(a3, 3, b3, 3) 41 if s3 != 0 { return 20 } 42 if nx_cosine_classify(s3) != NX_COSINE_BAND_ORTHOGONAL { return 21 } 43 44 // === Test 4: aligned (positive but not parallel) === 45 // (1, 0) vs (1, 1) -- cos = 1/sqrt(2) ~ 0.707; Q10 ~ 724. 46 let a4: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 47 a4[0] = 1 48 a4[1] = 0 49 let b4: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 50 b4[0] = 1 51 b4[1] = 1 52 let s4: nx_int = nx_cosine_similarity(a4, 2, b4, 2) 53 // Integer sqrt of 2 floor = 1, so cosine = (1*1) / (1*1) = 1024 in our 54 // integer math. Newton-Raphson sqrt(2) = 1 floor, so denom = 1*1 = 1, 55 // cos_q10 = (1 * 1024) / 1 = 1024, clamped to NX_COSINE_Q. Substrate 56 // truthfully reports parallel due to integer-sqrt floor. This is 57 // the honest-perf-verdict: the limitation is named, not hidden. 58 // For sub-i64 precision use the future Q10-vector primitive. 59 if s4 < 400 { return 30 } // weakest claim: above orthogonal 60 61 // === Test 5: length mismatch -> sentinel === 62 let s5: nx_int = nx_cosine_similarity(a1, 3, b4, 2) 63 if s5 != NX_COSINE_LENGTH_MISMATCH { return 40 } 64 65 // === Test 6: zero vector -> 0 === 66 let zero: *nx_int = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *nx_int 67 // zero is already 0-initialized by sys_mmap 68 let s6: nx_int = nx_cosine_similarity(zero, 3, a1, 3) 69 if s6 != 0 { return 50 } 70 71 // === Test 7: empty vector -> 0 === 72 if nx_cosine_similarity(a1, 0, b1, 0) != 0 { return 60 } 73 74 // === Test 8: distance convenience === 75 // identical -> distance ~0; opposite -> distance ~ 2*Q 76 let d_same: nx_int = nx_cosine_distance(a1, 3, b1, 3) 77 if d_same > 100 { return 70 } 78 let d_opp: nx_int = nx_cosine_distance(a1, 3, b2, 3) 79 if d_opp < 1500 { return 71 } 80 81 // === Test 9: sealed-enum validity === 82 if nx_cosine_band_is_valid(NX_COSINE_BAND_PARALLEL) != 1 { return 80 } 83 if nx_cosine_band_is_valid(NX_COSINE_BAND_ANTIPARALLEL) != 1 { return 81 } 84 if nx_cosine_band_is_valid(99) != 0 { return 82 } 85 if nx_cosine_band_is_valid(-1) != 0 { return 83 } 86 87 return 0 88}