sc_neurocore_engine/bindings/
hdc.rs1use pyo3::exceptions::PyValueError;
12use pyo3::prelude::*;
13use rand::SeedableRng;
14
15pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
17 module.add_class::<PyBitStreamTensor>()?;
18 Ok(())
19}
20
21#[pyclass(
23 name = "BitStreamTensor",
24 module = "sc_neurocore_engine.sc_neurocore_engine"
25)]
26pub struct PyBitStreamTensor {
27 inner: crate::bitstream::BitStreamTensor,
28}
29
30#[pymethods]
31impl PyBitStreamTensor {
32 #[new]
34 #[pyo3(signature = (dimension=10000, seed=0xACE1))]
35 fn new(dimension: usize, seed: u64) -> Self {
36 let mut rng = rand_xoshiro::Xoshiro256PlusPlus::seed_from_u64(seed);
37 let data = crate::bitstream::bernoulli_packed(0.5, dimension, &mut rng);
38 Self {
39 inner: crate::bitstream::BitStreamTensor::from_words(data, dimension),
40 }
41 }
42
43 #[staticmethod]
45 fn from_packed(data: Vec<u64>, length: usize) -> PyResult<Self> {
46 if length == 0 {
47 return Err(PyValueError::new_err("bitstream length must be > 0"));
48 }
49 Ok(Self {
50 inner: crate::bitstream::BitStreamTensor::from_words(data, length),
51 })
52 }
53
54 fn xor_inplace(&mut self, other: &PyBitStreamTensor) {
56 self.inner.xor_inplace(&other.inner);
57 }
58
59 fn xor(&self, other: &PyBitStreamTensor) -> PyBitStreamTensor {
61 PyBitStreamTensor {
62 inner: self.inner.xor(&other.inner),
63 }
64 }
65
66 fn rotate_right(&mut self, shift: usize) {
68 self.inner.rotate_right(shift);
69 }
70
71 fn hamming_distance(&self, other: &PyBitStreamTensor) -> f32 {
73 self.inner.hamming_distance(&other.inner)
74 }
75
76 #[staticmethod]
78 fn bundle(vectors: Vec<PyRef<'_, PyBitStreamTensor>>) -> PyBitStreamTensor {
79 let refs: Vec<&crate::bitstream::BitStreamTensor> =
80 vectors.iter().map(|vector| &vector.inner).collect();
81 PyBitStreamTensor {
82 inner: crate::bitstream::BitStreamTensor::bundle(&refs),
83 }
84 }
85
86 fn popcount(&self) -> u64 {
88 crate::bitstream::popcount(&self.inner)
89 }
90
91 #[getter]
93 fn data(&self) -> Vec<u64> {
94 self.inner.data.clone()
95 }
96
97 #[getter]
99 fn length(&self) -> usize {
100 self.inner.length
101 }
102
103 fn __len__(&self) -> usize {
104 self.inner.length
105 }
106
107 fn __repr__(&self) -> String {
108 format!(
109 "BitStreamTensor(length={}, popcount={})",
110 self.inner.length,
111 crate::bitstream::popcount(&self.inner)
112 )
113 }
114}