arithmetic.c 1008 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #include <devutil.h>
  2. #include <stdint.h>
  3. static inline uint64_t do_div(uint64_t a, uint64_t b, uint64_t* remainder)
  4. {
  5. uint64_t r = 0, q = 0;
  6. for (int32_t i = 0; i < 64; i++) {
  7. r = (r << 1) + (a >> 63);
  8. a <<= 1;
  9. q <<= 1;
  10. if (r >= b) {
  11. r -= b;
  12. q += 1;
  13. }
  14. }
  15. if (remainder)
  16. *remainder = r;
  17. return q;
  18. }
  19. static inline int64_t do_div_s(int64_t a, int64_t b, uint64_t* remainder)
  20. {
  21. int32_t qf = 0, rf = 0;
  22. if (a < 0) {
  23. qf = rf = 1;
  24. a = -a;
  25. }
  26. if (b < 0) {
  27. qf ^= 1;
  28. b = -b;
  29. }
  30. int64_t quotient = do_div(a, b, (uint64_t*)remainder);
  31. if (qf)
  32. quotient = -quotient;
  33. if (remainder && rf)
  34. *remainder = -*remainder;
  35. return quotient;
  36. }
  37. int64_t __divdi3(int64_t a, int64_t b)
  38. {
  39. return do_div_s(a, b, (uint64_t*)0);
  40. }
  41. int64_t __moddi3(int64_t a, int64_t b)
  42. {
  43. uint64_t remainder = 0;
  44. do_div_s(a, b, &remainder);
  45. return remainder;
  46. }