1pub mod accumulator;
59pub mod complex;
61pub mod dispatch;
63pub mod f16;
65pub mod quantized;
67
68pub mod builtins;
76
77pub mod buffer;
81pub mod tensor;
83pub mod tensor_snap;
85pub mod scratchpad;
87pub mod aligned_pool;
89mod kernel_bridge;
91pub use kernel_bridge::kernel;
92pub mod paged_kv;
94pub mod binned_alloc;
96pub mod frame_arena;
98pub mod object_slab;
100pub mod gc;
102pub mod sparse;
104pub mod sparse_solvers;
106pub mod tensor_tiled;
108pub mod tensor_simd;
110pub mod tensor_pool;
112pub mod det_map;
114pub mod linalg;
116pub mod value;
118pub mod error;
120pub mod lib_registry;
122pub mod json;
124pub mod datetime;
126pub mod window;
128pub mod stats;
130pub mod distributions;
132pub mod hypothesis;
134pub mod ml;
136pub mod fft;
138pub mod stationarity;
140pub mod ode;
142pub mod sparse_eigen;
144pub mod interpolate;
146pub mod optimize;
148pub mod clustering;
150pub mod tensor_dtype;
152pub mod timeseries;
154pub mod integrate;
156pub mod differentiate;
158pub mod profile;
161pub mod runtime_policy;
165pub mod idx;
168
169pub use buffer::Buffer;
174pub use tensor::Tensor;
176pub use scratchpad::Scratchpad;
178pub use aligned_pool::{AlignedPool, AlignedByteSlice};
180pub use paged_kv::{KvBlock, PagedKvCache};
182pub use gc::{GcRef, GcHeap};
184pub use binned_alloc::BinnedAllocator;
186pub use frame_arena::{FrameArena, ArenaStore};
188pub use object_slab::{ObjectSlab, SlabRef};
190pub use sparse::{SparseCsr, SparseCoo};
192pub use tensor_tiled::TiledMatmul;
194pub use det_map::{DetMap, murmurhash3, murmurhash3_finalize, value_hash, values_equal_static};
196pub use value::{Value, Bf16, FnValue};
198pub use error::RuntimeError;
200pub use tensor_dtype::{DType, TypedStorage};
202
203#[cfg(test)]
208mod tests {
209 use super::*;
210 use std::rc::Rc;
211 use cjc_repro::Rng;
212
213 #[test]
216 fn test_buffer_alloc_get_set() {
217 let mut buf = Buffer::alloc(5, 0.0f64);
218 assert_eq!(buf.len(), 5);
219 assert_eq!(buf.get(0), Some(0.0));
220 assert_eq!(buf.get(4), Some(0.0));
221 assert_eq!(buf.get(5), None);
222
223 buf.set(2, 42.0).unwrap();
224 assert_eq!(buf.get(2), Some(42.0));
225
226 assert!(buf.set(10, 1.0).is_err());
227 }
228
229 #[test]
230 fn test_buffer_from_vec() {
231 let buf = Buffer::from_vec(vec![1, 2, 3, 4, 5]);
232 assert_eq!(buf.len(), 5);
233 assert_eq!(buf.get(0), Some(1));
234 assert_eq!(buf.get(4), Some(5));
235 assert_eq!(buf.as_slice(), vec![1, 2, 3, 4, 5]);
236 }
237
238 #[test]
239 fn test_buffer_cow_behavior() {
240 let buf_a = Buffer::from_vec(vec![10, 20, 30]);
241 let mut buf_b = buf_a.clone();
242
243 assert_eq!(buf_a.refcount(), 2);
244 assert_eq!(buf_b.refcount(), 2);
245
246 buf_b.set(0, 99).unwrap();
247
248 assert_eq!(buf_a.refcount(), 1);
249 assert_eq!(buf_b.refcount(), 1);
250 assert_eq!(buf_a.get(0), Some(10));
251 assert_eq!(buf_b.get(0), Some(99));
252 }
253
254 #[test]
255 fn test_buffer_clone_buffer_forces_deep_copy() {
256 let buf_a = Buffer::from_vec(vec![1, 2, 3]);
257 let buf_b = buf_a.clone_buffer();
258
259 assert_eq!(buf_a.refcount(), 1);
260 assert_eq!(buf_b.refcount(), 1);
261 assert_eq!(buf_a.as_slice(), buf_b.as_slice());
262 }
263
264 #[test]
267 fn test_tensor_creation_and_indexing() {
268 let t = Tensor::zeros(&[2, 3]);
269 assert_eq!(t.shape(), &[2, 3]);
270 assert_eq!(t.ndim(), 2);
271 assert_eq!(t.len(), 6);
272 assert_eq!(t.get(&[0, 0]).unwrap(), 0.0);
273 assert_eq!(t.get(&[1, 2]).unwrap(), 0.0);
274
275 assert!(t.get(&[2, 0]).is_err());
276 assert!(t.get(&[0]).is_err());
277 }
278
279 #[test]
280 fn test_tensor_from_vec_and_set() {
281 let mut t = Tensor::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], &[2, 3]).unwrap();
282 assert_eq!(t.get(&[0, 0]).unwrap(), 1.0);
283 assert_eq!(t.get(&[0, 2]).unwrap(), 3.0);
284 assert_eq!(t.get(&[1, 0]).unwrap(), 4.0);
285 assert_eq!(t.get(&[1, 2]).unwrap(), 6.0);
286
287 t.set(&[1, 1], 99.0).unwrap();
288 assert_eq!(t.get(&[1, 1]).unwrap(), 99.0);
289 }
290
291 #[test]
292 fn test_tensor_elementwise_ops() {
293 let a = Tensor::from_vec(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]).unwrap();
294 let b = Tensor::from_vec(vec![5.0, 6.0, 7.0, 8.0], &[2, 2]).unwrap();
295
296 let sum = a.add(&b).unwrap();
297 assert_eq!(sum.to_vec(), vec![6.0, 8.0, 10.0, 12.0]);
298
299 let diff = a.sub(&b).unwrap();
300 assert_eq!(diff.to_vec(), vec![-4.0, -4.0, -4.0, -4.0]);
301
302 let prod = a.mul_elem(&b).unwrap();
303 assert_eq!(prod.to_vec(), vec![5.0, 12.0, 21.0, 32.0]);
304
305 let quot = b.div_elem(&a).unwrap();
306 assert_eq!(quot.to_vec(), vec![5.0, 3.0, 7.0 / 3.0, 2.0]);
307 }
308
309 #[test]
310 fn test_tensor_matmul_correctness() {
311 let a = Tensor::from_vec(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]).unwrap();
312 let b = Tensor::from_vec(vec![5.0, 6.0, 7.0, 8.0], &[2, 2]).unwrap();
313
314 let c = a.matmul(&b).unwrap();
315 assert_eq!(c.shape(), &[2, 2]);
316 assert_eq!(c.get(&[0, 0]).unwrap(), 19.0);
317 assert_eq!(c.get(&[0, 1]).unwrap(), 22.0);
318 assert_eq!(c.get(&[1, 0]).unwrap(), 43.0);
319 assert_eq!(c.get(&[1, 1]).unwrap(), 50.0);
320 }
321
322 #[test]
323 fn test_tensor_matmul_nonsquare() {
324 let a = Tensor::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], &[2, 3]).unwrap();
325 let b = Tensor::from_vec(vec![7.0, 8.0, 9.0, 10.0, 11.0, 12.0], &[3, 2]).unwrap();
326
327 let c = a.matmul(&b).unwrap();
328 assert_eq!(c.shape(), &[2, 2]);
329 assert_eq!(c.get(&[0, 0]).unwrap(), 58.0);
330 assert_eq!(c.get(&[0, 1]).unwrap(), 64.0);
331 assert_eq!(c.get(&[1, 0]).unwrap(), 139.0);
332 assert_eq!(c.get(&[1, 1]).unwrap(), 154.0);
333 }
334
335 #[test]
336 fn test_tensor_reshape_shares_buffer() {
337 let t = Tensor::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], &[2, 3]).unwrap();
338 let r = t.reshape(&[3, 2]).unwrap();
339
340 assert_eq!(r.shape(), &[3, 2]);
341 assert_eq!(r.get(&[0, 0]).unwrap(), 1.0);
342 assert_eq!(r.get(&[2, 1]).unwrap(), 6.0);
343
344 assert_eq!(t.buffer.refcount(), 2);
345
346 assert!(t.reshape(&[4, 2]).is_err());
347 }
348
349 #[test]
350 fn test_tensor_sum_and_mean() {
351 let t = Tensor::from_vec(vec![1.0, 2.0, 3.0, 4.0], &[4]).unwrap();
352 assert!((t.sum() - 10.0).abs() < 1e-12);
353 assert!((t.mean() - 2.5).abs() < 1e-12);
354 }
355
356 #[test]
359 fn test_gc_alloc_and_read() {
360 let mut heap = GcHeap::new(100);
361 let r1 = heap.alloc(42i64);
362 let r2 = heap.alloc("hello".to_string());
363
364 assert_eq!(heap.live_count(), 2);
365 assert_eq!(*heap.get::<i64>(r1).unwrap(), 42);
366 assert_eq!(heap.get::<String>(r2).unwrap().as_str(), "hello");
367
368 assert!(heap.get::<f64>(r1).is_none());
369 }
370
371 #[test]
372 fn test_gc_collect_is_noop_rc_backed() {
373 let mut heap = GcHeap::new(100);
376 let r1 = heap.alloc(1i64);
377 let r2 = heap.alloc(2i64);
378 let r3 = heap.alloc(3i64);
379
380 assert_eq!(heap.live_count(), 3);
381
382 heap.collect(&[r1, r2]);
384
385 assert_eq!(heap.live_count(), 3, "RC keeps all objects alive");
386 assert_eq!(*heap.get::<i64>(r1).unwrap(), 1);
387 assert_eq!(*heap.get::<i64>(r2).unwrap(), 2);
388 assert_eq!(*heap.get::<i64>(r3).unwrap(), 3);
389 }
390
391 #[test]
392 fn test_gc_explicit_free_and_slot_reuse() {
393 let mut heap = GcHeap::new(100);
395 let r1 = heap.alloc(1i64);
396 let r2 = heap.alloc(2i64);
397 let r3 = heap.alloc(3i64);
398
399 heap.free(r1);
401 heap.free(r2);
402 heap.free(r3);
403 assert_eq!(heap.live_count(), 0);
404 assert_eq!(heap.free_list().len(), 3);
405
406 let r4 = heap.alloc(99i64);
408 assert!(r4.index < 3, "should reuse a freed slot");
409 assert_eq!(*heap.get::<i64>(r4).unwrap(), 99);
410 }
411
412 #[test]
415 fn test_stable_summation_via_tensor() {
416 let n = 100_000;
417 let data: Vec<f64> = (0..n).map(|_| 0.00001).collect();
418 let t = Tensor::from_vec(data, &[n]).unwrap();
419 let result = t.sum();
420 let expected = 0.00001 * n as f64;
421 assert!(
422 (result - expected).abs() < 1e-10,
423 "Kahan sum drift: expected {expected}, got {result}"
424 );
425 }
426
427 #[test]
430 fn test_tensor_randn_deterministic() {
431 let mut rng1 = Rng::seeded(42);
432 let mut rng2 = Rng::seeded(42);
433
434 let t1 = Tensor::randn(&[3, 4], &mut rng1);
435 let t2 = Tensor::randn(&[3, 4], &mut rng2);
436
437 assert_eq!(t1.to_vec(), t2.to_vec());
438 }
439
440 #[test]
443 fn test_value_display() {
444 assert_eq!(format!("{}", Value::Int(42)), "42");
445 assert_eq!(format!("{}", Value::Bool(true)), "true");
446 assert_eq!(format!("{}", Value::Void), "void");
447 assert_eq!(format!("{}", Value::String(Rc::new("hi".into()))), "hi");
448 }
449
450 #[test]
451 fn test_cow_string_clone_shares() {
452 let s = Value::String(Rc::new("hello".into()));
453 let s2 = s.clone();
454 if let (Value::String(a), Value::String(b)) = (&s, &s2) {
455 assert!(Rc::ptr_eq(a, b));
456 } else {
457 panic!("expected String values");
458 }
459 }
460
461 #[test]
462 fn test_cow_string_display() {
463 let s = Value::String(Rc::new("world".into()));
464 assert_eq!(format!("{}", s), "world");
465 }
466
467 #[test]
470 fn test_byteslice_value_display_utf8() {
471 let bs = Value::ByteSlice(Rc::new(b"hello".to_vec()));
472 assert_eq!(format!("{}", bs), r#"b"hello""#);
473 }
474
475 #[test]
476 fn test_byteslice_value_display_hex() {
477 let bs = Value::ByteSlice(Rc::new(vec![0xff, 0x00, 0x41]));
478 assert_eq!(format!("{}", bs), r#"b"\xff\x00A""#);
479 }
480
481 #[test]
482 fn test_strview_value_display() {
483 let sv = Value::StrView(Rc::new(b"world".to_vec()));
484 assert_eq!(format!("{}", sv), "world");
485 }
486
487 #[test]
488 fn test_u8_value_display() {
489 assert_eq!(format!("{}", Value::U8(65)), "65");
490 }
491
492 #[test]
493 fn test_byteslice_hash_deterministic() {
494 let a = Value::ByteSlice(Rc::new(b"hello".to_vec()));
495 let b = Value::ByteSlice(Rc::new(b"hello".to_vec()));
496 assert_eq!(value_hash(&a), value_hash(&b));
497 }
498
499 #[test]
500 fn test_byteslice_hash_different_content() {
501 let a = Value::ByteSlice(Rc::new(b"hello".to_vec()));
502 let b = Value::ByteSlice(Rc::new(b"world".to_vec()));
503 assert_ne!(value_hash(&a), value_hash(&b));
504 }
505
506 #[test]
507 fn test_byteslice_equality() {
508 let a = Value::ByteSlice(Rc::new(b"abc".to_vec()));
509 let b = Value::ByteSlice(Rc::new(b"abc".to_vec()));
510 let c = Value::ByteSlice(Rc::new(b"def".to_vec()));
511 assert!(values_equal_static(&a, &b));
512 assert!(!values_equal_static(&a, &c));
513 }
514
515 #[test]
516 fn test_strview_equality() {
517 let a = Value::StrView(Rc::new(b"test".to_vec()));
518 let b = Value::StrView(Rc::new(b"test".to_vec()));
519 assert!(values_equal_static(&a, &b));
520 }
521
522 #[test]
523 fn test_u8_hash_and_equality() {
524 let a = Value::U8(42);
525 let b = Value::U8(42);
526 let c = Value::U8(99);
527 assert_eq!(value_hash(&a), value_hash(&b));
528 assert_ne!(value_hash(&a), value_hash(&c));
529 assert!(values_equal_static(&a, &b));
530 assert!(!values_equal_static(&a, &c));
531 }
532
533 #[test]
534 fn test_byteslice_clone_shares_rc() {
535 let bs = Value::ByteSlice(Rc::new(b"data".to_vec()));
536 let bs2 = bs.clone();
537 if let (Value::ByteSlice(a), Value::ByteSlice(b)) = (&bs, &bs2) {
538 assert!(Rc::ptr_eq(a, b));
539 } else {
540 panic!("expected ByteSlice values");
541 }
542 }
543
544 #[test]
545 fn test_byteslice_in_detmap() {
546 let mut map = DetMap::new();
547 let key = Value::ByteSlice(Rc::new(b"token".to_vec()));
548 map.insert(key.clone(), Value::Int(1));
549
550 let lookup = Value::ByteSlice(Rc::new(b"token".to_vec()));
551 assert!(map.contains_key(&lookup));
552 match map.get(&lookup) {
553 Some(Value::Int(1)) => {},
554 _ => panic!("expected Int(1)"),
555 }
556 }
557
558 #[test]
559 fn test_murmurhash3_byteslice_stability() {
560 let h1 = murmurhash3(b"hello");
561 let h2 = murmurhash3(b"hello");
562 assert_eq!(h1, h2);
563
564 let h3 = murmurhash3(b"");
565 let h4 = murmurhash3(b"");
566 assert_eq!(h3, h4);
567
568 assert_ne!(murmurhash3(b"hello"), murmurhash3(b"world"));
569 }
570}