Skip to content

Commit 7024115

Browse files
authored
Merge pull request #150 from AdaWorldAPI/claude/compare-rustynum-ndarray-5ePRn
fix: Container = 16,384 bits (256 × u64) — canonical layout
2 parents 904cde7 + 870a628 commit 7024115

17 files changed

Lines changed: 302 additions & 285 deletions

File tree

crates/ladybug-contract/src/container.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
1-
//! 8192-bit Container — the atomic unit of LadybugDB.
1+
//! 16,384-bit Container (CogRecord) — the atomic unit of LadybugDB.
22
//!
3-
//! A Container is a 1 KB bit-vector: 128 × u64 = 8,192 bits.
3+
//! A Container is a 2 KB bit-vector: 256 × u64 = 16,384 bits.
44
//! All cognitive operations (XOR bind, Hamming distance, majority-vote bundle)
5-
//! operate at this granularity.
5+
//! operate at this granularity. Each CogRecord IS one container.
66
77
/// Total bits in a single container.
8-
pub const CONTAINER_BITS: usize = 8_192;
8+
pub const CONTAINER_BITS: usize = 16_384;
99
/// Number of u64 words in a container.
10-
pub const CONTAINER_WORDS: usize = CONTAINER_BITS / 64; // 128
10+
pub const CONTAINER_WORDS: usize = CONTAINER_BITS / 64; // 256
1111
/// Number of bytes in a container.
12-
pub const CONTAINER_BYTES: usize = CONTAINER_WORDS * 8; // 1024
12+
pub const CONTAINER_BYTES: usize = CONTAINER_WORDS * 8; // 2048
1313
/// AVX-512 iteration count (8 words per 512-bit register).
14-
pub const CONTAINER_AVX512_ITERS: usize = CONTAINER_WORDS / 8; // 16
14+
pub const CONTAINER_AVX512_ITERS: usize = CONTAINER_WORDS / 8; // 32
1515
/// Maximum content containers in a CogRecord.
1616
pub const MAX_CONTAINERS: usize = 255;
1717
/// Expected Hamming distance for two random containers.
18-
pub const EXPECTED_DISTANCE: u32 = (CONTAINER_BITS / 2) as u32; // 4096
18+
pub const EXPECTED_DISTANCE: u32 = (CONTAINER_BITS / 2) as u32; // 8192
1919
/// Standard deviation of Hamming distance for random containers.
20-
pub const SIGMA: f64 = 45.254833995939045;
20+
/// sqrt(16384 / 4) = sqrt(4096) = 64.0
21+
pub const SIGMA: f64 = 64.0;
2122
/// Integer approximation of sigma.
22-
pub const SIGMA_APPROX: u32 = 45;
23+
pub const SIGMA_APPROX: u32 = 64;
2324

24-
/// 8,192-bit binary container for HDC/VSA operations.
25+
/// 16,384-bit binary container for HDC/VSA operations.
2526
///
2627
/// Cache-line aligned for SIMD; `#[repr(C)]` for binary stability.
2728
#[derive(Clone, PartialEq, Eq)]
@@ -216,7 +217,7 @@ impl Container {
216217
/// Zero-copy byte view (little-endian).
217218
#[inline]
218219
pub fn as_bytes(&self) -> &[u8; CONTAINER_BYTES] {
219-
// SAFETY: Container is repr(C), [u64; 128] has same layout as [u8; 1024]
220+
// SAFETY: Container is repr(C), [u64; 256] has same layout as [u8; 2048]
220221
unsafe { &*(self.words.as_ptr() as *const [u8; CONTAINER_BYTES]) }
221222
}
222223

@@ -229,7 +230,7 @@ impl Container {
229230
Self { words }
230231
}
231232

232-
/// Zero-cost borrow a `[u64; 128]` as `&Container`.
233+
/// Zero-cost borrow a `[u64; 256]` as `&Container`.
233234
///
234235
/// # Safety
235236
/// Caller must guarantee 64-byte alignment.
@@ -282,7 +283,7 @@ mod tests {
282283
let a = Container::random(42);
283284
let b = Container::random(99);
284285
let d = a.hamming(&b);
285-
assert!(d > 3500 && d < 4700, "hamming={d}, expected ~4096");
286+
assert!(d > 7000 && d < 9500, "hamming={d}, expected ~8192");
286287
}
287288

288289
#[test]

crates/ladybug-contract/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//!
1616
//! | Module | Contents |
1717
//! |--------|----------|
18-
//! | [`container`] | 8192-bit `Container` with XOR, Hamming, bundle ops |
18+
//! | [`container`] | 16,384-bit `Container` with XOR, Hamming, bundle ops |
1919
//! | [`geometry`] | `ContainerGeometry` — how content containers are interpreted |
2020
//! | [`record`] | `CogRecord` — metadata + N content containers |
2121
//! | [`meta`] | `MetaView` / `MetaViewMut` — zero-copy metadata accessors |
@@ -29,7 +29,7 @@
2929
//! | [`delegation`] | `DelegationRequest` / `DelegationResponse` |
3030
//! | [`wire`] | Binary wire protocol: `CogPacket` (8+8/4096 command packets, no JSON) |
3131
//! | [`legacy`] | V1 JSON backward compatibility (external wire format only) |
32-
//! | [`schema`] | Unified 2×8192 CogRecord schema constants and field descriptors |
32+
//! | [`schema`] | Unified 16,384-bit CogRecord schema constants and field descriptors |
3333
3434
pub mod container;
3535
pub mod wide_container;

crates/ladybug-contract/src/schema.rs

Lines changed: 168 additions & 126 deletions
Large diffs are not rendered by default.

src/cognitive/cognitive_kernel.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,8 @@ impl CognitiveKernel {
352352
packet: &CogPacket,
353353
node: &mut crate::cognitive::layer_stack::LayerNode,
354354
) -> (CognitiveKernelResult, CogPacket) {
355-
// Extract fingerprint from Container payload (Container = 8192 bits,
356-
// BindSpace = 16384 bits — zero-pad the upper half)
355+
// Extract fingerprint from Container payload (Container = 16384 bits,
356+
// same width as BindSpace Fingerprint)
357357
let content = packet.content();
358358
let input_fp = container_to_fingerprint(content);
359359

@@ -469,26 +469,19 @@ impl Default for CognitiveKernel {
469469
// CONTAINER ↔ FINGERPRINT BRIDGING
470470
// =============================================================================
471471

472-
/// Convert a Container (8192 bits = 128 × u64) to a Fingerprint-compatible
473-
/// word array (16384 bits = 256 × u64). Upper half zero-padded.
472+
/// Convert a Container (16384 bits = 256 × u64) to a Fingerprint.
473+
/// Container and Fingerprint are now the same width — direct copy.
474474
fn container_to_fingerprint(container: &Container) -> Fingerprint {
475475
let mut words = [0u64; FINGERPRINT_WORDS];
476-
for (i, &w) in container.words.iter().enumerate() {
477-
words[i] = w;
478-
}
479-
// XOR-fold: replicate lower 128 words into upper 128 with permutation
480-
// This preserves information density while filling the full 16K space
481-
for i in 0..128 {
482-
words[128 + i] = container.words[i].rotate_left(7);
483-
}
476+
words.copy_from_slice(&container.words);
484477
Fingerprint::from_raw(words)
485478
}
486479

487480
/// Convert a BindSpace fingerprint array back to a Container.
488-
/// Truncates to 128 words (8192 bits).
481+
/// Container and Fingerprint are now the same width — direct copy.
489482
fn fingerprint_to_container(fp: &[u64; FINGERPRINT_WORDS]) -> Container {
490-
let mut words = [0u64; 128];
491-
words.copy_from_slice(&fp[..128]);
483+
let mut words = [0u64; FINGERPRINT_WORDS];
484+
words.copy_from_slice(fp);
492485
Container { words }
493486
}
494487

src/container/search.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ pub fn belichtungsmesser(a: &Container, b: &Container) -> u32 {
2727
for &idx in &SAMPLE_POINTS {
2828
estimate += (a.words[idx] ^ b.words[idx]).count_ones();
2929
}
30-
// Scale: 7 samples × 64 bits = 448 bits sampled out of 8192
31-
// Scale factor: 8192 / 448 ≈ 18.29
30+
// Scale: 7 samples × 64 bits = 448 bits sampled out of CONTAINER_BITS
31+
// Scale factor: CONTAINER_BITS / 448
3232
estimate * CONTAINER_BITS as u32 / 448
3333
}
3434

src/container/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@ fn test_container_as_bytes() {
191191

192192
#[test]
193193
fn test_container_constants() {
194-
assert_eq!(CONTAINER_BITS, 8192);
195-
assert_eq!(CONTAINER_WORDS, 128);
196-
assert_eq!(CONTAINER_BYTES, 1024);
197-
assert_eq!(CONTAINER_AVX512_ITERS, 16);
194+
assert_eq!(CONTAINER_BITS, 16384);
195+
assert_eq!(CONTAINER_WORDS, 256);
196+
assert_eq!(CONTAINER_BYTES, 2048);
197+
assert_eq!(CONTAINER_AVX512_ITERS, 32);
198198
assert_eq!(CONTAINER_BITS % 64, 0);
199199
assert_eq!(CONTAINER_WORDS % 8, 0); // AVX-512 aligned
200200
assert!(CONTAINER_BITS.is_power_of_two());

src/core/rustynum_accel.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub fn fingerprint_dot_u8i8(a: &Fingerprint, b: &Fingerprint) -> i64 {
8383
}
8484

8585
// ────────────────────────────────────────────────────────────────
86-
// Container operations (8192-bit = 1024 bytes = 128 u64 words)
86+
// Container operations (16384-bit = 2048 bytes = 256 u64 words)
8787
// ────────────────────────────────────────────────────────────────
8888

8989
/// Popcount a Container using runtime-dispatched VPOPCNTDQ.

src/graph/spo/store.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ impl SpoStore {
305305

306306
/// Compute chain coherence: product of normalized link coherences.
307307
///
308-
/// coherence_per_link = 1.0 - (hamming(Z_i, X_{i+1}) / 8192.0)
308+
/// coherence_per_link = 1.0 - (hamming(Z_i, X_{i+1}) / CONTAINER_BITS)
309309
/// chain_coherence = product of all link coherences
310310
pub fn chain_coherence(&self, dns: &[u64]) -> f32 {
311311
if dns.len() < 2 { return 1.0; }
@@ -319,7 +319,7 @@ impl SpoStore {
319319
let (x_b, _, _) = match self.unpack_record(b) { Ok(v) => v, Err(_) => return 0.0 };
320320

321321
let dist = SparseContainer::hamming_sparse(&z_a, &x_b);
322-
let link_coherence = 1.0 - (dist as f32 / 8192.0);
322+
let link_coherence = 1.0 - (dist as f32 / ladybug_contract::container::CONTAINER_BITS as f32);
323323
coherence *= link_coherence;
324324
}
325325

@@ -357,7 +357,7 @@ impl SpoStore {
357357
let (_, _, z) = match self.unpack_record(record) { Ok(v) => v, Err(_) => return TruthValue::unknown() };
358358
let (x, _, _) = match self.unpack_record(next) { Ok(v) => v, Err(_) => return TruthValue::unknown() };
359359
let dist = SparseContainer::hamming_sparse(&z, &x);
360-
let link_coh = 1.0 - (dist as f32 / 8192.0);
360+
let link_coh = 1.0 - (dist as f32 / ladybug_contract::container::CONTAINER_BITS as f32);
361361
c_chain *= link_coh;
362362
}
363363
}

src/learning/dream.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Default for DreamConfig {
4545
fn default() -> Self {
4646
Self {
4747
prune_confidence_threshold: 0.2,
48-
merge_hamming_threshold: 1500, // ~18% of 8192 bits
48+
merge_hamming_threshold: 3000, // ~18% of 16384 bits
4949
recombination_count: 5,
5050
permute_offset: 7,
5151
max_output: 0,

src/learning/feedback.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ mod tests {
594594
#[test]
595595
fn test_truth_from_hamming_random() {
596596
// ~50% distance = random noise
597-
let tv = truth_from_hamming(8192, 16384);
597+
let tv = truth_from_hamming(8192, 16384); // 8192 = half of 16384 = random noise
598598
assert!((tv.f - 0.5).abs() < 0.01);
599599
assert!(tv.c < 0.1, "random should have low confidence");
600600
}

0 commit comments

Comments
 (0)