/* ** OSSP ui64 - 64-Bit Arithmetic ** Copyright (c) 2002-2005 Ralf S. Engelschall ** Copyright (c) 2002-2005 The OSSP Project ** ** This file is part of OSSP ui64, a 64-bit arithmetic library ** which can be found at http://www.ossp.org/pkg/lib/ui64/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** ui64_test.c: test suite */ #include #include #include #include "ts.h" #include "ui64.h" TS_TEST(test_imex_num) { struct { unsigned int num; } table[] = { { 0 }, /* minimum value */ { 255 }, /* 2^8 - 1 */ { 256 }, /* 2^8 */ { 257 }, /* 2^8 + 1 */ { 4294967295U }, /* 2^32 - 1 */ }; int i; ui64_t x; unsigned long n; ts_test_check(TS_CTX, "import/export via number"); for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { x = ui64_n2i(table[i].num); n = ui64_i2n(x); if (n != table[i].num) { ts_test_fail(TS_CTX, "input %d, " "expected output %d, got output %d", table[i].num, table[i].num, n); } } } TS_TEST(test_imex_str) { struct { int in_base; char *in_str; int out_base; char *out_str; } table[] = { { 16, "0", 10, "0" }, /* minimum value */ { 16, "ff", 10, "255" }, /* 2^8 - 1 */ { 16, "100", 10, "256" }, /* 2^8 */ { 16, "101", 10, "257" }, /* 2^8 + 1 */ { 16, "ffffffff", 10, "4294967295" }, /* 2^32 - 1 */ { 16, "100000000", 10, "4294967296" }, /* 2^32 */ { 16, "100000001", 10, "4294967297" }, /* 2^32 + 1 */ { 16, "ffffffffffffffff", 10, "18446744073709551615" } /* 2^64 - 1 */ }; int i; ui64_t x; char buf[128]; char *cp; ts_test_check(TS_CTX, "import/export via string"); for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { /* import/export input */ x = ui64_s2i(table[i].in_str, NULL, table[i].in_base); cp = ui64_i2s(x, buf, sizeof(buf), table[i].in_base); if (strcasecmp(table[i].in_str, cp) != 0) { ts_test_fail(TS_CTX, "input \"%s\" (%d), " "expected output \"%s\" (%d), got output \"%s\" (%d)", table[i].in_str, table[i].in_base, table[i].in_str, table[i].in_base, cp, table[i].in_base); } /* import/export output */ x = ui64_s2i(table[i].out_str, NULL, table[i].out_base); cp = ui64_i2s(x, buf, sizeof(buf), table[i].out_base); if (strcasecmp(table[i].out_str, cp) != 0) { ts_test_fail(TS_CTX, "input \"%s\" (%d), " "expected output \"%s\" (%d), got output \"%s\" (%d)", table[i].out_str, table[i].out_base, table[i].out_str, table[i].out_base, cp, table[i].out_base); } /* import input, export output */ x = ui64_s2i(table[i].in_str, NULL, table[i].in_base); cp = ui64_i2s(x, buf, sizeof(buf), table[i].out_base); if (strcasecmp(table[i].out_str, cp) != 0) { ts_test_fail(TS_CTX, "input \"%s\" (%d), " "expected output \"%s\" (%d), got output \"%s\" (%d)", table[i].in_str, table[i].in_base, table[i].out_str, table[i].out_base, cp, table[i].out_base); } } } TS_TEST(test_arithmetic) { int i; ui64_t a1, a2, re, ov; char re_a[128]; char *re_s; char ov_a[128]; char *ov_s; struct { char *a1; char *op; char *a2; char *re; char *ov; } table[] = { /* addition */ { "0", "+", "0", "0", "0" }, { "1", "+", "2", "3", "0" }, { "255", "+", "1", "256", "0" }, { "255", "+", "2", "257", "0" }, { "4294967296", "+", "4294967295", "8589934591", "0" }, { "4294967296", "+", "4294967296", "8589934592", "0" }, { "18446744073709551615", "+", "0", "18446744073709551615", "0" }, { "18446744073709551615", "+", "1", "0", "1" }, { "18446744073709551615", "+", "18446744073709551615", "18446744073709551614", "1" }, /* subtraction */ { "0", "-", "0", "0", "0" }, { "3", "-", "2", "1", "0" }, { "4294967296", "-", "4294967296", "0", "0" }, { "18446744073709551615", "-", "0", "18446744073709551615", "0" }, { "18446744073709551615", "-", "18446744073709551615", "0", "0" }, { "0", "-", "1", "18446744073709551615", "1" }, { "0", "-", "18446744073709551615", "1", "1" }, /* multiplication */ { "0", "*", "0", "0", "0" }, { "7", "*", "7", "49", "0" }, { "4294967296", "*", "4294967295", "18446744069414584320", "0" }, { "4294967296", "*", "4294967296", "0", "1" }, { "4294967296", "*", "4294967297", "4294967296", "1" }, { "1", "*", "18446744073709551615", "18446744073709551615", "0" }, { "18446744073709551615", "*", "1", "18446744073709551615", "0" }, { "2", "*", "18446744073709551615", "18446744073709551614", "1" }, { "3", "*", "18446744073709551615", "18446744073709551613", "2" }, { "4", "*", "18446744073709551615", "18446744073709551612", "3" }, /* division */ { "0", "/", "0", "0", "0" }, { "0", "/", "7", "0", "0" }, { "1", "/", "1", "1", "0" }, { "6", "/", "3", "2", "0" }, { "7", "/", "3", "2", "1" }, { "4096", "/", "8192", "0", "4096" }, { "65536", "/", "252", "260", "16" }, { "4294967296", "/", "4294967296", "1", "0" }, { "18446744073709551615", "/", "1", "18446744073709551615", "0" }, { "18446744073709551615", "/", "18446744073709551615", "1", "0" }, { "18000000000000000000", "/", "9000000000000000000", "2", "0" }, { "18000000000000000000", "/", "42", "428571428571428571", "18" }, { "18446744073709551615", "/", "4294967295", "4294967297", "0" }, { "18446744073709551615", "/", "4294967296", "4294967295", "4294967295" } }; ts_test_check(TS_CTX, "arithmetic operations"); for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { a1 = ui64_s2i(table[i].a1, NULL, 10); a2 = ui64_s2i(table[i].a2, NULL, 10); switch (table[i].op[0]) { case '+': re = ui64_add(a1, a2, &ov); break; case '-': re = ui64_sub(a1, a2, &ov); break; case '*': re = ui64_mul(a1, a2, &ov); break; case '/': re = ui64_div(a1, a2, &ov); break; default: re = ui64_zero(); break; } re_s = ui64_i2s(re, re_a, sizeof(re_a), 10); ov_s = ui64_i2s(ov, ov_a, sizeof(ov_a), 10); if ( strcasecmp(re_s, table[i].re) != 0 || strcasecmp(ov_s, table[i].ov) != 0) { ts_test_fail(TS_CTX, "%s %s %s = (expected) %s [%s] != %s [%s] (got)", table[i].a1, table[i].op, table[i].a2, table[i].re, table[i].ov, re_s, ov_s); } } } TS_TEST(test_rotate) { int i; ui64_t a1, re, ov; int a2; char re_a[128]; char *re_s; char ov_a[128]; char *ov_s; struct { char *a1; char *op; int a2; char *re; char *ov; } table[] = { /* rotate left */ { "0", "<", 0, "0", "0" }, { "1", "<", 1, "2", "0" }, { "2", "<", 2, "8", "0" }, { "4294967296", "<", 16, "281474976710656", "0" }, { "4294967296", "<", 17, "562949953421312", "0" }, { "4294967296", "<", 18, "1125899906842624", "0" }, { "18446744073709551615", "<", 64, "0", "18446744073709551615" }, { "18446744073709551615", "<", 32, "18446744069414584320", "4294967295" }, /* rotate right */ { "0", ">", 0, "0", "0" }, { "1", ">", 1, "0", "9223372036854775808" }, { "4", ">", 2, "1", "0" }, { "4294967296", ">", 16, "65536", "0" }, { "4294967295", ">", 16, "65535", "18446462598732840960" } }; ts_test_check(TS_CTX, "rotate operations"); for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { a1 = ui64_s2i(table[i].a1, NULL, 10); a2 = table[i].a2; switch (table[i].op[0]) { case '<': re = ui64_rol(a1, a2, &ov); break; case '>': re = ui64_ror(a1, a2, &ov); break; default: re = ui64_zero(); break; } re_s = ui64_i2s(re, re_a, sizeof(re_a), 10); ov_s = ui64_i2s(ov, ov_a, sizeof(ov_a), 10); if ( strcasecmp(re_s, table[i].re) != 0 || strcasecmp(ov_s, table[i].ov) != 0) { ts_test_fail(TS_CTX, "%s %s %d = (expected) %s [%s] != %s [%s] (got)", table[i].a1, table[i].op, table[i].a2, table[i].re, table[i].ov, re_s, ov_s); } } } int main(int argc, char *argv[]) { ts_suite_t *ts; int n; ts = ts_suite_new("OSSP ui64 (64-Bit Arithmetic)"); ts_suite_test(ts, test_imex_num, "import/export via number"); ts_suite_test(ts, test_imex_str, "import/export via string"); ts_suite_test(ts, test_arithmetic, "arithmetical operations"); ts_suite_test(ts, test_rotate, "bit-wise rotation"); n = ts_suite_run(ts); ts_suite_free(ts); return n; }