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