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