ff_uint/uint/
mod.rs

1#[macro_use]
2pub(crate) mod macros;
3pub(crate) mod traits;
4
5#[macro_export]
6macro_rules! construct_uint {
7	($(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt );) => {
8		$crate::concat_idents!(wrapped_mod = wrapped_mod, _, $name {
9			$visibility use wrapped_mod::$name;
10			mod wrapped_mod {
11				use $crate::unroll;
12				use $crate::Uint;
13				#[cfg(feature = "borsh_support")]
14				use $crate::borsh::{BorshSerialize, BorshDeserialize};
15				#[cfg(feature = "scale_support")]
16				use $crate::parity_scale_codec_derive::{Encode, Decode};
17				#[cfg(feature = "scale_support")]
18				use $crate::scale_info::TypeInfo;
19				use $crate::maybestd::{vec, vec::Vec};
20
21				#[repr(C)]
22				$(#[$attr])*
23				#[derive(Copy, Clone, Default, Debug)]
24				#[cfg_attr(feature = "borsh_support", derive(BorshSerialize, BorshDeserialize))]
25				#[cfg_attr(feature = "scale_support", derive(Encode, Decode, TypeInfo))]
26				pub struct $name (pub [u64; $n_words]);
27
28				#[inline]
29				const fn uint_from_u64(v:u64) -> $name {
30					let mut ret = [0;$n_words];
31					ret[0]=v;
32					$name(ret)
33				}
34
35				impl $name {
36					const WORD_BITS:usize = 64;
37					const NUM_WORDS : usize = $n_words;
38
39					const MAX : Self = Self([u64::max_value(); $n_words]);
40					const ZERO : Self = Self([0u64; $n_words]);
41					const ONE : Self = uint_from_u64(1);
42
43					#[inline]
44					pub const fn new(v:[u64; $n_words]) -> Self {
45						Self(v)
46					}
47
48					// Whether this fits u64.
49					#[inline]
50					fn fits_word(&self) -> bool {
51						let &$name(ref arr) = self;
52						for i in 1..$n_words { if arr[i] != 0 { return false; } }
53						return true;
54					}
55
56
57					#[inline]
58					fn full_shl(self, shift: u32) -> [u64; $n_words + 1] {
59						debug_assert!(shift < Self::WORD_BITS as u32);
60						let mut u = [064; $n_words + 1];
61						let u_lo = self.0[0] << shift;
62						let u_hi = self.overflowing_shr(Self::WORD_BITS as u32 - shift).0;
63						u[0] = u_lo;
64						u[1..].copy_from_slice(&u_hi.0[..]);
65						u
66					}
67
68					#[inline]
69					fn full_shr(u: [u64; $n_words + 1], shift: u32) -> Self {
70						debug_assert!(shift < Self::WORD_BITS as u32);
71						let mut res = Self::ZERO;
72						for i in 0..$n_words {
73							res.0[i] = u[i] >> shift;
74						}
75						// carry
76						if shift > 0 {
77							for i in 1..=$n_words {
78								res.0[i - 1] |= u[i] << (Self::WORD_BITS as u32 - shift);
79							}
80						}
81						res
82					}
83
84					#[inline]
85					fn full_mul_u64(self, by: u64) -> [u64; $n_words + 1] {
86						let (prod, carry) = self.overflowing_mul_u64(by);
87						let mut res = [0u64; $n_words + 1];
88						res[..$n_words].copy_from_slice(&prod.0[..]);
89						res[$n_words] = carry;
90						res
91					}
92
93					#[inline]
94					fn div_mod_small(mut self, other: u64) -> (Self, Self) {
95						let mut rem = 0u64;
96						self.0.iter_mut().rev().for_each(|d| {
97							let (q, r) = Self::div_mod_word(rem, *d, other);
98							*d = q;
99							rem = r;
100						});
101						(self, Self::from_u64(rem))
102					}
103
104					// See Knuth, TAOCP, Volume 2, section 4.3.1, Algorithm D.
105					#[inline]
106					fn div_mod_knuth(self, mut v: Self, n: usize, m: usize) -> (Self, Self) {
107						debug_assert!(self.bits() >= v.bits() && !v.fits_word());
108						debug_assert!(n + m <= $n_words);
109						// D1.
110						// Make sure 64th bit in v's highest word is set.
111						// If we shift both self and v, it won't affect the quotient
112						// and the remainder will only need to be shifted back.
113						let shift = v.0[n - 1].leading_zeros();
114						v = v.overflowing_shl(shift).0;
115						// u will store the remainder (shifted)
116						let mut u = self.full_shl(shift);
117
118						// quotient
119						let mut q = Self::ZERO;
120						let v_n_1 = v.0[n - 1];
121						let v_n_2 = v.0[n - 2];
122
123						// D2. D7.
124						// iterate from m downto 0
125						for j in (0..=m).rev() {
126							let u_jn = u[j + n];
127
128							// D3.
129							// q_hat is our guess for the j-th quotient digit
130							// q_hat = min(b - 1, (u_{j+n} * b + u_{j+n-1}) / v_{n-1})
131							// b = 1 << WORD_BITS
132							// Theorem B: q_hat >= q_j >= q_hat - 2
133							let mut q_hat = if u_jn < v_n_1 {
134								let (mut q_hat, mut r_hat) = Self::div_mod_word(u_jn, u[j + n - 1], v_n_1);
135								// this loop takes at most 2 iterations
136								loop {
137									// check if q_hat * v_{n-2} > b * r_hat + u_{j+n-2}
138									let (hi, lo) = Self::split_u128(u128::from(q_hat) * u128::from(v_n_2));
139									if (hi, lo) <= (r_hat, u[j + n - 2]) {
140										break;
141									}
142									// then iterate till it doesn't hold
143									q_hat -= 1;
144									let (new_r_hat, overflow) = r_hat.overflowing_add(v_n_1);
145									r_hat = new_r_hat;
146									// if r_hat overflowed, we're done
147									if overflow {
148										break;
149									}
150								}
151								q_hat
152							} else {
153								// here q_hat >= q_j >= q_hat - 1
154								u64::max_value()
155							};
156
157							// ex. 20:
158							// since q_hat * v_{n-2} <= b * r_hat + u_{j+n-2},
159							// either q_hat == q_j, or q_hat == q_j + 1
160
161							// D4.
162							// let's assume optimistically q_hat == q_j
163							// subtract (q_hat * v) from u[j..]
164							let q_hat_v = v.full_mul_u64(q_hat);
165							// u[j..] -= q_hat_v;
166							let c = Self::sub_slice(&mut u[j..], &q_hat_v[..n + 1]);
167
168							// D6.
169							// actually, q_hat == q_j + 1 and u[j..] has overflowed
170							// highly unlikely ~ (1 / 2^63)
171							if c {
172								q_hat -= 1;
173								// add v to u[j..]
174								let c = Self::add_slice(&mut u[j..], &v.0[..n]);
175								u[j + n] = u[j + n].wrapping_add(u64::from(c));
176							}
177
178							// D5.
179							q.0[j] = q_hat;
180						}
181
182						// D8.
183						let remainder = Self::full_shr(u, shift);
184
185						(q, remainder)
186					}
187
188					// Returns the least number of words needed to represent the nonzero number
189					#[inline]
190					fn words(bits: usize) -> usize {
191						debug_assert!(bits > 0);
192						(bits + Self::WORD_BITS - 1) / Self::WORD_BITS
193					}
194
195					#[inline(always)]
196					fn div_mod_word(hi: u64, lo: u64, y: u64) -> (u64, u64) {
197						debug_assert!(hi < y);
198						// NOTE: this is slow (__udivti3)
199						// let x = (u128::from(hi) << 64) + u128::from(lo);
200						// let d = u128::from(d);
201						// ((x / d) as u64, (x % d) as u64)
202						// TODO: look at https://gmplib.org/~tege/division-paper.pdf
203						const TWO32: u64 = 1 << 32;
204						let s = y.leading_zeros();
205						let y = y << s;
206						let (yn1, yn0) = Self::split(y);
207						let un32 = (hi << s) | lo.checked_shr(64 - s).unwrap_or(0);
208						let un10 = lo << s;
209						let (un1, un0) = Self::split(un10);
210						let mut q1 = un32.wrapping_div(yn1);
211						let mut rhat = un32 - q1 * yn1;
212
213						while q1 >= TWO32 || q1 * yn0 > TWO32 * rhat + un1 {
214							q1 -= 1;
215							rhat += yn1;
216							if rhat >= TWO32 {
217								break;
218							}
219						}
220
221						let un21 = un32.wrapping_mul(TWO32).wrapping_add(un1).wrapping_sub(q1.wrapping_mul(y));
222						let mut q0 = un21.wrapping_div(yn1);
223						rhat = un21.wrapping_sub(q0.wrapping_mul(yn1));
224
225						while q0 >= TWO32 || q0 * yn0 > TWO32 * rhat + un0 {
226							q0 -= 1;
227							rhat += yn1;
228							if rhat >= TWO32 {
229								break;
230							}
231						}
232
233						let rem = un21.wrapping_mul(TWO32).wrapping_add(un0).wrapping_sub(y.wrapping_mul(q0));
234						(q1 * TWO32 + q0, rem >> s)
235					}
236
237					#[inline]
238					fn add_slice(a: &mut [u64], b: &[u64]) -> bool {
239						Self::binop_slice(a, b, u64::overflowing_add)
240					}
241
242					#[inline]
243					fn sub_slice(a: &mut [u64], b: &[u64]) -> bool {
244						Self::binop_slice(a, b, u64::overflowing_sub)
245					}
246
247					#[inline]
248					fn binop_slice(a: &mut [u64], b: &[u64], binop: impl Fn(u64, u64) -> (u64, bool) + Copy) -> bool {
249						let mut c = false;
250						a.iter_mut().zip(b.iter()).for_each(|(x, y)| {
251							let (res, carry) = Self::binop_carry(*x, *y, c, binop);
252							*x = res;
253							c = carry;
254						});
255						c
256					}
257
258					#[inline]
259					fn binop_carry(a: u64, b: u64, c: bool, binop: impl Fn(u64, u64) -> (u64, bool)) -> (u64, bool) {
260						let (res1, overflow1) = b.overflowing_add(u64::from(c));
261						let (res2, overflow2) = binop(a, res1);
262						(res2, overflow1 || overflow2)
263					}
264
265					#[inline]
266					const fn mul_u64(a: u64, b: u64, carry: u64) -> (u64, u64) {
267						let (hi, lo) = Self::split_u128(a as u128 * b as u128 + carry as u128);
268						(lo, hi)
269					}
270
271					#[inline]
272					const fn split(a: u64) -> (u64, u64) {
273						(a >> 32, a & 0xFFFF_FFFF)
274					}
275
276					#[inline]
277					const fn split_u128(a: u128) -> (u64, u64) {
278						((a >> 64) as _, (a & 0xFFFFFFFFFFFFFFFF) as _)
279					}
280
281				}
282
283				$crate::impl_map_from!($name, bool, u64);
284				$crate::impl_map_from!($name, u8, u64);
285				$crate::impl_map_from!($name, u16, u64);
286				$crate::impl_map_from!($name, u32, u64);
287				$crate::impl_map_from!($name, usize, u64);
288				$crate::impl_map_from!($name, i8, i64);
289				$crate::impl_map_from!($name, i16, i64);
290				$crate::impl_map_from!($name, i32, i64);
291				$crate::impl_map_from!($name, isize, i64);
292
293
294				impl core::convert::TryFrom<$name> for bool {
295					type Error = &'static str;
296
297					#[inline]
298					fn try_from(u: $name) -> core::result::Result<bool, &'static str> {
299						let $name(arr) = u;
300						if !u.fits_word() || arr[0] > 2 {
301							Err("integer overflow when casting to bool",)
302						} else {
303							Ok(arr[0] == 1)
304						}
305					}
306				}
307
308				$crate::impl_try_from_for_primitive!($name, u8);
309				$crate::impl_try_from_for_primitive!($name, u16);
310				$crate::impl_try_from_for_primitive!($name, u32);
311				$crate::impl_try_from_for_primitive!($name, usize);
312				$crate::impl_try_from_for_primitive!($name, u64);
313				$crate::impl_try_from_for_primitive!($name, i8);
314				$crate::impl_try_from_for_primitive!($name, i16);
315				$crate::impl_try_from_for_primitive!($name, i32);
316				$crate::impl_try_from_for_primitive!($name, isize);
317				$crate::impl_try_from_for_primitive!($name, i64);
318
319
320
321				$crate::impl_typecast_128!($name, $n_words);
322
323				impl core::cmp::Ord for $name {
324					#[inline]
325					fn cmp(&self, other: &$name) -> core::cmp::Ordering {
326						self.wrapping_cmp(other)
327					}
328				}
329
330				impl core::cmp::PartialOrd for $name {
331					#[inline]
332					fn partial_cmp(&self, other: &$name) -> Option<core::cmp::Ordering> {
333						Some(self.cmp(other))
334					}
335				}
336
337				impl core::cmp::PartialEq for $name {
338					#[inline]
339					fn eq(&self, other: &$name) -> bool {
340						let &$name(ref a) = self;
341						let &$name(ref b) = other;
342						unroll!{
343							for i in 0 .. $n_words {
344								if a[i] != b[i] { return false; }
345							}
346						}
347						true
348					}
349				}
350
351				impl core::cmp::Eq for $name {}
352
353				impl core::hash::Hash for $name {
354					fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
355						self.as_inner().as_ref().hash(state);
356					}
357				}
358
359                #[cfg(feature = "rand_support")]
360				impl $crate::rand::distributions::Distribution<$name> for $crate::rand::distributions::Standard {
361					#[inline]
362					fn sample<R: $crate::rand::Rng + ?Sized>(&self, rng: &mut R) -> $name {
363						$name(rng.gen())
364					}
365				}
366
367				impl core::str::FromStr for $name {
368					type Err = &'static str;
369
370					fn from_str(value: &str) -> core::result::Result<$name, Self::Err> {
371						if !value.bytes().all(|b| b >= 48 && b <= 57) {
372							return Err("Invalid character")
373						}
374
375						let mut res = Self::default();
376						for b in value.bytes().map(|b| b - 48) {
377							let (r, overflow) = res.overflowing_mul_u64(10);
378							if overflow > 0 {
379								return Err("Invalid length");
380							}
381							let (r, overflow) = r.overflowing_add(uint_from_u64(b as u64));
382							if overflow {
383								return Err("Invalid length");
384							}
385							res = r;
386						}
387						Ok(res)
388					}
389				}
390
391				impl core::convert::From<&'static str> for $name {
392					fn from(s: &'static str) -> Self {
393						s.parse().unwrap()
394					}
395				}
396
397				impl core::convert::From<u64> for $name {
398					fn from(value: u64) -> $name {
399						let mut ret = [0; $n_words];
400						ret[0] = value;
401						$name(ret)
402					}
403				}
404
405				impl core::convert::From<i64> for $name {
406					fn from(value: i64) -> $name {
407						match value >= 0 {
408							true => From::from(value as u64),
409							false => { panic!("Unsigned integer can't be created from negative value"); }
410						}
411					}
412				}
413
414				impl core::fmt::Display for $name {
415					fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
416						if self.is_zero() {
417							return core::write!(f, "0");
418						}
419
420						let mut buf = [0_u8; $n_words * 20];
421						let mut i = buf.len() - 1;
422						let mut current = *self;
423						let ten = $name::from(10);
424
425						loop {
426							let rem = current.div_mod(ten).1;
427							let digit = rem.low_u64() as u8;
428							buf[i] = digit + b'0';
429							current = current.div_mod(ten).0;
430							if current.is_zero() {
431								break;
432							}
433							i -= 1;
434						}
435
436						// sequence of `'0'..'9'` chars is guaranteed to be a valid UTF8 string
437						let s = unsafe {
438							core::str::from_utf8_unchecked(&buf[i..])
439						};
440						f.write_str(s)
441					}
442				}
443
444				impl Uint for $name {
445					type Inner = [u64; $n_words];
446
447					const MAX : Self = Self::MAX;
448					const ZERO : Self = Self::ZERO;
449					const ONE : Self = Self::ONE;
450
451					const NUM_WORDS : usize = Self::NUM_WORDS;
452					const WORD_BITS : usize = Self::WORD_BITS;
453
454                    #[cfg(feature = "rand_support")]
455					#[inline]
456					fn random<R: $crate::rand::Rng + ?Sized>(rng: &mut R) -> Self {
457						rng.gen()
458					}
459
460					#[inline]
461					fn into_inner(self) -> Self::Inner {
462						self.0
463					}
464
465					#[inline]
466					fn as_inner(&self) -> &Self::Inner {
467						let &Self(ref res) = self;
468						res
469					}
470
471					#[inline]
472					fn as_inner_mut(&mut self) -> &mut Self::Inner {
473						let &mut Self(ref mut res) = self;
474						res
475					}
476
477					#[inline]
478					fn as_u64(&self) -> u64 {
479						if !self.fits_word() {
480							panic!("Integer overflow when casting to u64")
481						} else {
482							self.low_u64()
483						}
484					}
485
486					#[inline]
487					fn low_u64(&self) -> u64 {
488						self.0[0]
489					}
490
491					#[inline]
492					fn from_u64(v:u64) -> Self {
493						uint_from_u64(v)
494					}
495
496					/// Whether this is zero.
497					#[inline]
498					fn is_zero(&self) -> bool {
499						let &Self(ref arr) = self;
500						for i in 0..$n_words { if arr[i] != 0 { return false; } }
501						return true;
502					}
503
504					/// Returns the number of leading zeros in the binary representation of self.
505					#[inline]
506					fn leading_zeros(&self) -> u32 {
507						let mut r = 0;
508						for i in 0..$n_words {
509							let w = self.0[$n_words - i - 1];
510							if w == 0 {
511								r += 64;
512							} else {
513								r += w.leading_zeros();
514								break;
515							}
516						}
517						r
518					}
519
520					/// Returns the number of leading zeros in the binary representation of self.
521					#[inline]
522					fn trailing_zeros(&self) -> u32 {
523						let mut r = 0;
524						for i in 0..$n_words {
525							let w = self.0[i];
526							if w == 0 {
527								r += 64;
528							} else {
529								r += w.trailing_zeros();
530								break;
531							}
532						}
533						r
534					}
535
536					#[inline]
537					fn bits(&self) -> usize {
538						let &Self(ref arr) = self;
539						for i in 1..$n_words {
540							if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; }
541						}
542						0x40 - arr[0].leading_zeros() as usize
543					}
544
545
546					/// Returns a pair `(self / other, self % other)`.
547					///
548					/// # Panics
549					///
550					/// Panics if `other` is zero.
551					#[inline]
552					fn div_mod(mut self, mut other: Self) -> (Self, Self) {
553						use core::cmp::Ordering;
554
555						let my_bits = self.bits();
556						let your_bits = other.bits();
557
558						assert!(your_bits != 0, "division by zero");
559
560						// Early return in case we are dividing by a larger number than us
561						if my_bits < your_bits {
562							return (Self::ZERO, self);
563						}
564
565						if your_bits <= Self::WORD_BITS {
566							return self.div_mod_small(other.low_u64());
567						}
568
569						let (n, m) = {
570							let my_words = Self::words(my_bits);
571							let your_words = Self::words(your_bits);
572							(your_words, my_words - your_words)
573						};
574
575						self.div_mod_knuth(other, n, m)
576					}
577
578					#[inline]
579					fn overflowing_add(self, other: Self) -> (Self, bool) {
580						$crate::uint_overflowing_binop!(
581							$name,
582							$n_words,
583							self,
584							other,
585							u64::overflowing_add
586						)
587					}
588
589					#[inline]
590					fn overflowing_sub(self, other: Self) -> (Self, bool) {
591						$crate::uint_overflowing_binop!(
592							$name,
593							$n_words,
594							self,
595							other,
596							u64::overflowing_sub
597						)
598					}
599
600					/// Overflowing multiplication by u64.
601					/// Returns the result and carry.
602					#[inline]
603					fn overflowing_mul_u64(mut self, other: u64) -> (Self, u64) {
604						let mut carry = 0u64;
605
606						for d in self.0.iter_mut() {
607							let (res, c) = Self::mul_u64(*d, other, carry);
608							*d = res;
609							carry = c;
610						}
611
612						(self, carry)
613					}
614
615					#[inline]
616					fn overflowing_mul(self, other: Self) -> (Self, bool) {
617						$crate::uint_overflowing_mul!($name, $n_words, self, other)
618					}
619
620					#[inline]
621					fn overflowing_neg(self) -> (Self, bool) {
622						(self.overflowing_not().0.wrapping_add(Self::from_u64(1)), !self.is_zero())
623					}
624
625					#[inline]
626					fn overflowing_shl(self, lhs: u32) -> (Self, bool) {
627						let shift = lhs as usize;
628						let $name(ref original) = self;
629						let mut ret = [0u64; $n_words];
630						let word_shift = shift / 64;
631						let bit_shift = shift % 64;
632
633						// shift
634						for i in word_shift..$n_words {
635							ret[i] = original[i - word_shift] << bit_shift;
636						}
637						// carry
638						if bit_shift > 0 {
639							for i in word_shift+1..$n_words {
640								ret[i] += original[i - 1 - word_shift] >> (64 - bit_shift);
641							}
642						}
643						($name(ret), (lhs > ($n_words*64 - 1)))
644					}
645
646					#[inline]
647					fn overflowing_shr(self, rhs: u32) -> ($name, bool) {
648						let shift = rhs as usize;
649						let $name(ref original) = self;
650						let mut ret = [0u64; $n_words];
651						let word_shift = shift / 64;
652						let bit_shift = shift % 64;
653
654						// shift
655						for i in word_shift..$n_words {
656							ret[i - word_shift] = original[i] >> bit_shift;
657						}
658
659						// Carry
660						if bit_shift > 0 {
661							for i in word_shift+1..$n_words {
662								ret[i - word_shift - 1] += original[i] << (64 - bit_shift);
663							}
664						}
665						($name(ret), (rhs > ($n_words*64 - 1)))
666					}
667
668					#[inline]
669					fn overflowing_not(self) -> (Self, bool) {
670						let mut ret = [0u64; $n_words];
671						$crate::unroll! {
672							for i in 0..$n_words {
673								ret[i]=!self.0[i];
674							}
675						}
676						(Self(ret), false)
677					}
678
679					#[inline]
680					fn overflowing_bitand(self, other:Self) -> (Self, bool) {
681						let mut ret = [0u64; $n_words];
682						$crate::unroll! {
683							for i in 0..$n_words {
684								ret[i]=self.0[i] & other.0[i];
685							}
686						}
687						(Self(ret), false)
688					}
689
690					#[inline]
691					fn overflowing_bitor(self, other:Self) -> (Self, bool) {
692						let mut ret = [0u64; $n_words];
693						$crate::unroll! {
694							for i in 0..$n_words {
695								ret[i]=self.0[i] | other.0[i];
696							}
697						}
698						(Self(ret), false)
699					}
700
701					#[inline]
702					fn overflowing_bitxor(self, other:Self) -> (Self, bool) {
703						let mut ret = [0u64; $n_words];
704						$crate::unroll! {
705							for i in 0..$n_words {
706								ret[i]=self.0[i] ^ other.0[i];
707							}
708						}
709						(Self(ret), false)
710					}
711
712
713
714					/// Write to the slice in big-endian format.
715					#[inline]
716					fn put_big_endian(&self, bytes: &mut [u8]) {
717						use $crate::byteorder::{ByteOrder, BigEndian};
718						debug_assert!($n_words * 8 == bytes.len());
719						for i in 0..$n_words {
720							BigEndian::write_u64(&mut bytes[8 * i..], self.0[$n_words - i - 1]);
721						}
722					}
723
724					/// Write to the slice in little-endian format.
725					#[inline]
726					fn put_little_endian(&self, bytes: &mut [u8]) {
727						use $crate::byteorder::{ByteOrder, LittleEndian};
728						debug_assert!($n_words * 8 == bytes.len());
729						for i in 0..$n_words {
730							LittleEndian::write_u64(&mut bytes[8 * i..], self.0[i]);
731						}
732					}
733
734					#[inline]
735					fn to_big_endian(&self) -> Vec<u8> {
736						let mut res = vec![0u8;$n_words*8];
737						self.put_big_endian(&mut res);
738						res
739					}
740
741					#[inline]
742					fn to_little_endian(&self) -> Vec<u8> {
743						let mut res = vec![0u8;$n_words*8];
744						self.put_little_endian(&mut res);
745						res
746					}
747
748					#[inline]
749					fn from_big_endian(slice: &[u8]) -> Self {
750						use $crate::byteorder::{ByteOrder, BigEndian};
751						assert!($n_words * 8 >= slice.len());
752
753						let mut padded = [0u8; $n_words * 8];
754						padded[$n_words * 8 - slice.len() .. $n_words * 8].copy_from_slice(&slice);
755
756						let mut ret = [0; $n_words];
757						for i in 0..$n_words {
758							ret[$n_words - i - 1] = BigEndian::read_u64(&padded[8 * i..]);
759						}
760
761						$name(ret)
762					}
763
764					#[inline]
765					fn from_little_endian(slice: &[u8]) -> Self {
766						use $crate::byteorder::{ByteOrder, LittleEndian};
767						assert!($n_words * 8 >= slice.len());
768
769						let mut padded = [0u8; $n_words * 8];
770						padded[0..slice.len()].copy_from_slice(&slice);
771
772						let mut ret = [0; $n_words];
773						for i in 0..$n_words {
774							ret[i] = LittleEndian::read_u64(&padded[8 * i..]);
775						}
776
777						$name(ret)
778					}
779
780					#[inline]
781					fn wrapping_cmp(&self, other: &$name) -> core::cmp::Ordering {
782						let &$name(ref a) = self;
783						let &$name(ref b) = other;
784						let mut i = $n_words;
785
786						for i in (0 .. $n_words).rev() {
787							if a[i] < b[i] { return core::cmp::Ordering::Less; }
788							if a[i] > b[i] { return core::cmp::Ordering::Greater; }
789						}
790
791						core::cmp::Ordering::Equal
792					}
793
794
795				}
796			}
797		});
798	};
799}