72d3803d9c4a16d9b78824351cec50a2e5b29f34
[openafs.git] / src / tools / int64.c
1 /*
2  * CMUCS AFStools
3  * dumpscan - routines for scanning and manipulating AFS volume dumps
4  *
5  * Copyright (c) 1998 Carnegie Mellon University
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie Mellon
26  * the rights to redistribute these changes.
27  */
28
29 /* int64.c - Support for 64-bit integers */
30
31 #include <stdio.h>
32 #include <string.h>
33 #include "intNN.h"
34
35 char *
36 hexify_int64(dt_uint64 * X, char *buf)
37 {
38     static char mybuf[17];
39
40 #ifdef NATIVE_UINT64
41     char c, *p;
42     dt_uint64 x = *X;
43
44     if (!buf)
45         buf = mybuf;
46     p = buf + 16;
47     *p-- = 0;
48     while (x && p >= buf) {
49         c = x & 0xf;
50         c += ((c < 10) ? '0' : 'a' - 10);
51         *p-- = c;
52         x >>= 4;
53     }
54     while (p >= buf)
55         *p-- = '0';
56
57 #else
58     if (!buf)
59         buf = mybuf;
60     sprintf(buf, "%08lx%08lx", (unsigned long)X->hi, (unsigned long)X->lo);
61 #endif
62
63     return buf;
64 }
65
66
67 #ifdef NATIVE_UINT64
68 char *
69 decimate_int64(dt_uint64 * X, char *buf)
70 {
71     static char mybuf[21];
72     char *p;
73     dt_uint64 x = *X;
74
75     if (!buf)
76         buf = mybuf;
77     p = buf + 21;
78     *--p = 0;
79     while (x && p > buf) {
80         *--p = ((x % 10) + '0');
81         x /= 10;
82     }
83     if (!*p)
84         *--p = '0';
85     return p;
86 }
87
88 #else
89 static char bitvals[64][21] = {
90 /*                1 */ "00000000000000000001",
91 /*                2 */ "00000000000000000002",
92 /*                4 */ "00000000000000000004",
93 /*                8 */ "00000000000000000008",
94 /*               10 */ "00000000000000000016",
95 /*               20 */ "00000000000000000032",
96 /*               40 */ "00000000000000000064",
97 /*               80 */ "00000000000000000128",
98 /*              100 */ "00000000000000000256",
99 /*              200 */ "00000000000000000512",
100 /*              400 */ "00000000000000001024",
101 /*              800 */ "00000000000000002048",
102 /*             1000 */ "00000000000000004096",
103 /*             2000 */ "00000000000000008192",
104 /*             4000 */ "00000000000000016384",
105 /*             8000 */ "00000000000000032768",
106 /*            10000 */ "00000000000000065536",
107 /*            20000 */ "00000000000000131072",
108 /*            40000 */ "00000000000000262144",
109 /*            80000 */ "00000000000000524288",
110 /*           100000 */ "00000000000001048576",
111 /*           200000 */ "00000000000002097152",
112 /*           400000 */ "00000000000004194304",
113 /*           800000 */ "00000000000008388608",
114 /*          1000000 */ "00000000000016777216",
115 /*          2000000 */ "00000000000033554432",
116 /*          4000000 */ "00000000000067108864",
117 /*          8000000 */ "00000000000134217728",
118 /*         10000000 */ "00000000000268435456",
119 /*         20000000 */ "00000000000536870912",
120 /*         40000000 */ "00000000001073741824",
121 /*         80000000 */ "00000000002147483648",
122 /*        100000000 */ "00000000004294967296",
123 /*        200000000 */ "00000000008589934592",
124 /*        400000000 */ "00000000017179869184",
125 /*        800000000 */ "00000000034359738368",
126 /*       1000000000 */ "00000000068719476736",
127 /*       2000000000 */ "00000000137438953472",
128 /*       4000000000 */ "00000000274877906944",
129 /*       8000000000 */ "00000000549755813888",
130 /*      10000000000 */ "00000001099511627776",
131 /*      20000000000 */ "00000002199023255552",
132 /*      40000000000 */ "00000004398046511104",
133 /*      80000000000 */ "00000008796093022208",
134 /*     100000000000 */ "00000017592186044416",
135 /*     200000000000 */ "00000035184372088832",
136 /*     400000000000 */ "00000070368744177664",
137 /*     800000000000 */ "00000140737488355328",
138 /*    1000000000000 */ "00000281474976710656",
139 /*    2000000000000 */ "00000562949953421312",
140 /*    4000000000000 */ "00001125899906842624",
141 /*    8000000000000 */ "00002251799813685248",
142 /*   10000000000000 */ "00004503599627370496",
143 /*   20000000000000 */ "00009007199254740992",
144 /*   40000000000000 */ "00018014398509481984",
145 /*   80000000000000 */ "00036028797018963968",
146 /*  100000000000000 */ "00072057594037927936",
147 /*  200000000000000 */ "00144115188075855872",
148 /*  400000000000000 */ "00288230376151711744",
149 /*  800000000000000 */ "00576460752303423488",
150 /* 1000000000000000 */ "01152921504606846976",
151 /* 2000000000000000 */ "02305843009213693952",
152 /* 4000000000000000 */ "04611686018427387904",
153 /* 8000000000000000 */ "09223372036854775808"
154 };
155
156
157 static void
158 prep_table(void)
159 {
160     int bit, digit;
161
162     if (bitvals[0][0] < '0')
163         return;
164     for (bit = 0; bit < 64; bit++)
165         for (digit = 0; digit < 20; digit++)
166             bitvals[bit][digit] -= '0';
167 }
168
169
170 static void
171 add_bit(int bit, char *answer)
172 {
173     int digit;
174
175     for (digit = 19; digit >= 0; digit--) {
176         answer[digit] += bitvals[bit][digit];
177         if (!digit)
178             break;
179         while (answer[digit] > 9) {
180             answer[digit] -= 10;
181             answer[digit - 1]++;
182         }
183     }
184 }
185
186
187 static void
188 decimate(unsigned long hi, unsigned long lo, char *answer)
189 {
190     unsigned long mask;
191     int bit, digit;
192
193     memset(answer, 0, 21);
194     for (bit = 0, mask = 1; bit < 32; bit++, mask <<= 1)
195         if (lo & mask)
196             add_bit(bit, answer);
197     for (bit = 0, mask = 1; bit < 32; bit++, mask <<= 1)
198         if (hi & mask)
199             add_bit(bit + 32, answer);
200
201     for (digit = 0; digit < 20; digit++)
202         answer[digit] += '0';
203 }
204
205 char *
206 decimate_int64(dt_uint64 * X, char *buf)
207 {
208     static char mybuf[21];
209     char *p;
210
211     prep_table();
212     if (!buf)
213         buf = mybuf;
214     decimate(X->hi, X->lo, buf);
215     for (p = buf; *p == '0'; p++);
216     return (*p) ? p : p - 1;
217 }
218
219 #endif /* NATIVE_UINT64 */
220
221
222 void
223 shift_int64(dt_uint64 * X, int bits)
224 {
225 #ifdef NATIVE_UINT64
226     if (bits < 0)
227         *X >>= (-bits);
228     else
229         *X <<= bits;
230 #else
231     if (bits < 0) {
232         bits = -bits;
233         if (bits >= 32) {
234             X->lo = ((X->hi & 0xffffffffL) >> (bits - 32));
235             X->hi = 0;
236         } else {
237             X->lo = ((X->lo & 0xffffffffL) >> bits)
238                 | ((X->hi & ((1 << (32 - bits)) - 1)) << (32 - bits));
239             X->hi = ((X->hi & 0xffffffffL) >> bits);
240         }
241     } else {
242         if (bits >= 32) {
243             X->hi = ((X->lo & 0xffffffffL) << (bits - 32));
244             X->lo = 0;
245         } else {
246             X->hi = ((X->hi & 0xffffffffL) << bits)
247                 | ((X->lo & (((1 << bits) - 1) << (32 - bits))) >>
248                    (32 - bits));
249             X->lo = ((X->lo & 0xffffffffL) << bits);
250         }
251     }
252 #endif
253 }
254
255
256 #ifdef TEST_INT64
257
258 /** the rest of this is for testing the int64 suite **/
259
260 #ifdef NATIVE_UINT64
261
262 #define xize(x) #x
263 #define stringize(x) xize(x)
264 #define INT64_NAME stringize(unsigned NATIVE_UINT64)
265
266
267 #endif /* NATIVE_UINT64 */
268
269
270 void
271 verify_int64_size()
272 {
273 #ifdef NATIVE_UINT64
274     signed char testchar = -1;
275     unsigned int testint = (unsigned char)testchar;
276
277     printf("We think '%s' is a native 64-bit type\n", INT64_NAME);
278
279     if (testint != 0xff) {
280         printf("testint = 0x%x; should be 0xff\n", testint);
281         fprintf(stderr, "Hmm...  char's are not 8 bits.  That sucks!\n");
282         exit(-1);
283     }
284     printf("Looks like a char is 8 bits...\n");
285
286     if (sizeof(unsigned NATIVE_UINT64) != 8) {
287         printf("sizeof(%s) = %d; should be 8\n", INT64_NAME,
288                sizeof(unsigned NATIVE_UINT64));
289         fprintf(stderr, "Hey!  You said a %s was 64-bits wide!\n",
290                 INT64_NAME);
291         exit(-1);
292     }
293     printf("Yippee!  We have a native 64-bit type (%s)\n\n", INT64_NAME);
294
295 #else /* !NATIVE_UINT64 */
296
297     printf("Using fake 64-bit integers...\n\n");
298 #endif /* NATIVE_UINT64 */
299 }
300
301
302 void
303 test_int64_constructs(void)
304 {
305     dt_uint64 x, y;
306     afs_uint32 hi, lo;
307     int failures = 0, pass;
308     char buf[17];
309
310     printf("Constructor/accessor tests:\n");
311     printf("Setting x := %s\n", INT64_TEST_STR);
312     mk64(x, INT64_TEST_HI, INT64_TEST_LO);
313
314 #ifdef NATIVE_UINT64
315     pass = (x == INT64_TEST_CONST);
316     hexify_int64(&x, buf);
317     printf("NATIVE mk64: x       = 0x%16s                %s\n", buf,
318            pass ? "PASSED" : "FAILED");
319     if (!pass)
320         failures++;
321 #else
322     pass = (x.hi == INT64_TEST_HI && x.lo == INT64_TEST_LO);
323     printf("FAKE mk64:   x.hi    = 0x%08lx  x.lo    = 0x%08lx  %s\n", x.hi,
324            x.lo, pass ? "PASSED" : "FAILED");
325     if (!pass)
326         failures++;
327 #endif
328
329     pass = (hi64(x) == INT64_TEST_HI && lo64(x) == INT64_TEST_LO);
330     printf("hi64/lo64:   hi64(x) = 0x%08lx  lo64(x) = 0x%08lx  %s\n", hi64(x),
331            lo64(x), pass ? "PASSED" : "FAILED");
332     if (!pass)
333         failures++;
334
335     ex64(x, hi, lo);
336     pass = (hi == INT64_TEST_HI && lo == INT64_TEST_LO);
337     printf("ex64:        hi      = 0x%08lx  lo      = 0x%08lx  %s\n", hi, lo,
338            pass ? "PASSED" : "FAILED");
339     if (!pass)
340         failures++;
341
342     cp64(y, x);
343     pass = (hi64(y) == INT64_TEST_HI && lo64(y) == INT64_TEST_LO);
344     printf("cp64:        hi64(y) = 0x%08lx  lo64(y) = 0x%08lx  %s\n", hi64(y),
345            lo64(y), pass ? "PASSED" : "FAILED");
346     if (!pass)
347         failures++;
348
349     if (failures)
350         printf("%d/4 tests FAILED\n\n", failures);
351     else
352         printf("All 4 tests PASSED\n\n");
353 }
354
355
356 void
357 test_int64_compares()
358 {
359 #define NCOMPARE 9
360     dt_uint64 control, test[NCOMPARE];
361     char cbuf[17], tbuf[17];
362     int i, r, result[NCOMPARE];
363     int pass, failures, FAILURES = 0;
364
365     printf("Comparison tests:\n");
366
367     mk64(control, 0x12345678, 0xabcdabcd);
368     mk64(test[0], 0x12340000, 0xabcd0000);
369     result[0] = +1;
370     mk64(test[1], 0x12340000, 0xabcdabcd);
371     result[1] = +1;
372     mk64(test[2], 0x12340000, 0xabcdffff);
373     result[2] = +1;
374     mk64(test[3], 0x12345678, 0xabcd0000);
375     result[3] = +1;
376     mk64(test[4], 0x12345678, 0xabcdabcd);
377     result[4] = 0;
378     mk64(test[5], 0x12345678, 0xabcdffff);
379     result[5] = -1;
380     mk64(test[6], 0x1234ffff, 0xabcd0000);
381     result[6] = -1;
382     mk64(test[7], 0x1234ffff, 0xabcdabcd);
383     result[7] = -1;
384     mk64(test[8], 0x1234ffff, 0xabcdffff);
385     result[8] = -1;
386
387     for (i = 0; i < NCOMPARE; i++) {
388         failures = 0;
389         hexify_int64(&control, cbuf);
390         hexify_int64(&test[i], tbuf);
391
392         r = eq64(control, test[i]);
393         pass = (r == (result[i] == 0));
394         if (!pass)
395             failures++;
396         printf("0x%s == 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
397
398         r = ne64(control, test[i]);
399         pass = (r == (result[i] != 0));
400         if (!pass)
401             failures++;
402         printf("0x%s != 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
403
404         r = lt64(control, test[i]);
405         pass = (r == (result[i] < 0));
406         if (!pass)
407             failures++;
408         printf("0x%s <  0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
409
410         r = le64(control, test[i]);
411         pass = (r == (result[i] <= 0));
412         if (!pass)
413             failures++;
414         printf("0x%s <= 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
415
416         r = gt64(control, test[i]);
417         pass = (r == (result[i] > 0));
418         if (!pass)
419             failures++;
420         printf("0x%s >  0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
421
422         r = ge64(control, test[i]);
423         pass = (r == (result[i] >= 0));
424         if (!pass)
425             failures++;
426         printf("0x%s >= 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
427
428         r = zero64(test[i]);
429         pass = !r;
430         if (!pass)
431             failures++;
432         printf("0x%s is nonzero            %s\n", tbuf,
433                pass ? "PASSED" : "FAILED");
434
435         if (failures)
436             printf("%d/7 tests on this pair FAILED\n\n", failures);
437         else
438             printf("All 7 tests on this pair PASSED\n\n");
439     }
440
441     mk64(control, 0, 0);
442     pass = zero64(control);
443     if (!pass)
444         FAILURES++;
445     printf("0x0000000000000000 is zero               %s\n",
446            pass ? "PASSED" : "FAILED");
447
448     if (FAILURES)
449         printf("%d/%d comparison tests FAILED\n\n", FAILURES,
450                7 * NCOMPARE + 1);
451     else
452         printf("All %d comparison tests PASSED\n\n", 7 * NCOMPARE + 1);
453 }
454
455
456 void
457 test_int64_arith()
458 {
459     printf("No arithmetic tests yet!!!\n");
460 }
461
462
463 void
464 main()
465 {
466     verify_int64_size();
467     test_int64_constructs();
468     test_int64_compares();
469     test_int64_arith();
470     exit(0);
471 }
472 #endif