62e3c17b |
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 | |
7 | #include <assert.h> |
8 | |
9 | typedef struct { |
10 | unsigned long hi, lo; |
11 | } uint64, int64; |
12 | |
13 | uint64 uint64_div10(uint64 x, int *remainder) { |
14 | uint64 y; |
15 | int rem, r2; |
16 | y.hi = x.hi / 10; |
17 | y.lo = x.lo / 10; |
18 | rem = x.lo % 10; |
19 | /* |
20 | * Now we have to add in the remainder left over from x.hi. |
21 | */ |
22 | r2 = x.hi % 10; |
23 | y.lo += r2 * 2 * (0x80000000 / 10); |
24 | rem += r2 * 2 * (0x80000000 % 10); |
25 | y.lo += rem / 10; |
26 | rem %= 10; |
27 | |
28 | if (remainder) |
29 | *remainder = rem; |
30 | return y; |
31 | } |
32 | |
33 | void uint64_decimal(uint64 x, char *buffer) { |
34 | char buf[20]; |
35 | int start = 20; |
36 | int d; |
37 | |
38 | while (x.hi || x.lo) { |
39 | x = uint64_div10(x, &d); |
40 | assert(start > 0); |
41 | buf[--start] = d + '0'; |
42 | } |
43 | |
44 | memcpy(buffer, buf+start, sizeof(buf)-start); |
45 | buffer[sizeof(buf)-start] = '\0'; |
46 | } |
47 | |
48 | uint64 uint64_make(unsigned long hi, unsigned long lo) { |
49 | uint64 y; |
50 | y.hi = hi; |
51 | y.lo = lo; |
52 | return y; |
53 | } |
54 | |
55 | uint64 uint64_add(uint64 x, uint64 y) { |
56 | x.lo += y.lo; |
57 | x.hi += y.hi + (x.lo < y.lo ? 1 : 0); |
58 | return x; |
59 | } |
60 | |
61 | uint64 uint64_add32(uint64 x, unsigned long y) { |
62 | uint64 yy; |
63 | yy.hi = 0; |
64 | yy.lo = y; |
65 | return uint64_add(x, yy); |
66 | } |