mod.rs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. use core::ops;
  2. macro_rules! hty {
  3. ($ty:ty) => {
  4. <$ty as LargeInt>::HighHalf
  5. };
  6. }
  7. macro_rules! os_ty {
  8. ($ty:ty) => {
  9. <$ty as Int>::OtherSign
  10. };
  11. }
  12. pub mod addsub;
  13. pub mod mul;
  14. pub mod sdiv;
  15. pub mod shift;
  16. pub mod udiv;
  17. /// Trait for some basic operations on integers
  18. pub trait Int:
  19. Copy
  20. + PartialEq
  21. + PartialOrd
  22. + ops::AddAssign
  23. + ops::BitAndAssign
  24. + ops::BitOrAssign
  25. + ops::ShlAssign<i32>
  26. + ops::ShrAssign<u32>
  27. + ops::Add<Output = Self>
  28. + ops::Sub<Output = Self>
  29. + ops::Div<Output = Self>
  30. + ops::Shl<u32, Output = Self>
  31. + ops::Shr<u32, Output = Self>
  32. + ops::BitOr<Output = Self>
  33. + ops::BitXor<Output = Self>
  34. + ops::BitAnd<Output = Self>
  35. + ops::Not<Output = Self>
  36. {
  37. /// Type with the same width but other signedness
  38. type OtherSign: Int;
  39. /// Unsigned version of Self
  40. type UnsignedInt: Int;
  41. /// The bitwidth of the int type
  42. const BITS: u32;
  43. const ZERO: Self;
  44. const ONE: Self;
  45. /// Extracts the sign from self and returns a tuple.
  46. ///
  47. /// # Examples
  48. ///
  49. /// ```rust,ignore
  50. /// let i = -25_i32;
  51. /// let (sign, u) = i.extract_sign();
  52. /// assert_eq!(sign, true);
  53. /// assert_eq!(u, 25_u32);
  54. /// ```
  55. fn extract_sign(self) -> (bool, Self::UnsignedInt);
  56. fn unsigned(self) -> Self::UnsignedInt;
  57. fn from_unsigned(unsigned: Self::UnsignedInt) -> Self;
  58. fn from_bool(b: bool) -> Self;
  59. // copied from primitive integers, but put in a trait
  60. fn max_value() -> Self;
  61. fn min_value() -> Self;
  62. fn wrapping_add(self, other: Self) -> Self;
  63. fn wrapping_mul(self, other: Self) -> Self;
  64. fn wrapping_sub(self, other: Self) -> Self;
  65. fn wrapping_shl(self, other: u32) -> Self;
  66. fn overflowing_add(self, other: Self) -> (Self, bool);
  67. fn aborting_div(self, other: Self) -> Self;
  68. fn aborting_rem(self, other: Self) -> Self;
  69. fn leading_zeros(self) -> u32;
  70. }
  71. fn unwrap<T>(t: Option<T>) -> T {
  72. match t {
  73. Some(t) => t,
  74. None => ::abort(),
  75. }
  76. }
  77. macro_rules! int_impl_common {
  78. ($ty:ty, $bits:expr) => {
  79. const BITS: u32 = $bits;
  80. const ZERO: Self = 0;
  81. const ONE: Self = 1;
  82. fn from_bool(b: bool) -> Self {
  83. b as $ty
  84. }
  85. fn max_value() -> Self {
  86. <Self>::max_value()
  87. }
  88. fn min_value() -> Self {
  89. <Self>::min_value()
  90. }
  91. fn wrapping_add(self, other: Self) -> Self {
  92. <Self>::wrapping_add(self, other)
  93. }
  94. fn wrapping_mul(self, other: Self) -> Self {
  95. <Self>::wrapping_mul(self, other)
  96. }
  97. fn wrapping_sub(self, other: Self) -> Self {
  98. <Self>::wrapping_sub(self, other)
  99. }
  100. fn wrapping_shl(self, other: u32) -> Self {
  101. <Self>::wrapping_shl(self, other)
  102. }
  103. fn overflowing_add(self, other: Self) -> (Self, bool) {
  104. <Self>::overflowing_add(self, other)
  105. }
  106. fn aborting_div(self, other: Self) -> Self {
  107. unwrap(<Self>::checked_div(self, other))
  108. }
  109. fn aborting_rem(self, other: Self) -> Self {
  110. unwrap(<Self>::checked_rem(self, other))
  111. }
  112. fn leading_zeros(self) -> u32 {
  113. <Self>::leading_zeros(self)
  114. }
  115. }
  116. }
  117. macro_rules! int_impl {
  118. ($ity:ty, $uty:ty, $bits:expr) => {
  119. impl Int for $uty {
  120. type OtherSign = $ity;
  121. type UnsignedInt = $uty;
  122. fn extract_sign(self) -> (bool, $uty) {
  123. (false, self)
  124. }
  125. fn unsigned(self) -> $uty {
  126. self
  127. }
  128. fn from_unsigned(me: $uty) -> Self {
  129. me
  130. }
  131. int_impl_common!($uty, $bits);
  132. }
  133. impl Int for $ity {
  134. type OtherSign = $uty;
  135. type UnsignedInt = $uty;
  136. fn extract_sign(self) -> (bool, $uty) {
  137. if self < 0 {
  138. (true, (!(self as $uty)).wrapping_add(1))
  139. } else {
  140. (false, self as $uty)
  141. }
  142. }
  143. fn unsigned(self) -> $uty {
  144. self as $uty
  145. }
  146. fn from_unsigned(me: $uty) -> Self {
  147. me as $ity
  148. }
  149. int_impl_common!($ity, $bits);
  150. }
  151. };
  152. }
  153. int_impl!(i32, u32, 32);
  154. int_impl!(i64, u64, 64);
  155. int_impl!(i128, u128, 128);
  156. /// Trait to convert an integer to/from smaller parts
  157. pub trait LargeInt: Int {
  158. type LowHalf: Int;
  159. type HighHalf: Int;
  160. fn low(self) -> Self::LowHalf;
  161. fn low_as_high(low: Self::LowHalf) -> Self::HighHalf;
  162. fn high(self) -> Self::HighHalf;
  163. fn high_as_low(low: Self::HighHalf) -> Self::LowHalf;
  164. fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
  165. }
  166. macro_rules! large_int {
  167. ($ty:ty, $tylow:ty, $tyhigh:ty, $halfbits:expr) => {
  168. impl LargeInt for $ty {
  169. type LowHalf = $tylow;
  170. type HighHalf = $tyhigh;
  171. fn low(self) -> $tylow {
  172. self as $tylow
  173. }
  174. fn low_as_high(low: $tylow) -> $tyhigh {
  175. low as $tyhigh
  176. }
  177. fn high(self) -> $tyhigh {
  178. (self >> $halfbits) as $tyhigh
  179. }
  180. fn high_as_low(high: $tyhigh) -> $tylow {
  181. high as $tylow
  182. }
  183. fn from_parts(low: $tylow, high: $tyhigh) -> $ty {
  184. low as $ty | ((high as $ty) << $halfbits)
  185. }
  186. }
  187. };
  188. }
  189. large_int!(u64, u32, u32, 32);
  190. large_int!(i64, u32, i32, 32);
  191. large_int!(u128, u64, u64, 64);
  192. large_int!(i128, u64, i64, 64);
  193. /// Trait to express (possibly lossy) casting of integers
  194. pub trait CastInto<T: Copy>: Copy {
  195. fn cast(self) -> T;
  196. }
  197. macro_rules! cast_into {
  198. ($ty:ty) => {
  199. cast_into!($ty; usize, isize, u32, i32, u64, i64, u128, i128);
  200. };
  201. ($ty:ty; $($into:ty),*) => {$(
  202. impl CastInto<$into> for $ty {
  203. fn cast(self) -> $into {
  204. self as $into
  205. }
  206. }
  207. )*};
  208. }
  209. cast_into!(u32);
  210. cast_into!(i32);
  211. cast_into!(u64);
  212. cast_into!(i64);
  213. cast_into!(u128);
  214. cast_into!(i128);
  215. pub trait WideInt: Int {
  216. type Output: Int;
  217. fn wide_mul(self, other: Self) -> (Self, Self);
  218. fn wide_shift_left(&mut self, low: &mut Self, count: i32);
  219. fn wide_shift_right_with_sticky(&mut self, low: &mut Self, count: i32);
  220. }
  221. macro_rules! impl_wide_int {
  222. ($ty:ty, $tywide:ty, $bits:expr) => {
  223. impl WideInt for $ty {
  224. type Output = $ty;
  225. fn wide_mul(self, other: Self) -> (Self, Self) {
  226. let product = (self as $tywide).wrapping_mul(other as $tywide);
  227. ((product >> ($bits as $ty)) as $ty, product as $ty)
  228. }
  229. fn wide_shift_left(&mut self, low: &mut Self, count: i32) {
  230. *self = (*self << count) | (*low >> ($bits - count));
  231. *low = *low << count;
  232. }
  233. fn wide_shift_right_with_sticky(&mut self, low: &mut Self, count: i32) {
  234. if count < $bits {
  235. let sticky = *low << ($bits - count);
  236. *low = *self << ($bits - count) | *low >> count | sticky;
  237. *self = *self >> count;
  238. } else if count < 2 * $bits {
  239. let sticky = *self << (2 * $bits - count) | *low;
  240. *low = *self >> (count - $bits) | sticky;
  241. *self = 0;
  242. } else {
  243. let sticky = *self | *low;
  244. *self = sticky;
  245. *self = 0;
  246. }
  247. }
  248. }
  249. };
  250. }
  251. impl_wide_int!(u32, u64, 32);
  252. impl_wide_int!(u64, u128, 64);
  253. intrinsics! {
  254. #[maybe_use_optimized_c_shim]
  255. #[cfg(any(
  256. target_pointer_width = "16",
  257. target_pointer_width = "32",
  258. target_pointer_width = "64"
  259. ))]
  260. pub extern "C" fn __clzsi2(x: usize) -> usize {
  261. // TODO: const this? Would require const-if
  262. // Note(Lokathor): the `intrinsics!` macro can't process mut inputs
  263. let mut x = x;
  264. let mut y: usize;
  265. let mut n: usize = {
  266. #[cfg(target_pointer_width = "64")]
  267. {
  268. 64
  269. }
  270. #[cfg(target_pointer_width = "32")]
  271. {
  272. 32
  273. }
  274. #[cfg(target_pointer_width = "16")]
  275. {
  276. 16
  277. }
  278. };
  279. #[cfg(target_pointer_width = "64")]
  280. {
  281. y = x >> 32;
  282. if y != 0 {
  283. n -= 32;
  284. x = y;
  285. }
  286. }
  287. #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
  288. {
  289. y = x >> 16;
  290. if y != 0 {
  291. n -= 16;
  292. x = y;
  293. }
  294. }
  295. y = x >> 8;
  296. if y != 0 {
  297. n -= 8;
  298. x = y;
  299. }
  300. y = x >> 4;
  301. if y != 0 {
  302. n -= 4;
  303. x = y;
  304. }
  305. y = x >> 2;
  306. if y != 0 {
  307. n -= 2;
  308. x = y;
  309. }
  310. y = x >> 1;
  311. if y != 0 {
  312. n - 2
  313. } else {
  314. n - x
  315. }
  316. }
  317. }