udiv.rs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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 qc::{U32, U64};
  196. use gcc_s;
  197. use quickcheck::TestResult;
  198. use rand;
  199. quickcheck!{
  200. fn udivdi3(n: U64, d: U64) -> TestResult {
  201. let (n, d) = (n.0, d.0);
  202. if d == 0 {
  203. TestResult::discard()
  204. } else {
  205. let q = super::__udivdi3(n, d);
  206. match gcc_s::udivdi3() {
  207. Some(udivdi3) if rand::random() => {
  208. TestResult::from_bool(q == unsafe { udivdi3(n, d) })
  209. },
  210. _ => TestResult::from_bool(q == n / d),
  211. }
  212. }
  213. }
  214. fn umoddi3(n: U64, d: U64) -> TestResult {
  215. let (n, d) = (n.0, d.0);
  216. if d == 0 {
  217. TestResult::discard()
  218. } else {
  219. let r = super::__umoddi3(n, d);
  220. match gcc_s::umoddi3() {
  221. Some(umoddi3) if rand::random() => {
  222. TestResult::from_bool(r == unsafe { umoddi3(n, d) })
  223. },
  224. _ => TestResult::from_bool(r == n % d),
  225. }
  226. }
  227. }
  228. fn udivmoddi4(n: U64, d: U64) -> TestResult {
  229. let (n, d) = (n.0, d.0);
  230. if d == 0 {
  231. TestResult::discard()
  232. } else {
  233. let mut r = 0;
  234. let q = super::__udivmoddi4(n, d, Some(&mut r));
  235. match gcc_s::udivmoddi4() {
  236. Some(udivmoddi4) if rand::random() => {
  237. let mut gcc_s_r = 0;
  238. let gcc_s_q = unsafe {
  239. udivmoddi4(n, d, Some(&mut gcc_s_r))
  240. };
  241. TestResult::from_bool(q == gcc_s_q && r == gcc_s_r)
  242. },
  243. _ => TestResult::from_bool(q == n / d && r == n % d),
  244. }
  245. }
  246. }
  247. fn udivsi3(n: U32, d: U32) -> TestResult {
  248. let (n, d) = (n.0, d.0);
  249. if d == 0 {
  250. TestResult::discard()
  251. } else {
  252. let q = super::__udivsi3(n, d);
  253. match gcc_s::udivsi3() {
  254. Some(udivsi3) if rand::random() => {
  255. TestResult::from_bool(q == unsafe { udivsi3(n, d) })
  256. },
  257. _ => TestResult::from_bool(q == n / d),
  258. }
  259. }
  260. }
  261. fn umodsi3(n: U32, d: U32) -> TestResult {
  262. let (n, d) = (n.0, d.0);
  263. if d == 0 {
  264. TestResult::discard()
  265. } else {
  266. let r = super::__umodsi3(n, d);
  267. match gcc_s::umodsi3() {
  268. Some(umodsi3) if rand::random() => {
  269. TestResult::from_bool(r == unsafe { umodsi3(n, d) })
  270. },
  271. _ => TestResult::from_bool(r == n % d),
  272. }
  273. }
  274. }
  275. fn udivmodsi4(n: U32, d: U32) -> TestResult {
  276. let (n, d) = (n.0, d.0);
  277. if d == 0 {
  278. TestResult::discard()
  279. } else {
  280. let mut r = 0;
  281. let q = super::__udivmodsi4(n, d, Some(&mut r));
  282. match gcc_s::udivmodsi4() {
  283. Some(udivmodsi4) if rand::random() => {
  284. let mut gcc_s_r = 0;
  285. let gcc_s_q = unsafe {
  286. udivmodsi4(n, d, Some(&mut gcc_s_r))
  287. };
  288. TestResult::from_bool(q == gcc_s_q && r == gcc_s_r)
  289. },
  290. _ => TestResult::from_bool(q == n / d && r == n % d),
  291. }
  292. }
  293. }
  294. }
  295. }