udiv.rs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. use core::mem;
  2. use int::{Int, LargeInt};
  3. /// Returns `n / d`
  4. #[cfg_attr(not(test), no_mangle)]
  5. pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
  6. // Special cases
  7. if d == 0 {
  8. panic!("Division by zero");
  9. }
  10. if n == 0 {
  11. return 0;
  12. }
  13. let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());
  14. // d > n
  15. if sr > u32::bits() - 1 {
  16. return 0;
  17. }
  18. // d == 1
  19. if sr == u32::bits() - 1 {
  20. return n;
  21. }
  22. sr += 1;
  23. // 1 <= sr <= u32::bits() - 1
  24. let mut q = n << (u32::bits() - sr);
  25. let mut r = n >> sr;
  26. let mut carry = 0;
  27. for _ in 0..sr {
  28. // r:q = ((r:q) << 1) | carry
  29. r = (r << 1) | (q >> (u32::bits() - 1));
  30. q = (q << 1) | carry;
  31. // carry = 0;
  32. // if r > d {
  33. // r -= d;
  34. // carry = 1;
  35. // }
  36. let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32::bits() - 1);
  37. carry = (s & 1) as u32;
  38. r -= d & s as u32;
  39. }
  40. (q << 1) | carry
  41. }
  42. /// Returns `n % d`
  43. #[cfg_attr(not(test), no_mangle)]
  44. pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 {
  45. n - __udivsi3(n, d) * d
  46. }
  47. /// Returns `n / d` and sets `*rem = n % d`
  48. #[cfg_attr(not(test), no_mangle)]
  49. pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 {
  50. let q = __udivsi3(n, d);
  51. if let Some(rem) = rem {
  52. *rem = n - (q * d);
  53. }
  54. q
  55. }
  56. /// Returns `n / d`
  57. #[cfg_attr(not(test), no_mangle)]
  58. pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 {
  59. __udivmoddi4(n, d, None)
  60. }
  61. /// Returns `n % d`
  62. #[cfg_attr(not(test), no_mangle)]
  63. pub extern "C" fn __umoddi3(a: u64, b: u64) -> u64 {
  64. let mut rem = unsafe { mem::uninitialized() };
  65. __udivmoddi4(a, b, Some(&mut rem));
  66. rem
  67. }
  68. /// Returns `n / d` and sets `*rem = n % d`
  69. #[cfg_attr(not(test), no_mangle)]
  70. pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
  71. // NOTE X is unknown, K != 0
  72. if n.high() == 0 {
  73. if d.high() == 0 {
  74. // 0 X
  75. // ---
  76. // 0 X
  77. if let Some(rem) = rem {
  78. *rem = u64::from(n.low() % d.low());
  79. }
  80. return u64::from(n.low() / d.low());
  81. } else {
  82. // 0 X
  83. // ---
  84. // K X
  85. if let Some(rem) = rem {
  86. *rem = n;
  87. }
  88. return 0;
  89. };
  90. }
  91. let mut sr;
  92. let mut q;
  93. let mut r;
  94. if d.low() == 0 {
  95. if d.high() == 0 {
  96. // K X
  97. // ---
  98. // 0 0
  99. panic!("Division by zero");
  100. }
  101. if n.low() == 0 {
  102. // K 0
  103. // ---
  104. // K 0
  105. if let Some(rem) = rem {
  106. *rem = u64::from_parts(0, n.high() % d.high());
  107. }
  108. return u64::from(n.high() / d.high());
  109. }
  110. // K K
  111. // ---
  112. // K 0
  113. if d.high().is_power_of_two() {
  114. if let Some(rem) = rem {
  115. *rem = u64::from_parts(n.low(), n.high() & (d.high() - 1));
  116. }
  117. return u64::from(n.high() >> d.high().trailing_zeros());
  118. }
  119. sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
  120. // D > N
  121. if sr > u32::bits() - 2 {
  122. if let Some(rem) = rem {
  123. *rem = n;
  124. }
  125. return 0;
  126. }
  127. sr += 1;
  128. // 1 <= sr <= u32::bits() - 1
  129. q = n << (u64::bits() - sr);
  130. r = n >> sr;
  131. } else {
  132. if d.high() == 0 {
  133. // K X
  134. // ---
  135. // 0 K
  136. if d.low().is_power_of_two() {
  137. if let Some(rem) = rem {
  138. *rem = u64::from(n.low() & (d.low() - 1));
  139. }
  140. if d.low() == 1 {
  141. return n;
  142. } else {
  143. let sr = d.low().trailing_zeros();
  144. return n >> sr;
  145. };
  146. }
  147. sr = 1 + u32::bits() + d.low().leading_zeros() - n.high().leading_zeros();
  148. // 2 <= sr <= u64::bits() - 1
  149. q = n << (u64::bits() - sr);
  150. r = n >> sr;
  151. } else {
  152. // K X
  153. // ---
  154. // K K
  155. sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
  156. // D > N
  157. if sr > u32::bits() - 1 {
  158. if let Some(rem) = rem {
  159. *rem = n;
  160. }
  161. return 0;
  162. }
  163. sr += 1;
  164. // 1 <= sr <= u32::bits()
  165. q = n << (u64::bits() - sr);
  166. r = n >> sr;
  167. }
  168. }
  169. // Not a special case
  170. // q and r are initialized with
  171. // q = n << (u64::bits() - sr)
  172. // r = n >> sr
  173. // 1 <= sr <= u64::bits() - 1
  174. let mut carry = 0;
  175. for _ in 0..sr {
  176. // r:q = ((r:q) << 1) | carry
  177. r = (r << 1) | (q >> (u64::bits() - 1));
  178. q = (q << 1) | carry as u64;
  179. // carry = 0
  180. // if r >= d {
  181. // r -= d;
  182. // carry = 1;
  183. // }
  184. let s = (d.wrapping_sub(r).wrapping_sub(1)) as i64 >> (u64::bits() - 1);
  185. carry = (s & 1) as u32;
  186. r -= d & s as u64;
  187. }
  188. if let Some(rem) = rem {
  189. *rem = r;
  190. }
  191. (q << 1) | carry as u64
  192. }
  193. #[cfg(test)]
  194. mod tests {
  195. use gcc_s;
  196. use quickcheck::TestResult;
  197. use qc::{U32, U64};
  198. quickcheck!{
  199. fn udivdi3(n: U64, d: U64) -> TestResult {
  200. let (n, d) = (n.0, d.0);
  201. if d == 0 {
  202. TestResult::discard()
  203. } else {
  204. let q = super::__udivdi3(n, d);
  205. if let Some(udivdi3) = gcc_s::udivdi3() {
  206. TestResult::from_bool(q == unsafe { udivdi3(n, d) })
  207. } else {
  208. TestResult::from_bool(q == n / d)
  209. }
  210. }
  211. }
  212. fn umoddi3(n: U64, d: U64) -> TestResult {
  213. let (n, d) = (n.0, d.0);
  214. if d == 0 {
  215. TestResult::discard()
  216. } else {
  217. let r = super::__umoddi3(n, d);
  218. if let Some(umoddi3) = gcc_s::umoddi3() {
  219. TestResult::from_bool(r == unsafe { umoddi3(n, d) })
  220. } else {
  221. TestResult::from_bool(r == n % d)
  222. }
  223. }
  224. }
  225. fn udivmoddi4(n: U64, d: U64) -> TestResult {
  226. let (n, d) = (n.0, d.0);
  227. if d == 0 {
  228. TestResult::discard()
  229. } else {
  230. let mut r = 0;
  231. let q = super::__udivmoddi4(n, d, Some(&mut r));
  232. if let Some(udivmoddi4) = gcc_s::udivmoddi4() {
  233. let mut gcc_s_r = 0;
  234. let gcc_s_q = unsafe {
  235. udivmoddi4(n, d, Some(&mut gcc_s_r))
  236. };
  237. TestResult::from_bool(q == gcc_s_q && r == gcc_s_r)
  238. } else {
  239. TestResult::from_bool(q == n / d && r == n % d)
  240. }
  241. }
  242. }
  243. fn udivsi3(n: U32, d: U32) -> TestResult {
  244. let (n, d) = (n.0, d.0);
  245. if d == 0 {
  246. TestResult::discard()
  247. } else {
  248. let q = super::__udivsi3(n, d);
  249. if let Some(udivsi3) = gcc_s::udivsi3() {
  250. TestResult::from_bool(q == unsafe { udivsi3(n, d) })
  251. } else {
  252. TestResult::from_bool(q == n / d)
  253. }
  254. }
  255. }
  256. fn umodsi3(n: U32, d: U32) -> TestResult {
  257. let (n, d) = (n.0, d.0);
  258. if d == 0 {
  259. TestResult::discard()
  260. } else {
  261. let r = super::__umodsi3(n, d);
  262. if let Some(umodsi3) = gcc_s::umodsi3() {
  263. TestResult::from_bool(r == unsafe { umodsi3(n, d) })
  264. } else {
  265. TestResult::from_bool(r == n % d)
  266. }
  267. }
  268. }
  269. fn udivmodsi4(n: U32, d: U32) -> TestResult {
  270. let (n, d) = (n.0, d.0);
  271. if d == 0 {
  272. TestResult::discard()
  273. } else {
  274. let mut r = 0;
  275. let q = super::__udivmodsi4(n, d, Some(&mut r));
  276. if let Some(udivmodsi4) = gcc_s::udivmodsi4() {
  277. let mut gcc_s_r = 0;
  278. let gcc_s_q = unsafe {
  279. udivmodsi4(n, d, Some(&mut gcc_s_r))
  280. };
  281. TestResult::from_bool(q == gcc_s_q && r == gcc_s_r)
  282. } else {
  283. TestResult::from_bool(q == n / d && r == n % d)
  284. }
  285. }
  286. }
  287. }
  288. }