sdiv.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. use Int;
  2. macro_rules! div {
  3. ($intrinsic:ident: $ty:ty, $uty:ty) => {
  4. /// Returns `a / b`
  5. #[cfg_attr(not(test), no_mangle)]
  6. pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty {
  7. let s_a = a >> (<$ty>::bits() - 1);
  8. let s_b = b >> (<$ty>::bits() - 1);
  9. let a = (a ^ s_a) - s_a;
  10. let b = (b ^ s_b) - s_b;
  11. let s = s_a ^ s_b;
  12. let r = (a as $uty) / (b as $uty);
  13. (r as $ty ^ s) - s
  14. }
  15. }
  16. }
  17. macro_rules! mod_ {
  18. ($intrinsic:ident: $ty:ty, $uty:ty) => {
  19. /// Returns `a % b`
  20. #[cfg_attr(not(test), no_mangle)]
  21. pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty {
  22. let s = b >> (<$ty>::bits() - 1);
  23. let b = (b ^ s) - s;
  24. let s = a >> (<$ty>::bits() - 1);
  25. let a = (a ^ s) - s;
  26. let r = (a as $uty) % (b as $uty);
  27. (r as $ty ^ s) - s
  28. }
  29. }
  30. }
  31. macro_rules! divmod {
  32. ($intrinsic:ident, $div:ident: $ty:ty) => {
  33. /// Returns `a / b` and sets `*rem = n % d`
  34. #[cfg_attr(not(test), no_mangle)]
  35. pub extern "C" fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty {
  36. let r = $div(a, b);
  37. *rem = a - (r * b);
  38. r
  39. }
  40. }
  41. }
  42. div!(__divsi3: i32, u32);
  43. div!(__divdi3: i64, u64);
  44. mod_!(__modsi3: i32, u32);
  45. mod_!(__moddi3: i64, u64);
  46. divmod!(__divmodsi4, __divsi3: i32);
  47. divmod!(__divmoddi4, __divdi3: i64);
  48. #[cfg(test)]
  49. mod tests {
  50. use quickcheck::TestResult;
  51. use qc::{U32, U64};
  52. quickcheck!{
  53. fn divdi3(n: U64, d: U64) -> TestResult {
  54. let (n, d) = (n.0 as i64, d.0 as i64);
  55. if d == 0 {
  56. TestResult::discard()
  57. } else {
  58. let q = super::__divdi3(n, d);
  59. TestResult::from_bool(q == n / d)
  60. }
  61. }
  62. fn moddi3(n: U64, d: U64) -> TestResult {
  63. let (n, d) = (n.0 as i64, d.0 as i64);
  64. if d == 0 {
  65. TestResult::discard()
  66. } else {
  67. let r = super::__moddi3(n, d);
  68. TestResult::from_bool(r == n % d)
  69. }
  70. }
  71. fn divmoddi4(n: U64, d: U64) -> TestResult {
  72. let (n, d) = (n.0 as i64, d.0 as i64);
  73. if d == 0 {
  74. TestResult::discard()
  75. } else {
  76. let mut r = 0;
  77. let q = super::__divmoddi4(n, d, &mut r);
  78. TestResult::from_bool(q == n / d && r == n % d)
  79. }
  80. }
  81. fn divsi3(n: U32, d: U32) -> TestResult {
  82. let (n, d) = (n.0 as i32, d.0 as i32);
  83. if d == 0 {
  84. TestResult::discard()
  85. } else {
  86. let q = super::__divsi3(n, d);
  87. TestResult::from_bool(q == n / d)
  88. }
  89. }
  90. fn modsi3(n: U32, d: U32) -> TestResult {
  91. let (n, d) = (n.0 as i32, d.0 as i32);
  92. if d == 0 {
  93. TestResult::discard()
  94. } else {
  95. let r = super::__modsi3(n, d);
  96. TestResult::from_bool(r == n % d)
  97. }
  98. }
  99. fn divmodsi4(n: U32, d: U32) -> TestResult {
  100. let (n, d) = (n.0 as i32, d.0 as i32);
  101. if d == 0 {
  102. TestResult::discard()
  103. } else {
  104. let mut r = 0;
  105. let q = super::__divmodsi4(n, d, &mut r);
  106. TestResult::from_bool(q == n / d && r == n % d)
  107. }
  108. }
  109. }
  110. }