relp_num/traits/size.rs
1//! # How much room a number takes
2//!
3//! Exact arithmetic has no rounding to wash a value away, so a number's cost is the size of its
4//! encoding rather than its magnitude. `1 / 3` is small in value and small to store;
5//! `10^30 / (10^30 + 1)` is a hair under one and expensive at both ends. Anything that wants to
6//! reason about what a problem costs to hold has to be able to ask.
7//!
8//! What to do with the answer is [`Narrow`](crate::Narrow): once the sizes are known, the values
9//! can be moved into a type that is only as wide as they need.
10
11/// The size of a number's representation, in bits.
12///
13/// Counted over the magnitude: the sign is not part of it, because it costs the same however large
14/// the value is.
15///
16/// # What implements it
17///
18/// The rational types of this crate. The primitive integers and the markers of
19/// [`fixed`](crate::fixed) answer the same question trivially and are not implemented yet, so code
20/// that wants to measure a mixed set of coefficients cannot do so through this trait alone.
21pub trait EncodingSize {
22 /// Bits in the numerator.
23 ///
24 /// Zero for the value zero, and the bit length of the magnitude otherwise.
25 #[must_use]
26 fn numerator_bits(&self) -> u32;
27
28 /// Bits in the denominator.
29 ///
30 /// One for a value that is an integer, whose denominator is one.
31 #[must_use]
32 fn denominator_bits(&self) -> u32;
33
34 /// What it costs to store this value.
35 #[must_use]
36 fn encoding_bits(&self) -> u64 {
37 u64::from(self.numerator_bits()) + u64::from(self.denominator_bits())
38 }
39}