shift_ops.rs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. //! Bit shift operators.
  2. use crate::arch::word::Word;
  3. use crate::buffer::Buffer;
  4. use crate::ibig::IBig;
  5. use crate::primitive::{double_word, extend_word, split_double_word, WORD_BITS_USIZE};
  6. use crate::shift;
  7. use crate::sign::Sign::*;
  8. use crate::ubig::Repr::*;
  9. use crate::ubig::UBig;
  10. use core::mem;
  11. use core::ops::{Shl, ShlAssign, Shr, ShrAssign};
  12. macro_rules! impl_shifts {
  13. ($t:ty) => {
  14. impl Shl<&usize> for $t {
  15. type Output = $t;
  16. #[inline]
  17. fn shl(self, rhs: &usize) -> $t {
  18. self.shl(*rhs)
  19. }
  20. }
  21. impl Shl<&usize> for &$t {
  22. type Output = $t;
  23. #[inline]
  24. fn shl(self, rhs: &usize) -> $t {
  25. self.shl(*rhs)
  26. }
  27. }
  28. impl ShlAssign<usize> for $t {
  29. #[inline]
  30. fn shl_assign(&mut self, rhs: usize) {
  31. *self = mem::take(self) << rhs;
  32. }
  33. }
  34. impl ShlAssign<&usize> for $t {
  35. #[inline]
  36. fn shl_assign(&mut self, rhs: &usize) {
  37. *self = mem::take(self) << rhs;
  38. }
  39. }
  40. impl Shr<&usize> for $t {
  41. type Output = $t;
  42. #[inline]
  43. fn shr(self, rhs: &usize) -> $t {
  44. self.shr(*rhs)
  45. }
  46. }
  47. impl Shr<&usize> for &$t {
  48. type Output = $t;
  49. #[inline]
  50. fn shr(self, rhs: &usize) -> $t {
  51. self.shr(*rhs)
  52. }
  53. }
  54. impl ShrAssign<usize> for $t {
  55. #[inline]
  56. fn shr_assign(&mut self, rhs: usize) {
  57. *self = mem::take(self).shr(rhs);
  58. }
  59. }
  60. impl ShrAssign<&usize> for $t {
  61. #[inline]
  62. fn shr_assign(&mut self, rhs: &usize) {
  63. *self = mem::take(self).shr(rhs);
  64. }
  65. }
  66. };
  67. }
  68. impl_shifts!(UBig);
  69. impl_shifts!(IBig);
  70. impl Shl<usize> for UBig {
  71. type Output = UBig;
  72. #[inline]
  73. fn shl(self, rhs: usize) -> UBig {
  74. match self.into_repr() {
  75. Small(0) => UBig::from_word(0),
  76. Small(word) => UBig::shl_word(word, rhs),
  77. Large(buffer) => UBig::shl_large(buffer, rhs),
  78. }
  79. }
  80. }
  81. impl Shl<usize> for &UBig {
  82. type Output = UBig;
  83. #[inline]
  84. fn shl(self, rhs: usize) -> UBig {
  85. match self.repr() {
  86. Small(0) => UBig::from_word(0),
  87. Small(word) => UBig::shl_word(*word, rhs),
  88. Large(buffer) => UBig::shl_ref_large(buffer, rhs),
  89. }
  90. }
  91. }
  92. impl Shr<usize> for UBig {
  93. type Output = UBig;
  94. #[inline]
  95. fn shr(self, rhs: usize) -> UBig {
  96. match self.into_repr() {
  97. Small(word) => UBig::shr_word(word, rhs),
  98. Large(buffer) => UBig::shr_large(buffer, rhs),
  99. }
  100. }
  101. }
  102. impl Shr<usize> for &UBig {
  103. type Output = UBig;
  104. #[inline]
  105. fn shr(self, rhs: usize) -> UBig {
  106. match self.repr() {
  107. Small(word) => UBig::shr_word(*word, rhs),
  108. Large(buffer) => UBig::shr_large_ref(buffer, rhs),
  109. }
  110. }
  111. }
  112. impl Shl<usize> for IBig {
  113. type Output = IBig;
  114. #[inline]
  115. fn shl(self, rhs: usize) -> IBig {
  116. let (sign, mag) = self.into_sign_magnitude();
  117. IBig::from_sign_magnitude(sign, mag.shl(rhs))
  118. }
  119. }
  120. impl Shl<usize> for &IBig {
  121. type Output = IBig;
  122. #[inline]
  123. fn shl(self, rhs: usize) -> IBig {
  124. let (sign, mag) = (self.sign(), self.magnitude());
  125. IBig::from_sign_magnitude(sign, mag.shl(rhs))
  126. }
  127. }
  128. impl Shr<usize> for IBig {
  129. type Output = IBig;
  130. #[inline]
  131. fn shr(self, rhs: usize) -> IBig {
  132. let (sign, mag) = self.into_sign_magnitude();
  133. match sign {
  134. Positive => IBig::from(mag.shr(rhs)),
  135. Negative => {
  136. let b = mag.are_low_bits_nonzero(rhs);
  137. -IBig::from(mag.shr(rhs)) - IBig::from(b)
  138. }
  139. }
  140. }
  141. }
  142. impl Shr<usize> for &IBig {
  143. type Output = IBig;
  144. #[inline]
  145. fn shr(self, rhs: usize) -> IBig {
  146. let (sign, mag) = (self.sign(), self.magnitude());
  147. match sign {
  148. Positive => IBig::from(mag.shr(rhs)),
  149. Negative => {
  150. let b = mag.are_low_bits_nonzero(rhs);
  151. -IBig::from(mag.shr(rhs)) - IBig::from(b)
  152. }
  153. }
  154. }
  155. }
  156. impl UBig {
  157. /// Shift left one non-zero `Word` by `rhs` bits.
  158. #[inline]
  159. fn shl_word(word: Word, rhs: usize) -> UBig {
  160. debug_assert!(word != 0);
  161. if rhs <= WORD_BITS_USIZE {
  162. UBig::from(extend_word(word) << rhs)
  163. } else {
  164. UBig::shl_word_slow(word, rhs)
  165. }
  166. }
  167. /// Shift left one non-zero `Word` by `rhs` bits.
  168. fn shl_word_slow(word: Word, rhs: usize) -> UBig {
  169. let shift_words = rhs / WORD_BITS_USIZE;
  170. let shift_bits = (rhs % WORD_BITS_USIZE) as u32;
  171. let (lo, hi) = split_double_word(extend_word(word) << shift_bits);
  172. let mut buffer = Buffer::allocate(shift_words + 2);
  173. buffer.push_zeros(shift_words);
  174. buffer.push(lo);
  175. buffer.push(hi);
  176. buffer.into()
  177. }
  178. /// Shift left `buffer` by `rhs` bits.
  179. fn shl_large(mut buffer: Buffer, rhs: usize) -> UBig {
  180. let shift_words = rhs / WORD_BITS_USIZE;
  181. if buffer.capacity() < buffer.len() + shift_words + 1 {
  182. return UBig::shl_ref_large(&buffer, rhs);
  183. }
  184. let shift_bits = (rhs % WORD_BITS_USIZE) as u32;
  185. let carry = shift::shl_in_place(&mut buffer, shift_bits);
  186. buffer.push(carry);
  187. buffer.push_zeros_front(shift_words);
  188. buffer.into()
  189. }
  190. /// Shift left large number of words by `rhs` bits.
  191. fn shl_ref_large(words: &[Word], rhs: usize) -> UBig {
  192. let shift_words = rhs / WORD_BITS_USIZE;
  193. let shift_bits = (rhs % WORD_BITS_USIZE) as u32;
  194. let mut buffer = Buffer::allocate(shift_words + words.len() + 1);
  195. buffer.push_zeros(shift_words);
  196. buffer.extend(words);
  197. let carry = shift::shl_in_place(&mut buffer[shift_words..], shift_bits);
  198. buffer.push(carry);
  199. buffer.into()
  200. }
  201. /// Shift right one `Word` by `rhs` bits.
  202. #[inline]
  203. fn shr_word(word: Word, rhs: usize) -> UBig {
  204. let word = if rhs < WORD_BITS_USIZE {
  205. word >> rhs
  206. } else {
  207. 0
  208. };
  209. UBig::from_word(word)
  210. }
  211. /// Shift right `buffer` by `rhs` bits.
  212. fn shr_large(mut buffer: Buffer, rhs: usize) -> UBig {
  213. let shift_words = rhs / WORD_BITS_USIZE;
  214. if shift_words >= buffer.len() {
  215. return UBig::from_word(0);
  216. }
  217. let shift_bits = (rhs % WORD_BITS_USIZE) as u32;
  218. buffer.erase_front(shift_words);
  219. shift::shr_in_place(&mut buffer, shift_bits);
  220. buffer.into()
  221. }
  222. /// Shift right large number of words by `rhs` bits.
  223. fn shr_large_ref(words: &[Word], rhs: usize) -> UBig {
  224. let shift_words = rhs / WORD_BITS_USIZE;
  225. let shift_bits = (rhs % WORD_BITS_USIZE) as u32;
  226. let words = &words[shift_words.min(words.len())..];
  227. match words {
  228. [] => UBig::from_word(0),
  229. &[w] => UBig::from_word(w >> shift_bits),
  230. &[lo, hi] => UBig::from(double_word(lo, hi) >> shift_bits),
  231. _ => {
  232. let mut buffer = Buffer::allocate(words.len());
  233. buffer.extend(words);
  234. shift::shr_in_place(&mut buffer, shift_bits);
  235. buffer.into()
  236. }
  237. }
  238. }
  239. }