shift.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. use int::{Int, LargeInt};
  2. trait Ashl: Int + LargeInt {
  3. /// Returns `a << b`, requires `b < Self::BITS`
  4. fn ashl(self, offset: u32) -> Self
  5. where
  6. Self: LargeInt<HighHalf = <Self as LargeInt>::LowHalf>,
  7. {
  8. let half_bits = Self::BITS / 2;
  9. if offset & half_bits != 0 {
  10. Self::from_parts(Int::ZERO, self.low() << (offset - half_bits))
  11. } else if offset == 0 {
  12. self
  13. } else {
  14. Self::from_parts(
  15. self.low() << offset,
  16. (self.high() << offset) | (self.low() >> (half_bits - offset)),
  17. )
  18. }
  19. }
  20. }
  21. impl Ashl for u64 {}
  22. impl Ashl for u128 {}
  23. trait Ashr: Int + LargeInt {
  24. /// Returns arithmetic `a >> b`, requires `b < Self::BITS`
  25. fn ashr(self, offset: u32) -> Self
  26. where
  27. Self: LargeInt<LowHalf = <<Self as LargeInt>::HighHalf as Int>::UnsignedInt>,
  28. {
  29. let half_bits = Self::BITS / 2;
  30. if offset & half_bits != 0 {
  31. Self::from_parts(
  32. (self.high() >> (offset - half_bits)).unsigned(),
  33. self.high() >> (half_bits - 1),
  34. )
  35. } else if offset == 0 {
  36. self
  37. } else {
  38. let high_unsigned = self.high().unsigned();
  39. Self::from_parts(
  40. (high_unsigned << (half_bits - offset)) | (self.low() >> offset),
  41. self.high() >> offset,
  42. )
  43. }
  44. }
  45. }
  46. impl Ashr for i64 {}
  47. impl Ashr for i128 {}
  48. trait Lshr: Int + LargeInt {
  49. /// Returns logical `a >> b`, requires `b < Self::BITS`
  50. fn lshr(self, offset: u32) -> Self
  51. where
  52. Self: LargeInt<HighHalf = <Self as LargeInt>::LowHalf>,
  53. {
  54. let half_bits = Self::BITS / 2;
  55. if offset & half_bits != 0 {
  56. Self::from_parts(self.high() >> (offset - half_bits), Int::ZERO)
  57. } else if offset == 0 {
  58. self
  59. } else {
  60. Self::from_parts(
  61. (self.high() << (half_bits - offset)) | (self.low() >> offset),
  62. self.high() >> offset,
  63. )
  64. }
  65. }
  66. }
  67. impl Lshr for u64 {}
  68. impl Lshr for u128 {}
  69. intrinsics! {
  70. #[maybe_use_optimized_c_shim]
  71. #[arm_aeabi_alias = __aeabi_llsl]
  72. pub extern "C" fn __ashldi3(a: u64, b: u32) -> u64 {
  73. a.ashl(b)
  74. }
  75. pub extern "C" fn __ashlti3(a: u128, b: u32) -> u128 {
  76. a.ashl(b)
  77. }
  78. #[maybe_use_optimized_c_shim]
  79. #[arm_aeabi_alias = __aeabi_lasr]
  80. pub extern "C" fn __ashrdi3(a: i64, b: u32) -> i64 {
  81. a.ashr(b)
  82. }
  83. pub extern "C" fn __ashrti3(a: i128, b: u32) -> i128 {
  84. a.ashr(b)
  85. }
  86. #[maybe_use_optimized_c_shim]
  87. #[arm_aeabi_alias = __aeabi_llsr]
  88. pub extern "C" fn __lshrdi3(a: u64, b: u32) -> u64 {
  89. a.lshr(b)
  90. }
  91. pub extern "C" fn __lshrti3(a: u128, b: u32) -> u128 {
  92. a.lshr(b)
  93. }
  94. pub extern "C" fn __rust_i128_shlo(a: i128, b: u128) -> (i128, bool) {
  95. (__ashlti3(a as _, b as _) as _, b >= 128)
  96. }
  97. pub extern "C" fn __rust_u128_shlo(a: u128, b: u128) -> (u128, bool) {
  98. (__ashlti3(a, b as _), b >= 128)
  99. }
  100. pub extern "C" fn __rust_i128_shro(a: i128, b: u128) -> (i128, bool) {
  101. (__ashrti3(a, b as _), b >= 128)
  102. }
  103. pub extern "C" fn __rust_u128_shro(a: u128, b: u128) -> (u128, bool) {
  104. (__lshrti3(a, b as _), b >= 128)
  105. }
  106. }