num_modular/
word.rs

1macro_rules! simple_word_impl {
2    ($S:ty, $D:ident) => {
3        pub type Word = $S;
4        pub type DoubleWord = $D;
5        pub use super::$D as DoubleWordModule;
6
7        #[inline(always)]
8        pub const fn ones(n: u32) -> Word {
9            if n == 0 {
10                0
11            } else {
12                Word::MAX >> (Word::BITS - n)
13            }
14        }
15
16        #[inline(always)]
17        pub const fn extend(word: Word) -> DoubleWord {
18            word as DoubleWord
19        }
20
21        #[inline(always)]
22        pub const fn low(dw: DoubleWord) -> Word {
23            dw as Word
24        }
25
26        #[inline(always)]
27        pub const fn high(dw: DoubleWord) -> Word {
28            (dw >> Word::BITS) as Word
29        }
30
31        #[inline(always)]
32        pub const fn split(dw: DoubleWord) -> (Word, Word) {
33            (low(dw), high(dw))
34        }
35
36        #[inline(always)]
37        pub const fn merge(low: Word, high: Word) -> DoubleWord {
38            extend(low) | extend(high) << Word::BITS
39        }
40
41        /// Widening multiplication
42        #[inline(always)]
43        pub const fn wmul(a: Word, b: Word) -> DoubleWord {
44            extend(a) * extend(b)
45        }
46
47        /// Widening squaring
48        #[inline(always)]
49        pub const fn wsqr(a: Word) -> DoubleWord {
50            extend(a) * extend(a)
51        }
52
53        /// Narrowing remainder
54        pub const fn nrem(n: DoubleWord, d: Word) -> Word {
55            (n % d as DoubleWord) as _
56        }
57    };
58}
59use simple_word_impl;
60
61pub mod u8 {
62    super::simple_word_impl!(u8, u16);
63}
64
65pub mod u16 {
66    super::simple_word_impl!(u16, u32);
67}
68
69pub mod u32 {
70    super::simple_word_impl!(u32, u64);
71}
72
73pub mod u64 {
74    super::simple_word_impl!(u64, u128);
75}
76
77pub mod usize {
78    #[cfg(target_pointer_width = "16")]
79    super::simple_word_impl!(usize, u32);
80    #[cfg(target_pointer_width = "32")]
81    super::simple_word_impl!(usize, u64);
82    #[cfg(target_pointer_width = "64")]
83    super::simple_word_impl!(usize, u128);
84}
85
86pub mod u128 {
87    use crate::double::udouble;
88    pub type Word = u128;
89    pub type DoubleWord = udouble;
90
91    #[inline]
92    pub const fn extend(word: Word) -> DoubleWord {
93        udouble { lo: word, hi: 0 }
94    }
95
96    #[inline(always)]
97    pub const fn low(dw: DoubleWord) -> Word {
98        dw.lo
99    }
100
101    #[inline(always)]
102    pub const fn high(dw: DoubleWord) -> Word {
103        dw.hi
104    }
105
106    #[inline]
107    pub const fn split(dw: DoubleWord) -> (Word, Word) {
108        (dw.lo, dw.hi)
109    }
110
111    #[inline]
112    pub const fn merge(low: Word, high: Word) -> DoubleWord {
113        udouble { lo: low, hi: high }
114    }
115
116    #[inline]
117    pub const fn wmul(a: Word, b: Word) -> DoubleWord {
118        udouble::widening_mul(a, b)
119    }
120
121    #[inline]
122    pub const fn wsqr(a: Word) -> DoubleWord {
123        udouble::widening_square(a)
124    }
125
126    #[inline]
127    pub fn nrem(n: DoubleWord, d: Word) -> Word {
128        n % d
129    }
130}