1#![warn(missing_docs)]
55#![warn(clippy::pedantic)]
56#![allow(clippy::module_name_repetitions)]
57#![allow(clippy::cast_possible_truncation)]
58#![allow(clippy::cast_possible_wrap)]
59#![allow(clippy::cast_sign_loss)]
60#![allow(clippy::cast_lossless)] pub mod arithmetic;
63pub mod dispatch;
64mod error;
65pub mod kernels;
66mod packed;
67pub mod simd;
68mod sparse;
69mod trit;
70mod tryte;
71pub mod vsa;
72mod word;
73
74#[cfg(feature = "cuda")]
75pub mod gpu;
76
77pub use dispatch::{DevicePreference, DispatchConfig, Format, Operation, TritVector};
78pub use error::{Result, TernaryError};
79pub use kernels::{
80 get_backend, get_backend_for_size, BackendConfig, BackendPreference, CpuBackend,
81 DynamicBackend, RandomConfig, TernaryBackend,
82};
83pub use packed::PackedTritVec;
84pub use sparse::SparseVec;
85pub use trit::Trit;
86pub use tryte::{Tryte3, TRYTE3_MAX, TRYTE3_MIN};
87pub use word::{Word6, WORD6_MAX, WORD6_MIN};
88
89#[cfg(feature = "cuda")]
90pub use gpu::{
91 warn_if_cpu, GpuBind, GpuBundle, GpuCosineSimilarity, GpuDispatchable, GpuDotSimilarity,
92 GpuError, GpuHammingDistance, GpuRandom, GpuResult, GpuUnbind, RandomInput,
93};
94
95#[cfg(feature = "cuda")]
96pub use kernels::CubeclBackend;
97
98pub mod prelude {
106 pub use crate::arithmetic::{from_balanced_ternary, to_balanced_ternary};
107 pub use crate::kernels::{
108 get_backend, BackendConfig, BackendPreference, CpuBackend, TernaryBackend,
109 };
110 pub use crate::packed::PackedTritVec;
111 pub use crate::sparse::SparseVec;
112 pub use crate::trit::Trit;
113 pub use crate::tryte::Tryte3;
114 pub use crate::vsa::{bind, bundle, cosine_similarity, hamming_distance};
115 pub use crate::word::Word6;
116 pub use crate::{Result, TernaryError};
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_basic_workflow() {
125 let mut vec = PackedTritVec::new(100);
127
128 vec.set(0, Trit::P);
130 vec.set(1, Trit::N);
131 vec.set(50, Trit::P);
132
133 assert_eq!(vec.get(0), Trit::P);
135 assert_eq!(vec.get(1), Trit::N);
136 assert_eq!(vec.get(2), Trit::Z);
137 assert_eq!(vec.count_nonzero(), 3);
138 }
139
140 #[test]
141 fn test_vsa_workflow() {
142 let mut a = PackedTritVec::new(64);
143 let mut b = PackedTritVec::new(64);
144
145 for i in 0..32 {
147 a.set(i, Trit::P);
148 b.set(i, Trit::P);
149 }
150
151 let bundled = vsa::bundle(&a, &b);
153 let sim = vsa::cosine_similarity(&a, &bundled);
154 assert!(sim > 0.9, "bundled vector should be similar to inputs");
155
156 let bound = vsa::bind(&a, &b);
158 let recovered = vsa::unbind(&bound, &b);
159
160 for i in 0..64 {
162 assert_eq!(recovered.get(i), a.get(i));
163 }
164 }
165
166 #[test]
167 fn test_sparse_workflow() {
168 let mut sparse = SparseVec::new(10000);
169 sparse.set(100, Trit::P);
170 sparse.set(5000, Trit::N);
171
172 assert_eq!(sparse.count_nonzero(), 2);
173 assert!(sparse.sparsity() > 0.99);
174
175 let packed = sparse.to_packed();
177 assert_eq!(packed.get(100), Trit::P);
178 assert_eq!(packed.get(5000), Trit::N);
179 }
180
181 #[test]
182 fn test_tryte_arithmetic() {
183 let a = Tryte3::from_value(7).unwrap();
184 let b = Tryte3::from_value(5).unwrap();
185
186 let (sum, carry) = a + b;
187 let total = sum.value() + carry.value() as i32 * 27;
188 assert_eq!(total, 12);
189 }
190
191 #[test]
192 fn test_word_arithmetic() {
193 let a = Word6::from_value(100).unwrap();
194 let b = Word6::from_value(50).unwrap();
195
196 let (sum, carry) = a + b;
197 let total = sum.value() + carry.value() as i32 * 729;
198 assert_eq!(total, 150);
199 }
200}