int64.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Handling of the int64 and uint64 types. Done in 32-bit integers,
  3. * for (pre-C99) portability. Hopefully once C99 becomes widespread
  4. * we can kiss this lot goodbye...
  5. */
  6. #include <assert.h>
  7. #include <string.h>
  8. #include "int64.h"
  9. uint64 uint64_div10(uint64 x, int *remainder)
  10. {
  11. uint64 y;
  12. unsigned int rem, r2;
  13. y.hi = x.hi / 10;
  14. y.lo = x.lo / 10;
  15. rem = x.lo % 10;
  16. /*
  17. * Now we have to add in the remainder left over from x.hi.
  18. */
  19. r2 = x.hi % 10;
  20. y.lo += r2 * 429496729;
  21. rem += r2 * 6;
  22. y.lo += rem / 10;
  23. rem %= 10;
  24. if (remainder)
  25. *remainder = rem;
  26. return y;
  27. }
  28. void uint64_decimal(uint64 x, char *buffer)
  29. {
  30. char buf[20];
  31. int start = 20;
  32. int d;
  33. do {
  34. x = uint64_div10(x, &d);
  35. assert(start > 0);
  36. buf[--start] = d + '0';
  37. } while (x.hi || x.lo);
  38. memcpy(buffer, buf + start, sizeof(buf) - start);
  39. buffer[sizeof(buf) - start] = '\0';
  40. }
  41. uint64 uint64_make(unsigned long hi, unsigned long lo)
  42. {
  43. uint64 y;
  44. y.hi = hi & 0xFFFFFFFFU;
  45. y.lo = lo & 0xFFFFFFFFU;
  46. return y;
  47. }
  48. uint64 uint64_add(uint64 x, uint64 y)
  49. {
  50. x.lo = (x.lo + y.lo) & 0xFFFFFFFFU;
  51. x.hi += y.hi + (x.lo < y.lo ? 1 : 0);
  52. return x;
  53. }
  54. uint64 uint64_add32(uint64 x, unsigned long y)
  55. {
  56. uint64 yy;
  57. yy.hi = 0;
  58. yy.lo = y;
  59. return uint64_add(x, yy);
  60. }
  61. int uint64_compare(uint64 x, uint64 y)
  62. {
  63. if (x.hi != y.hi)
  64. return x.hi < y.hi ? -1 : +1;
  65. if (x.lo != y.lo)
  66. return x.lo < y.lo ? -1 : +1;
  67. return 0;
  68. }
  69. uint64 uint64_subtract(uint64 x, uint64 y)
  70. {
  71. x.lo = (x.lo - y.lo) & 0xFFFFFFFFU;
  72. x.hi = (x.hi - y.hi - (x.lo > (y.lo ^ 0xFFFFFFFFU) ? 1 : 0)) & 0xFFFFFFFFU;
  73. return x;
  74. }
  75. double uint64_to_double(uint64 x)
  76. {
  77. return (4294967296.0 * x.hi) + (double)x.lo;
  78. }
  79. uint64 uint64_shift_right(uint64 x, int shift)
  80. {
  81. if (shift < 32) {
  82. x.lo >>= shift;
  83. x.lo |= (x.hi << (32-shift)) & 0xFFFFFFFFU;
  84. x.hi >>= shift;
  85. } else {
  86. x.lo = x.hi >> (shift-32);
  87. x.hi = 0;
  88. }
  89. return x;
  90. }
  91. uint64 uint64_shift_left(uint64 x, int shift)
  92. {
  93. if (shift < 32) {
  94. x.hi = (x.hi << shift) & 0xFFFFFFFFU;
  95. x.hi |= (x.lo >> (32-shift));
  96. x.lo = (x.lo << shift) & 0xFFFFFFFFU;
  97. } else {
  98. x.hi = (x.lo << (shift-32)) & 0xFFFFFFFFU;
  99. x.lo = 0;
  100. }
  101. return x;
  102. }
  103. uint64 uint64_from_decimal(char *str)
  104. {
  105. uint64 ret;
  106. ret.hi = ret.lo = 0;
  107. while (*str >= '0' && *str <= '9') {
  108. ret = uint64_add(uint64_shift_left(ret, 3),
  109. uint64_shift_left(ret, 1));
  110. ret = uint64_add32(ret, *str - '0');
  111. str++;
  112. }
  113. return ret;
  114. }
  115. #ifdef TESTMODE
  116. #include <stdio.h>
  117. int main(void)
  118. {
  119. uint64 x, y, z;
  120. char buf[80];
  121. x = uint64_make(0x3456789AUL, 0xDEF01234UL);
  122. printf("%08lx.%08lx\n", x.hi, x.lo);
  123. uint64_decimal(x, buf);
  124. printf("%s\n", buf);
  125. y = uint64_add32(x, 0xFFFFFFFFU);
  126. printf("%08lx.%08lx\n", y.hi, y.lo);
  127. uint64_decimal(y, buf);
  128. printf("%s\n", buf);
  129. z = uint64_subtract(y, x);
  130. printf("%08lx.%08lx\n", z.hi, z.lo);
  131. uint64_decimal(z, buf);
  132. printf("%s\n", buf);
  133. z = uint64_subtract(x, y);
  134. printf("%08lx.%08lx\n", z.hi, z.lo);
  135. uint64_decimal(z, buf);
  136. printf("%s\n", buf);
  137. y = uint64_shift_right(x, 4);
  138. printf("%08lx.%08lx\n", y.hi, y.lo);
  139. y = uint64_shift_right(x, 36);
  140. printf("%08lx.%08lx\n", y.hi, y.lo);
  141. y = uint64_shift_left(x, 4);
  142. printf("%08lx.%08lx\n", x.hi, x.lo);
  143. y = uint64_shift_left(x, 36);
  144. printf("%08lx.%08lx\n", x.hi, x.lo);
  145. return 0;
  146. }
  147. #endif