int64.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #ifndef __libfixmath_int64_h__
  2. #define __libfixmath_int64_h__
  3. #ifdef __cplusplus
  4. extern "C"
  5. {
  6. #endif
  7. #ifndef FIXMATH_NO_64BIT
  8. static inline int64_t int64_const(int32_t hi, uint32_t lo) { return (((int64_t)hi << 32) | lo); }
  9. static inline int64_t int64_from_int32(int32_t x) { return (int64_t)x; }
  10. static inline int32_t int64_hi(int64_t x) { return (x >> 32); }
  11. static inline uint32_t int64_lo(int64_t x) { return (x & ((1ULL << 32) - 1)); }
  12. static inline int64_t int64_add(int64_t x, int64_t y) { return (x + y); }
  13. static inline int64_t int64_neg(int64_t x) { return (-x); }
  14. static inline int64_t int64_sub(int64_t x, int64_t y) { return (x - y); }
  15. static inline int64_t int64_shift(int64_t x, int8_t y) { return (y < 0 ? (x >> -y) : (x << y)); }
  16. static inline int64_t int64_mul_i32_i32(int32_t x, int32_t y) { return (x * y); }
  17. static inline int64_t int64_mul_i64_i32(int64_t x, int32_t y) { return (x * y); }
  18. static inline int64_t int64_div_i64_i32(int64_t x, int32_t y) { return (x / y); }
  19. static inline int int64_cmp_eq(int64_t x, int64_t y) { return (x == y); }
  20. static inline int int64_cmp_ne(int64_t x, int64_t y) { return (x != y); }
  21. static inline int int64_cmp_gt(int64_t x, int64_t y) { return (x > y); }
  22. static inline int int64_cmp_ge(int64_t x, int64_t y) { return (x >= y); }
  23. static inline int int64_cmp_lt(int64_t x, int64_t y) { return (x < y); }
  24. static inline int int64_cmp_le(int64_t x, int64_t y) { return (x <= y); }
  25. #else
  26. typedef struct {
  27. int32_t hi;
  28. uint32_t lo;
  29. } __int64_t;
  30. static inline __int64_t int64_const(int32_t hi, uint32_t lo) { return (__int64_t){ hi, lo }; }
  31. static inline __int64_t int64_from_int32(int32_t x) { return (__int64_t){ (x < 0 ? -1 : 0), x }; }
  32. static inline int32_t int64_hi(__int64_t x) { return x.hi; }
  33. static inline uint32_t int64_lo(__int64_t x) { return x.lo; }
  34. static inline int int64_cmp_eq(__int64_t x, __int64_t y) { return ((x.hi == y.hi) && (x.lo == y.lo)); }
  35. static inline int int64_cmp_ne(__int64_t x, __int64_t y) { return ((x.hi != y.hi) || (x.lo != y.lo)); }
  36. static inline int int64_cmp_gt(__int64_t x, __int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo > y.lo))); }
  37. static inline int int64_cmp_ge(__int64_t x, __int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo >= y.lo))); }
  38. static inline int int64_cmp_lt(__int64_t x, __int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo < y.lo))); }
  39. static inline int int64_cmp_le(__int64_t x, __int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo <= y.lo))); }
  40. static inline __int64_t int64_add(__int64_t x, __int64_t y) {
  41. __int64_t ret;
  42. ret.hi = x.hi + y.hi;
  43. ret.lo = x.lo + y.lo;
  44. if((ret.lo < x.lo) || (ret.hi < y.hi))
  45. ret.hi++;
  46. return ret;
  47. }
  48. static inline __int64_t int64_neg(__int64_t x) {
  49. __int64_t ret;
  50. ret.hi = ~x.hi;
  51. ret.lo = ~x.lo + 1;
  52. if(ret.lo == 0)
  53. ret.hi++;
  54. return ret;
  55. }
  56. static inline __int64_t int64_sub(__int64_t x, __int64_t y) {
  57. return int64_add(x, int64_neg(y));
  58. }
  59. static inline __int64_t int64_shift(__int64_t x, int8_t y) {
  60. __int64_t ret;
  61. if(y > 0) {
  62. if(y >= 32)
  63. return (__int64_t){ 0, 0 };
  64. ret.hi = (x.hi << y) | (x.lo >> (32 - y));
  65. ret.lo = (x.lo << y);
  66. } else {
  67. y = -y;
  68. if(y >= 32)
  69. return (__int64_t){ 0, 0 };
  70. ret.lo = (x.lo >> y) | (x.hi << (32 - y));
  71. ret.hi = (x.hi >> y);
  72. }
  73. return ret;
  74. }
  75. static inline __int64_t int64_mul_i32_i32(int32_t x, int32_t y) {
  76. int16_t hi[2] = { (x >> 16), (y >> 16) };
  77. uint16_t lo[2] = { (x & 0xFFFF), (y & 0xFFFF) };
  78. int32_t r_hi = hi[0] * hi[1];
  79. int32_t r_md = (hi[0] * lo[1]) + (hi[1] * lo[0]);
  80. uint32_t r_lo = lo[0] * lo[1];
  81. r_hi += (r_md >> 16);
  82. r_lo += (r_md << 16);
  83. return (__int64_t){ r_hi, r_lo };
  84. }
  85. static inline __int64_t int64_mul_i64_i32(__int64_t x, int32_t y) {
  86. int neg = ((x.hi ^ y) < 0);
  87. if(x.hi < 0)
  88. x = int64_neg(x);
  89. if(y < 0)
  90. y = -y;
  91. uint32_t _x[4] = { (x.hi >> 16), (x.hi & 0xFFFF), (x.lo >> 16), (x.lo & 0xFFFF) };
  92. uint32_t _y[2] = { (y >> 16), (y & 0xFFFF) };
  93. uint32_t r[4];
  94. r[0] = (_x[0] * _y[0]);
  95. r[1] = (_x[1] * _y[0]) + (_x[0] * _y[1]);
  96. r[2] = (_x[1] * _y[1]) + (_x[2] * _y[0]);
  97. r[3] = (_x[2] * _y[0]) + (_x[1] * _y[1]);
  98. __int64_t ret;
  99. ret.lo = r[0] + (r[1] << 16);
  100. ret.hi = (r[3] << 16) + r[2] + (r[1] >> 16);
  101. return (neg ? int64_neg(ret) : ret);
  102. }
  103. static inline __int64_t int64_div_i64_i32(__int64_t x, int32_t y) {
  104. int neg = ((x.hi ^ y) < 0);
  105. if(x.hi < 0)
  106. x = int64_neg(x);
  107. if(y < 0)
  108. y = -y;
  109. __int64_t ret = { (x.hi / y) , (x.lo / y) };
  110. x.hi = x.hi % y;
  111. x.lo = x.lo % y;
  112. __int64_t _y = int64_from_int32(y);
  113. __int64_t i;
  114. for(i = int64_from_int32(1); int64_cmp_lt(_y, x); _y = int64_shift(_y, 1), i = int64_shift(i, 1));
  115. while(x.hi) {
  116. _y = int64_shift(_y, -1);
  117. i = int64_shift(i, -1);
  118. if(int64_cmp_ge(x, _y)) {
  119. x = int64_sub(x, _y);
  120. ret = int64_add(ret, i);
  121. }
  122. }
  123. ret = int64_add(ret, int64_from_int32(x.lo / y));
  124. return (neg ? int64_neg(ret) : ret);
  125. }
  126. #define int64_t __int64_t
  127. #endif
  128. #ifdef __cplusplus
  129. }
  130. #endif
  131. #endif