math.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //! Mathematical functions.
  2. use crate::arch::word::Word;
  3. use crate::assert::debug_assert_in_const_fn;
  4. use crate::primitive::PrimitiveUnsigned;
  5. /// The length of an integer in bits.
  6. /// 0 for 0.
  7. #[inline]
  8. pub(crate) fn bit_len<T: PrimitiveUnsigned>(x: T) -> u32 {
  9. T::BIT_SIZE - x.leading_zeros()
  10. }
  11. /// The length of an integer in bits.
  12. /// 0 for 0.
  13. #[inline]
  14. pub(crate) const fn bit_len_word(x: Word) -> u32 {
  15. Word::BIT_SIZE - x.leading_zeros()
  16. }
  17. /// Ceiling of log_2(x).
  18. /// x must be non-zero.
  19. #[inline]
  20. pub(crate) fn ceil_log_2<T: PrimitiveUnsigned>(x: T) -> u32 {
  21. debug_assert!(x != T::from(0u8));
  22. bit_len(x - T::from(1u8))
  23. }
  24. /// Ceiling of log_2(x).
  25. /// x must be non-zero.
  26. #[inline]
  27. pub(crate) const fn ceil_log_2_word(x: Word) -> u32 {
  28. debug_assert_in_const_fn!(x != 0);
  29. bit_len_word(x - 1)
  30. }
  31. /// Ceiling of a / b.
  32. #[inline]
  33. pub(crate) fn ceil_div<T: PrimitiveUnsigned>(a: T, b: T) -> T {
  34. if a == T::from(0u8) {
  35. T::from(0u8)
  36. } else {
  37. (a - T::from(1u8)) / b + T::from(1u8)
  38. }
  39. }
  40. /// Ceiling of a / b.
  41. #[inline]
  42. pub(crate) const fn ceil_div_usize(a: usize, b: usize) -> usize {
  43. if a == 0 {
  44. 0
  45. } else {
  46. (a - 1) / b + 1
  47. }
  48. }
  49. /// Round up a to a multiple of b.
  50. #[inline]
  51. pub(crate) fn round_up<T: PrimitiveUnsigned>(a: T, b: T) -> T {
  52. ceil_div(a, b) * b
  53. }
  54. /// Round up a to a multiple of b.
  55. #[inline]
  56. pub(crate) const fn round_up_usize(a: usize, b: usize) -> usize {
  57. ceil_div_usize(a, b) * b
  58. }
  59. /// n ones: 2^n - 1
  60. #[inline]
  61. pub(crate) fn ones<T>(n: u32) -> T
  62. where
  63. T: PrimitiveUnsigned,
  64. {
  65. if n == 0 {
  66. T::from(0u8)
  67. } else {
  68. T::MAX >> (T::BIT_SIZE - n)
  69. }
  70. }
  71. /// n ones: 2^n - 1
  72. #[inline]
  73. pub(crate) const fn ones_word(n: u32) -> Word {
  74. if n == 0 {
  75. 0
  76. } else {
  77. Word::MAX >> (Word::BIT_SIZE - n)
  78. }
  79. }
  80. #[inline]
  81. pub(crate) const fn min_usize(a: usize, b: usize) -> usize {
  82. if a < b {
  83. a
  84. } else {
  85. b
  86. }
  87. }
  88. #[cfg(test)]
  89. mod tests {
  90. use super::*;
  91. #[test]
  92. fn test_bit_len() {
  93. assert_eq!(bit_len(0u32), 0);
  94. assert_eq!(bit_len(0b10011101u32), 8);
  95. assert_eq!(bit_len(0b10000000u32), 8);
  96. assert_eq!(bit_len(0b1111111u32), 7);
  97. }
  98. #[test]
  99. fn test_ceil_log_2() {
  100. assert_eq!(ceil_log_2(1u32), 0);
  101. assert_eq!(ceil_log_2(7u32), 3);
  102. assert_eq!(ceil_log_2(8u32), 3);
  103. assert_eq!(ceil_log_2(9u32), 4);
  104. assert_eq!(ceil_log_2(u32::MAX), 32);
  105. }
  106. #[test]
  107. fn test_ceil_div() {
  108. assert_eq!(ceil_div(0u32, 10u32), 0);
  109. assert_eq!(ceil_div(9u32, 10u32), 1);
  110. assert_eq!(ceil_div(10u32, 10u32), 1);
  111. assert_eq!(ceil_div(11u32, 10u32), 2);
  112. }
  113. #[test]
  114. fn test_round_up() {
  115. assert_eq!(round_up(0u32, 10u32), 0);
  116. assert_eq!(round_up(9u32, 10u32), 10);
  117. assert_eq!(round_up(10u32, 10u32), 10);
  118. assert_eq!(round_up(11u32, 10u32), 20);
  119. }
  120. #[test]
  121. fn test_ones() {
  122. assert_eq!(ones::<u32>(0), 0);
  123. assert_eq!(ones::<u32>(5), 0b11111);
  124. assert_eq!(ones::<u32>(32), u32::MAX);
  125. }
  126. }