a/math/numbers/number.rs
1use super::ByteOrder;
2use core::fmt;
3
4/// An integer of any size, stored as its sign and the bytes of its absolute value.
5///
6/// `value` holds the absolute value (the magnitude) of the integer as bytes, in the order
7/// `byte_order` names: the most significant byte first for [`ByteOrder::BigEndian`], the
8/// least significant first for [`ByteOrder::LittleEndian`]. `negative` holds the sign. This
9/// is the sign-and-magnitude form most big-integer libraries use: `-2` is `[2]` with
10/// `negative` set, not the two's-complement byte `[0xFE]`.
11///
12/// The constructors keep the shortest form: they drop the zero bytes above the most
13/// significant non-zero byte and keep one byte for zero, so `1` and `-1` are `[1]`, and `0` is
14/// `[0]`, in either order. An empty `value` is zero as well; the constructors keep an empty
15/// vector empty. Zero is never negative: there is one zero, not a positive and a negative one.
16///
17/// The fields are public, so a `Number` can also be built directly; it is then stored exactly
18/// as given, zero bytes and the sign of zero included.
19///
20/// # Examples
21///
22/// ```
23/// use a::math::numbers::{ByteOrder, Number};
24///
25/// let big = Number::new_from_i32(-0x0001_0203, ByteOrder::BigEndian);
26/// assert_eq!(big.value, [0x01, 0x02, 0x03]);
27/// assert!(big.is_negative());
28///
29/// let little = Number::new_from_u32(0x0001_0203, ByteOrder::LittleEndian);
30/// assert_eq!(little.value, [0x03, 0x02, 0x01]);
31/// assert!(!little.is_negative());
32/// ```
33pub struct Number {
34 /// The bytes of the absolute value of the number, in the order of `byte_order`.
35 pub value: Vec<u8>,
36 /// Whether the number is below zero; `false` for zero.
37 pub negative: bool,
38 /// The order of the bytes in `value`.
39 pub byte_order: ByteOrder,
40}
41
42impl Number {
43 /// Creates a non-negative number from its bytes in `byte_order`, dropping the zero bytes
44 /// above the most significant non-zero byte: the leading zeros in big-endian order, the
45 /// trailing zeros in little-endian order.
46 ///
47 /// Zero bytes below the most significant non-zero byte are part of the number and stay.
48 /// A number whose bytes are all zero keeps one of them, `[0]`; an empty vector stays
49 /// empty.
50 ///
51 /// Takes `O(n)` time for `n` bytes and reuses the allocation of `value`. For a negative
52 /// number, see [`new_signed`](Self::new_signed).
53 ///
54 /// # Examples
55 ///
56 /// ```
57 /// use a::math::numbers::{ByteOrder, Number};
58 ///
59 /// let n = Number::new(vec![0, 0, 1, 0, 2], ByteOrder::BigEndian);
60 /// assert_eq!(n.value, [1, 0, 2]);
61 ///
62 /// let n = Number::new(vec![2, 0, 1, 0, 0], ByteOrder::LittleEndian);
63 /// assert_eq!(n.value, [2, 0, 1]);
64 ///
65 /// let zero = Number::new(vec![0, 0, 0], ByteOrder::BigEndian);
66 /// assert_eq!(zero.value, [0]);
67 /// ```
68 pub fn new(mut value: Vec<u8>, byte_order: ByteOrder) -> Self {
69 match byte_order {
70 // The most significant byte comes first: drop everything before the first
71 // non-zero byte, or all but the last byte when every byte is zero.
72 ByteOrder::BigEndian => {
73 let start = value
74 .iter()
75 .position(|&b| b != 0)
76 .unwrap_or(value.len().saturating_sub(1));
77 value.drain(..start);
78 }
79 // The most significant byte comes last: cut everything after the last non-zero
80 // byte, or all but the first byte when every byte is zero.
81 ByteOrder::LittleEndian => {
82 let end = value.iter().rposition(|&b| b != 0).map_or(1, |i| i + 1);
83 value.truncate(end);
84 }
85 }
86 Self {
87 value,
88 negative: false,
89 byte_order,
90 }
91 }
92
93 /// Creates a number from the bytes of its absolute value in `byte_order` and its sign,
94 /// dropping the high zero bytes as [`new`](Self::new) does.
95 ///
96 /// The number is negative when `negative` is set and the bytes are not all zero: zero is
97 /// never negative.
98 ///
99 /// # Examples
100 ///
101 /// ```
102 /// use a::math::numbers::{ByteOrder, Number};
103 ///
104 /// let n = Number::new_signed(vec![0, 1, 0], true, ByteOrder::BigEndian);
105 /// assert_eq!(n.value, [1, 0]);
106 /// assert!(n.is_negative());
107 ///
108 /// let zero = Number::new_signed(vec![0, 0], true, ByteOrder::BigEndian);
109 /// assert_eq!(zero.value, [0]);
110 /// assert!(!zero.is_negative());
111 /// ```
112 pub fn new_signed(value: Vec<u8>, negative: bool, byte_order: ByteOrder) -> Self {
113 let number = Self::new(value, byte_order);
114 // Once trimmed, zero is `[0]` or `[]` in either order: it keeps the sign of `new`.
115 let negative = negative && !matches!(number.value.as_slice(), [] | [0]);
116 Self { negative, ..number }
117 }
118
119 /// Creates a number from a `u8`, its only byte. Zero is kept as `[0]`.
120 pub fn new_from_u8(value: u8, byte_order: ByteOrder) -> Self {
121 Self::new(vec![value], byte_order)
122 }
123
124 /// Creates a number from the bytes of a `u16` in `byte_order`, without the high zero
125 /// bytes (see [`new`](Self::new)).
126 pub fn new_from_u16(value: u16, byte_order: ByteOrder) -> Self {
127 let bytes = match byte_order {
128 ByteOrder::BigEndian => value.to_be_bytes().to_vec(),
129 ByteOrder::LittleEndian => value.to_le_bytes().to_vec(),
130 };
131 Self::new(bytes, byte_order)
132 }
133
134 /// Creates a number from the bytes of a `u32` in `byte_order`, without the high zero
135 /// bytes (see [`new`](Self::new)).
136 pub fn new_from_u32(value: u32, byte_order: ByteOrder) -> Self {
137 let bytes = match byte_order {
138 ByteOrder::BigEndian => value.to_be_bytes().to_vec(),
139 ByteOrder::LittleEndian => value.to_le_bytes().to_vec(),
140 };
141 Self::new(bytes, byte_order)
142 }
143
144 /// Creates a number from the bytes of a `u64` in `byte_order`, without the high zero
145 /// bytes (see [`new`](Self::new)).
146 ///
147 /// # Examples
148 ///
149 /// ```
150 /// use a::math::numbers::{ByteOrder, Number};
151 ///
152 /// let n = Number::new_from_u64(0x0A0B_0C0D, ByteOrder::BigEndian);
153 /// assert_eq!(n.value, [0x0A, 0x0B, 0x0C, 0x0D]);
154 ///
155 /// let n = Number::new_from_u64(0x0A0B_0C0D, ByteOrder::LittleEndian);
156 /// assert_eq!(n.value, [0x0D, 0x0C, 0x0B, 0x0A]);
157 ///
158 /// let zero = Number::new_from_u64(0, ByteOrder::LittleEndian);
159 /// assert_eq!(zero.value, [0]);
160 /// ```
161 pub fn new_from_u64(value: u64, byte_order: ByteOrder) -> Self {
162 let bytes = match byte_order {
163 ByteOrder::BigEndian => value.to_be_bytes().to_vec(),
164 ByteOrder::LittleEndian => value.to_le_bytes().to_vec(),
165 };
166 Self::new(bytes, byte_order)
167 }
168
169 /// Creates a number from the bytes of a `u128` in `byte_order`, without the high zero
170 /// bytes (see [`new`](Self::new)).
171 pub fn new_from_u128(value: u128, byte_order: ByteOrder) -> Self {
172 let bytes = match byte_order {
173 ByteOrder::BigEndian => value.to_be_bytes().to_vec(),
174 ByteOrder::LittleEndian => value.to_le_bytes().to_vec(),
175 };
176 Self::new(bytes, byte_order)
177 }
178
179 /// Creates a number from the bytes of a `usize` in `byte_order`, without the high zero
180 /// bytes (see [`new`](Self::new)).
181 ///
182 /// `usize` is as wide as a pointer, but as the high zero bytes are dropped, a value has
183 /// the same bytes on every target.
184 pub fn new_from_usize(value: usize, byte_order: ByteOrder) -> Self {
185 let bytes = match byte_order {
186 ByteOrder::BigEndian => value.to_be_bytes().to_vec(),
187 ByteOrder::LittleEndian => value.to_le_bytes().to_vec(),
188 };
189 Self::new(bytes, byte_order)
190 }
191
192 /// Creates a non-negative number from bytes given as `i8`s in `byte_order`, without the
193 /// high zero bytes (see [`new`](Self::new)).
194 ///
195 /// The `i8`s are only how the bytes are given, not signed digits: each one is the byte
196 /// with the same bits (`-1` is `0xFF`, `-128` is `0x80`), and the number is never
197 /// negative.
198 ///
199 /// # Examples
200 ///
201 /// ```
202 /// use a::math::numbers::{ByteOrder, Number};
203 ///
204 /// let n = Number::new_from_i8_vec(vec![0, -1, 1], ByteOrder::BigEndian);
205 /// assert_eq!(n.value, [0xFF, 0x01]);
206 /// assert!(!n.is_negative());
207 /// ```
208 pub fn new_from_i8_vec(value: Vec<i8>, byte_order: ByteOrder) -> Self {
209 Self::new(value.iter().map(|&x| x as u8).collect(), byte_order)
210 }
211
212 /// Creates a number from an `i8`: its sign, and its absolute value as the only byte.
213 /// `i8::MIN` becomes `[0x80]` with `negative` set. Zero is kept as `[0]`.
214 pub fn new_from_i8(value: i8, byte_order: ByteOrder) -> Self {
215 // `unsigned_abs` is exact for every value, `MIN` included, whose absolute value does
216 // not fit in the signed type; the same holds for the wider types below.
217 Self {
218 negative: value < 0,
219 ..Self::new_from_u8(value.unsigned_abs(), byte_order)
220 }
221 }
222
223 /// Creates a number from an `i16`: its sign, and the bytes of its absolute value in
224 /// `byte_order` without the high zero bytes (see [`new`](Self::new)).
225 ///
226 /// # Examples
227 ///
228 /// ```
229 /// use a::math::numbers::{ByteOrder, Number};
230 ///
231 /// let n = Number::new_from_i16(-2, ByteOrder::BigEndian);
232 /// assert_eq!(n.value, [0x02]);
233 /// assert!(n.is_negative());
234 ///
235 /// let n = Number::new_from_i16(i16::MIN, ByteOrder::BigEndian);
236 /// assert_eq!(n.value, [0x80, 0x00]);
237 /// assert!(n.is_negative());
238 /// ```
239 pub fn new_from_i16(value: i16, byte_order: ByteOrder) -> Self {
240 Self {
241 negative: value < 0,
242 ..Self::new_from_u16(value.unsigned_abs(), byte_order)
243 }
244 }
245
246 /// Creates a number from an `i32`: its sign, and the bytes of its absolute value in
247 /// `byte_order` without the high zero bytes (see [`new`](Self::new)).
248 pub fn new_from_i32(value: i32, byte_order: ByteOrder) -> Self {
249 Self {
250 negative: value < 0,
251 ..Self::new_from_u32(value.unsigned_abs(), byte_order)
252 }
253 }
254
255 /// Creates a number from an `i64`: its sign, and the bytes of its absolute value in
256 /// `byte_order` without the high zero bytes (see [`new`](Self::new)).
257 pub fn new_from_i64(value: i64, byte_order: ByteOrder) -> Self {
258 Self {
259 negative: value < 0,
260 ..Self::new_from_u64(value.unsigned_abs(), byte_order)
261 }
262 }
263
264 /// Creates a number from an `i128`: its sign, and the bytes of its absolute value in
265 /// `byte_order` without the high zero bytes (see [`new`](Self::new)).
266 pub fn new_from_i128(value: i128, byte_order: ByteOrder) -> Self {
267 Self {
268 negative: value < 0,
269 ..Self::new_from_u128(value.unsigned_abs(), byte_order)
270 }
271 }
272
273 /// Creates a number from an `isize`: its sign, and the bytes of its absolute value in
274 /// `byte_order` without the high zero bytes (see [`new`](Self::new)).
275 ///
276 /// As for [`new_from_usize`](Self::new_from_usize), a value has the same bytes on every
277 /// target.
278 pub fn new_from_isize(value: isize, byte_order: ByteOrder) -> Self {
279 Self {
280 negative: value < 0,
281 ..Self::new_from_usize(value.unsigned_abs(), byte_order)
282 }
283 }
284
285 /// Creates a non-negative number from the UTF-8 bytes of a string, read in `byte_order`,
286 /// without the high zero bytes (see [`new`](Self::new)).
287 ///
288 /// The string is not parsed as digits: its bytes are the number, the way textbook RSA
289 /// turns a message into an integer, so a leading `'-'` is the byte `0x2D`, not a sign.
290 /// In big-endian order the first byte of the string is the most significant one, and
291 /// leading `'\0'` characters are dropped as zero bytes; in little-endian order the first
292 /// byte is the least significant one, and trailing `'\0'` characters are dropped. An empty
293 /// string gives an empty `value`.
294 ///
295 /// # Examples
296 ///
297 /// ```
298 /// use a::math::numbers::{ByteOrder, Number};
299 ///
300 /// // 0x31_32_33 = 3,224,115, not 123.
301 /// let n = Number::new_from_str("123", ByteOrder::BigEndian);
302 /// assert_eq!(n.value, [0x31, 0x32, 0x33]);
303 /// ```
304 pub fn new_from_str(value: &str, byte_order: ByteOrder) -> Self {
305 Self::new(value.as_bytes().to_vec(), byte_order)
306 }
307
308 /// Returns whether the number is below zero.
309 ///
310 /// It reads `negative`, as the constructors and the operators keep it: never set for zero. A
311 /// number built directly from its fields is stored as given, and a zero magnitude with
312 /// `negative` set says it is negative here, though it is zero to the comparisons and the
313 /// arithmetic, and to [`is_zero`](Self::is_zero) and [`signum`](Self::signum).
314 ///
315 /// # Examples
316 ///
317 /// ```
318 /// use a::math::numbers::{ByteOrder, Number};
319 ///
320 /// assert!(Number::new_from_i32(-7, ByteOrder::BigEndian).is_negative());
321 /// assert!(!Number::new_from_i32(7, ByteOrder::BigEndian).is_negative());
322 /// assert!(!Number::new_from_i32(0, ByteOrder::BigEndian).is_negative());
323 /// ```
324 pub fn is_negative(&self) -> bool {
325 self.negative
326 }
327
328 /// Returns the order of the bytes in `value`.
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// use a::math::numbers::{ByteOrder, Number};
334 ///
335 /// let n = Number::new_from_u8(7, ByteOrder::LittleEndian);
336 /// assert!(n.byte_order() == ByteOrder::LittleEndian);
337 /// ```
338 pub fn byte_order(&self) -> ByteOrder {
339 self.byte_order
340 }
341}
342
343impl Clone for Number {
344 /// Returns a copy of the number, its bytes exactly as they are stored, high zero bytes
345 /// included, in a new vector of their length.
346 #[inline]
347 fn clone(&self) -> Self {
348 Number {
349 value: self.value.clone(),
350 negative: self.negative,
351 byte_order: self.byte_order,
352 }
353 }
354
355 /// Makes `self` a copy of `source`, in the vector of `self` when it has room.
356 #[inline]
357 fn clone_from(&mut self, source: &Self) {
358 self.value.clone_from(&source.value);
359 self.negative = source.negative;
360 self.byte_order = source.byte_order;
361 }
362}
363
364impl Default for Number {
365 /// Returns zero, little-endian, with an empty vector, which allocates nothing: `mem::take` of
366 /// a number leaves this behind. Little-endian is the order of the limbs of the arithmetic on
367 /// every target this crate has kernels for: the kernels read and write its bytes as limbs as
368 /// they are, where big-endian bytes are turned around.
369 ///
370 /// # Examples
371 ///
372 /// ```
373 /// use a::math::numbers::{ByteOrder, Number};
374 ///
375 /// let zero = Number::default();
376 /// assert!(zero.is_zero());
377 /// assert!(zero.byte_order() == ByteOrder::LittleEndian);
378 /// assert_eq!(zero.value.capacity(), 0);
379 /// ```
380 #[inline]
381 fn default() -> Self {
382 Number {
383 value: Vec::new(),
384 negative: false,
385 byte_order: ByteOrder::LittleEndian,
386 }
387 }
388}
389
390impl fmt::Debug for Number {
391 /// Writes the number in decimal, as [`Display`](fmt::Display) does, so that numbers that are
392 /// equal look alike; the bytes are in the public fields.
393 ///
394 /// # Examples
395 ///
396 /// ```
397 /// use a::math::numbers::{ByteOrder, Number};
398 ///
399 /// let n = Number::new_from_i32(-1000, ByteOrder::BigEndian);
400 /// assert_eq!(format!("{n:?}"), "-1000");
401 /// assert_eq!(format!("{:?}", [n]), "[-1000]");
402 /// ```
403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404 fmt::Display::fmt(self, f)
405 }
406}