bitcoin/util/
uint.rs

1// Rust Bitcoin Library
2// Written in 2014 by
3//     Andrew Poelstra <apoelstra@wpsoftware.net>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! Big unsigned integer types
16//!
17//! Implementation of a various large-but-fixed sized unsigned integer types.
18//! The functions here are designed to be fast.
19//!
20
21macro_rules! construct_uint {
22    ($name:ident, $n_words:expr) => (
23        /// Little-endian large integer type
24        #[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
25        pub struct $name(pub [u64; $n_words]);
26        impl_array_newtype!($name, u64, $n_words);
27
28        impl $name {
29            /// Conversion to u32
30            #[inline]
31            pub fn low_u32(&self) -> u32 {
32                let &$name(ref arr) = self;
33                arr[0] as u32
34            }
35
36            /// Conversion to u64
37            #[inline]
38            pub fn low_u64(&self) -> u64 {
39                let &$name(ref arr) = self;
40                arr[0] as u64
41            }
42
43
44            /// Return the least number of bits needed to represent the number
45            #[inline]
46            pub fn bits(&self) -> usize {
47                let &$name(ref arr) = self;
48                for i in 1..$n_words {
49                    if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; }
50                }
51                0x40 - arr[0].leading_zeros() as usize
52            }
53
54            /// Multiplication by u32
55            pub fn mul_u32(self, other: u32) -> $name {
56                let $name(ref arr) = self;
57                let mut carry = [0u64; $n_words];
58                let mut ret = [0u64; $n_words];
59                for i in 0..$n_words {
60                    let not_last_word = i < $n_words - 1;
61                    let upper = other as u64 * (arr[i] >> 32);
62                    let lower = other as u64 * (arr[i] & 0xFFFFFFFF);
63                    if not_last_word {
64                        carry[i + 1] += upper >> 32;
65                    }
66                    let (sum, overflow) = lower.overflowing_add(upper << 32);
67                    ret[i] = sum;
68                    if overflow && not_last_word {
69                        carry[i + 1] += 1;
70                    }
71                }
72                $name(ret) + $name(carry)
73            }
74
75            /// Create an object from a given unsigned 64-bit integer
76            #[inline]
77            pub fn from_u64(init: u64) -> Option<$name> {
78                let mut ret = [0; $n_words];
79                ret[0] = init;
80                Some($name(ret))
81            }
82
83            /// Create an object from a given signed 64-bit integer
84            #[inline]
85            pub fn from_i64(init: i64) -> Option<$name> {
86                if init >= 0 {
87                    $name::from_u64(init as u64)
88                } else {
89                    None
90                }
91            }
92
93            /// Creates big integer value from a byte slice array using
94            /// big-endian encoding
95            pub fn from_be_bytes(bytes: [u8; $n_words * 8]) -> $name {
96                use super::endian::slice_to_u64_be;
97                let mut slice = [0u64; $n_words];
98                slice.iter_mut()
99                    .rev()
100                    .zip(bytes.chunks(8))
101                    .for_each(|(word, bytes)| *word = slice_to_u64_be(bytes));
102                $name(slice)
103            }
104
105            // divmod like operation, returns (quotient, remainder)
106            #[inline]
107            fn div_rem(self, other: Self) -> (Self, Self) {
108                let mut sub_copy = self;
109                let mut shift_copy = other;
110                let mut ret = [0u64; $n_words];
111
112                let my_bits = self.bits();
113                let your_bits = other.bits();
114
115                // Check for division by 0
116                assert!(your_bits != 0);
117
118                // Early return in case we are dividing by a larger number than us
119                if my_bits < your_bits {
120                    return ($name(ret), sub_copy);
121                }
122
123                // Bitwise long division
124                let mut shift = my_bits - your_bits;
125                shift_copy = shift_copy << shift;
126                loop {
127                    if sub_copy >= shift_copy {
128                        ret[shift / 64] |= 1 << (shift % 64);
129                        sub_copy = sub_copy - shift_copy;
130                    }
131                    shift_copy = shift_copy >> 1;
132                    if shift == 0 {
133                        break;
134                    }
135                    shift -= 1;
136                }
137
138                ($name(ret), sub_copy)
139            }
140        }
141
142        impl PartialOrd for $name {
143            #[inline]
144            fn partial_cmp(&self, other: &$name) -> Option<::std::cmp::Ordering> {
145                Some(self.cmp(&other))
146            }
147        }
148
149        impl Ord for $name {
150            #[inline]
151            fn cmp(&self, other: &$name) -> ::std::cmp::Ordering {
152                // We need to manually implement ordering because we use little-endian
153                // and the auto derive is a lexicographic ordering(i.e. memcmp)
154                // which with numbers is equivilant to big-endian
155                for i in 0..$n_words {
156                    if self[$n_words - 1 - i] < other[$n_words - 1 - i] { return ::std::cmp::Ordering::Less; }
157                    if self[$n_words - 1 - i] > other[$n_words - 1 - i] { return ::std::cmp::Ordering::Greater; }
158                }
159                ::std::cmp::Ordering::Equal
160            }
161        }
162
163        impl ::std::ops::Add<$name> for $name {
164            type Output = $name;
165
166            fn add(self, other: $name) -> $name {
167                let $name(ref me) = self;
168                let $name(ref you) = other;
169                let mut ret = [0u64; $n_words];
170                let mut carry = [0u64; $n_words];
171                let mut b_carry = false;
172                for i in 0..$n_words {
173                    ret[i] = me[i].wrapping_add(you[i]);
174                    if i < $n_words - 1 && ret[i] < me[i] {
175                        carry[i + 1] = 1;
176                        b_carry = true;
177                    }
178                }
179                if b_carry { $name(ret) + $name(carry) } else { $name(ret) }
180            }
181        }
182
183        impl ::std::ops::Sub<$name> for $name {
184            type Output = $name;
185
186            #[inline]
187            fn sub(self, other: $name) -> $name {
188                self + !other + $crate::util::BitArray::one()
189            }
190        }
191
192        impl ::std::ops::Mul<$name> for $name {
193            type Output = $name;
194
195            fn mul(self, other: $name) -> $name {
196                use $crate::util::BitArray;
197                let mut me = $name::zero();
198                // TODO: be more efficient about this
199                for i in 0..(2 * $n_words) {
200                    let to_mul = (other >> (32 * i)).low_u32();
201                    me = me + (self.mul_u32(to_mul) << (32 * i));
202                }
203                me
204            }
205        }
206
207        impl ::std::ops::Div<$name> for $name {
208            type Output = $name;
209
210            fn div(self, other: $name) -> $name {
211                self.div_rem(other).0
212            }
213        }
214
215        impl ::std::ops::Rem<$name> for $name {
216            type Output = $name;
217
218            fn rem(self, other: $name) -> $name {
219                self.div_rem(other).1
220            }
221        }
222
223        impl $crate::util::BitArray for $name {
224            #[inline]
225            fn bit(&self, index: usize) -> bool {
226                let &$name(ref arr) = self;
227                arr[index / 64] & (1 << (index % 64)) != 0
228            }
229
230            #[inline]
231            fn bit_slice(&self, start: usize, end: usize) -> $name {
232                (*self >> start).mask(end - start)
233            }
234
235            #[inline]
236            fn mask(&self, n: usize) -> $name {
237                let &$name(ref arr) = self;
238                let mut ret = [0; $n_words];
239                for i in 0..$n_words {
240                    if n >= 0x40 * (i + 1) {
241                        ret[i] = arr[i];
242                    } else {
243                        ret[i] = arr[i] & ((1 << (n - 0x40 * i)) - 1);
244                        break;
245                    }
246                }
247                $name(ret)
248            }
249
250            #[inline]
251            fn trailing_zeros(&self) -> usize {
252                let &$name(ref arr) = self;
253                for i in 0..($n_words - 1) {
254                    if arr[i] > 0 { return (0x40 * i) + arr[i].trailing_zeros() as usize; }
255                }
256                (0x40 * ($n_words - 1)) + arr[$n_words - 1].trailing_zeros() as usize
257            }
258
259            fn zero() -> $name { Default::default() }
260            fn one() -> $name {
261                $name({ let mut ret = [0; $n_words]; ret[0] = 1; ret })
262            }
263        }
264
265        impl ::std::ops::BitAnd<$name> for $name {
266            type Output = $name;
267
268            #[inline]
269            fn bitand(self, other: $name) -> $name {
270                let $name(ref arr1) = self;
271                let $name(ref arr2) = other;
272                let mut ret = [0u64; $n_words];
273                for i in 0..$n_words {
274                    ret[i] = arr1[i] & arr2[i];
275                }
276                $name(ret)
277            }
278        }
279
280        impl ::std::ops::BitXor<$name> for $name {
281            type Output = $name;
282
283            #[inline]
284            fn bitxor(self, other: $name) -> $name {
285                let $name(ref arr1) = self;
286                let $name(ref arr2) = other;
287                let mut ret = [0u64; $n_words];
288                for i in 0..$n_words {
289                    ret[i] = arr1[i] ^ arr2[i];
290                }
291                $name(ret)
292            }
293        }
294
295        impl ::std::ops::BitOr<$name> for $name {
296            type Output = $name;
297
298            #[inline]
299            fn bitor(self, other: $name) -> $name {
300                let $name(ref arr1) = self;
301                let $name(ref arr2) = other;
302                let mut ret = [0u64; $n_words];
303                for i in 0..$n_words {
304                    ret[i] = arr1[i] | arr2[i];
305                }
306                $name(ret)
307            }
308        }
309
310        impl ::std::ops::Not for $name {
311            type Output = $name;
312
313            #[inline]
314            fn not(self) -> $name {
315                let $name(ref arr) = self;
316                let mut ret = [0u64; $n_words];
317                for i in 0..$n_words {
318                    ret[i] = !arr[i];
319                }
320                $name(ret)
321            }
322        }
323
324        impl ::std::ops::Shl<usize> for $name {
325            type Output = $name;
326
327            fn shl(self, shift: usize) -> $name {
328                let $name(ref original) = self;
329                let mut ret = [0u64; $n_words];
330                let word_shift = shift / 64;
331                let bit_shift = shift % 64;
332                for i in 0..$n_words {
333                    // Shift
334                    if bit_shift < 64 && i + word_shift < $n_words {
335                        ret[i + word_shift] += original[i] << bit_shift;
336                    }
337                    // Carry
338                    if bit_shift > 0 && i + word_shift + 1 < $n_words {
339                        ret[i + word_shift + 1] += original[i] >> (64 - bit_shift);
340                    }
341                }
342                $name(ret)
343            }
344        }
345
346        impl ::std::ops::Shr<usize> for $name {
347            type Output = $name;
348
349            fn shr(self, shift: usize) -> $name {
350                let $name(ref original) = self;
351                let mut ret = [0u64; $n_words];
352                let word_shift = shift / 64;
353                let bit_shift = shift % 64;
354                for i in word_shift..$n_words {
355                    // Shift
356                    ret[i - word_shift] += original[i] >> bit_shift;
357                    // Carry
358                    if bit_shift > 0 && i < $n_words - 1 {
359                        ret[i - word_shift] += original[i + 1] << (64 - bit_shift);
360                    }
361                }
362                $name(ret)
363            }
364        }
365
366        impl ::std::fmt::Debug for $name {
367            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
368                let &$name(ref data) = self;
369                write!(f, "0x")?;
370                for ch in data.iter().rev() {
371                    write!(f, "{:016x}", ch)?;
372                }
373                Ok(())
374            }
375        }
376
377        display_from_debug!($name);
378
379        impl $crate::consensus::Encodable for $name {
380            #[inline]
381            fn consensus_encode<S: ::std::io::Write>(
382                &self,
383                mut s: S,
384            ) -> Result<usize, ::std::io::Error> {
385                let &$name(ref data) = self;
386                let mut len = 0;
387                for word in data.iter() {
388                    len += word.consensus_encode(&mut s)?;
389                }
390                Ok(len)
391            }
392        }
393
394        impl $crate::consensus::Decodable for $name {
395            fn consensus_decode<D: ::std::io::Read>(
396                mut d: D,
397            ) -> Result<$name, $crate::consensus::encode::Error> {
398                use $crate::consensus::Decodable;
399                let mut ret: [u64; $n_words] = [0; $n_words];
400                for i in 0..$n_words {
401                    ret[i] = Decodable::consensus_decode(&mut d)?;
402                }
403                Ok($name(ret))
404            }
405        }
406    );
407}
408
409construct_uint!(Uint256, 4);
410construct_uint!(Uint128, 2);
411
412impl Uint256 {
413    /// Increment by 1
414    #[inline]
415    pub fn increment(&mut self) {
416        let &mut Uint256(ref mut arr) = self;
417        arr[0] += 1;
418        if arr[0] == 0 {
419            arr[1] += 1;
420            if arr[1] == 0 {
421                arr[2] += 1;
422                if arr[2] == 0 {
423                    arr[3] += 1;
424                }
425            }
426        }
427    }
428
429    /// Decay to a uint128
430    #[inline]
431    pub fn low_128(&self) -> Uint128 {
432        let &Uint256(data) = self;
433        Uint128([data[0], data[1]])
434    }
435}
436
437#[cfg(test)]
438mod tests {
439    use consensus::{deserialize, serialize};
440    use util::uint::{Uint256, Uint128};
441    use util::BitArray;
442
443    #[test]
444    pub fn uint256_bits_test() {
445        assert_eq!(Uint256::from_u64(255).unwrap().bits(), 8);
446        assert_eq!(Uint256::from_u64(256).unwrap().bits(), 9);
447        assert_eq!(Uint256::from_u64(300).unwrap().bits(), 9);
448        assert_eq!(Uint256::from_u64(60000).unwrap().bits(), 16);
449        assert_eq!(Uint256::from_u64(70000).unwrap().bits(), 17);
450
451        // Try to read the following lines out loud quickly
452        let mut shl = Uint256::from_u64(70000).unwrap();
453        shl = shl << 100;
454        assert_eq!(shl.bits(), 117);
455        shl = shl << 100;
456        assert_eq!(shl.bits(), 217);
457        shl = shl << 100;
458        assert_eq!(shl.bits(), 0);
459
460        // Bit set check
461        assert!(!Uint256::from_u64(10).unwrap().bit(0));
462        assert!(Uint256::from_u64(10).unwrap().bit(1));
463        assert!(!Uint256::from_u64(10).unwrap().bit(2));
464        assert!(Uint256::from_u64(10).unwrap().bit(3));
465        assert!(!Uint256::from_u64(10).unwrap().bit(4));
466    }
467
468    #[test]
469    pub fn uint256_display_test() {
470        assert_eq!(format!("{}", Uint256::from_u64(0xDEADBEEF).unwrap()),
471                   "0x00000000000000000000000000000000000000000000000000000000deadbeef");
472        assert_eq!(format!("{}", Uint256::from_u64(u64::max_value()).unwrap()),
473                   "0x000000000000000000000000000000000000000000000000ffffffffffffffff");
474
475        let max_val = Uint256([0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
476                               0xFFFFFFFFFFFFFFFF]);
477        assert_eq!(format!("{}", max_val),
478                   "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
479    }
480
481    #[test]
482    pub fn uint256_comp_test() {
483        let small = Uint256([10u64, 0, 0, 0]);
484        let big = Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]);
485        let bigger = Uint256([0x9C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]);
486        let biggest = Uint256([0x5C8C3EE70C644118u64, 0x0209E7378231E632, 0, 1]);
487
488        assert!(small < big);
489        assert!(big < bigger);
490        assert!(bigger < biggest);
491        assert!(bigger <= biggest);
492        assert!(biggest <= biggest);
493        assert!(bigger >= big);
494        assert!(bigger >= small);
495        assert!(small <= small);
496    }
497
498    #[test]
499    pub fn uint_from_be_bytes() {
500        assert_eq!(Uint128::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed]),
501                   Uint128([0xdeafbabe2bedfeed, 0x1badcafedeadbeef]));
502
503        assert_eq!(Uint256::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed,
504                                           0xba, 0xad, 0xf0, 0x0d, 0xde, 0xfa, 0xce, 0xda, 0x11, 0xfe, 0xd2, 0xba, 0xd1, 0xc0, 0xff, 0xe0]),
505                   Uint256([0x11fed2bad1c0ffe0, 0xbaadf00ddefaceda, 0xdeafbabe2bedfeed, 0x1badcafedeadbeef]));
506    }
507
508    #[test]
509    pub fn uint256_arithmetic_test() {
510        let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap();
511        let copy = init;
512
513        let add = init + copy;
514        assert_eq!(add, Uint256([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0]));
515        // Bitshifts
516        let shl = add << 88;
517        assert_eq!(shl, Uint256([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0]));
518        let shr = shl >> 40;
519        assert_eq!(shr, Uint256([0x7DDE000000000000u64, 0x0001BD5B7DDFBD5B, 0, 0]));
520        // Increment
521        let mut incr = shr;
522        incr.increment();
523        assert_eq!(incr, Uint256([0x7DDE000000000001u64, 0x0001BD5B7DDFBD5B, 0, 0]));
524        // Subtraction
525        let sub = incr - init;
526        assert_eq!(sub, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0]));
527        // Multiplication
528        let mult = sub.mul_u32(300);
529        assert_eq!(mult, Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]));
530        // Division
531        assert_eq!(Uint256::from_u64(105).unwrap() /
532                   Uint256::from_u64(5).unwrap(),
533                   Uint256::from_u64(21).unwrap());
534        let div = mult / Uint256::from_u64(300).unwrap();
535        assert_eq!(div, Uint256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0]));
536
537        assert_eq!(Uint256::from_u64(105).unwrap() % Uint256::from_u64(5).unwrap(),
538                   Uint256::from_u64(0).unwrap());
539        assert_eq!(Uint256::from_u64(35498456).unwrap() % Uint256::from_u64(3435).unwrap(),
540                   Uint256::from_u64(1166).unwrap());
541        let rem_src = mult * Uint256::from_u64(39842).unwrap() + Uint256::from_u64(9054).unwrap();
542        assert_eq!(rem_src % Uint256::from_u64(39842).unwrap(),
543                   Uint256::from_u64(9054).unwrap());
544        // TODO: bit inversion
545    }
546
547    #[test]
548    pub fn mul_u32_test() {
549        let u64_val = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap();
550
551        let u96_res = u64_val.mul_u32(0xFFFFFFFF);
552        let u128_res = u96_res.mul_u32(0xFFFFFFFF);
553        let u160_res = u128_res.mul_u32(0xFFFFFFFF);
554        let u192_res = u160_res.mul_u32(0xFFFFFFFF);
555        let u224_res = u192_res.mul_u32(0xFFFFFFFF);
556        let u256_res = u224_res.mul_u32(0xFFFFFFFF);
557
558        assert_eq!(u96_res, Uint256([0xffffffff21524111u64, 0xDEADBEEE, 0, 0]));
559        assert_eq!(u128_res, Uint256([0x21524111DEADBEEFu64, 0xDEADBEEE21524110, 0, 0]));
560        assert_eq!(u160_res, Uint256([0xBD5B7DDD21524111u64, 0x42A4822200000001, 0xDEADBEED, 0]));
561        assert_eq!(u192_res, Uint256([0x63F6C333DEADBEEFu64, 0xBD5B7DDFBD5B7DDB, 0xDEADBEEC63F6C334, 0]));
562        assert_eq!(u224_res, Uint256([0x7AB6FBBB21524111u64, 0xFFFFFFFBA69B4558, 0x854904485964BAAA, 0xDEADBEEB]));
563        assert_eq!(u256_res, Uint256([0xA69B4555DEADBEEFu64, 0xA69B455CD41BB662, 0xD41BB662A69B4550, 0xDEADBEEAA69B455C]));
564    }
565
566    #[test]
567    pub fn multiplication_test() {
568        let u64_val = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap();
569
570        let u128_res = u64_val * u64_val;
571
572        assert_eq!(u128_res, Uint256([0x048D1354216DA321u64, 0xC1B1CD13A4D13D46, 0, 0]));
573
574        let u256_res = u128_res * u128_res;
575
576        assert_eq!(u256_res, Uint256([0xF4E166AAD40D0A41u64, 0xF5CF7F3618C2C886u64,
577                                      0x4AFCFF6F0375C608u64, 0x928D92B4D7F5DF33u64]));
578    }
579
580    #[test]
581    pub fn uint256_bitslice_test() {
582        let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap();
583        let add = init + (init << 64);
584        assert_eq!(add.bit_slice(64, 128), init);
585        assert_eq!(add.mask(64), init);
586    }
587
588    #[test]
589    pub fn uint256_extreme_bitshift_test() {
590        // Shifting a u64 by 64 bits gives an undefined value, so make sure that
591        // we're doing the Right Thing here
592        let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap();
593
594        assert_eq!(init << 64, Uint256([0, 0xDEADBEEFDEADBEEF, 0, 0]));
595        let add = (init << 64) + init;
596        assert_eq!(add, Uint256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0]));
597        assert_eq!(add >> 0, Uint256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0]));
598        assert_eq!(add << 0, Uint256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0]));
599        assert_eq!(add >> 64, Uint256([0xDEADBEEFDEADBEEF, 0, 0, 0]));
600        assert_eq!(add << 64, Uint256([0, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0]));
601    }
602
603    #[test]
604    pub fn uint256_serialize_test() {
605        let start1 = Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]);
606        let start2 = Uint256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0xABCD, 0xFFFF]);
607        let serial1 = serialize(&start1);
608        let serial2 = serialize(&start2);
609        let end1: Result<Uint256, _> = deserialize(&serial1);
610        let end2: Result<Uint256, _> = deserialize(&serial2);
611
612        assert_eq!(end1.ok(), Some(start1));
613        assert_eq!(end2.ok(), Some(start2));
614    }
615}