ternaria_arith/lib.rs
1//! Balanced ternary arithmetic.
2//!
3//! Digits are -1, 0 and +1 (a [`Trit`]). A value is the sum of d_k * 3^k over
4//! its digits. One trit carries log2(3), about 1.585 bits.
5//!
6//! Properties relied on elsewhere in the platform:
7//!
8//! - Negation flips every digit and requires no carry. There is no two's
9//! complement representation and no signed/unsigned distinction.
10//! - The range is symmetric: n trits cover -(3^n-1)/2 to (3^n-1)/2. `-x` never
11//! overflows and [`Word::abs`] is total.
12//! - Truncation gives the correctly rounded result. Discarded digits are worth
13//! at most half a unit in the last place, and exact ties cannot occur.
14//! - Comparison has three outcomes and returns one trit. See [`Word::cmp3`].
15//!
16//! # Example
17//!
18//! ```
19//! use ternaria_arith::{Trit, Word};
20//!
21//! let a = Word::from_value(42);
22//! let b = Word::from_value(-17);
23//!
24//! assert_eq!(a.checked_add(b).unwrap().value(), 25);
25//!
26//! // Negation cannot overflow.
27//! assert_eq!((-a).value(), -42);
28//! assert_eq!(Word::MIN.neg(), Word::MAX);
29//!
30//! // Comparison returns one trit.
31//! assert_eq!(b.cmp3(a), Trit::Neg);
32//!
33//! // Balanced ternary notation: T is -1.
34//! assert_eq!(a.to_string(), "1TTT0");
35//! assert_eq!("1TTT0".parse::<Word>().unwrap(), a);
36//!
37//! // A 27-trit product is exactly 54 trits, so this cannot overflow.
38//! let exact = Word::MAX.widening_mul(Word::MAX);
39//! assert_eq!(exact.to_i128(), 3_812_798_742_493i128.pow(2));
40//! ```
41
42#![forbid(unsafe_code)]
43#![warn(missing_docs)]
44
45mod balanced;
46mod trit;
47
48pub use balanced::{DoubleWord, NatError, ParseTritsError, Tryte, Word};
49pub use trit::Trit;