*** /dev/null Sat Nov 23 01:07:49 2024
--- - Sat Nov 23 01:07:59 2024
***************
*** 0 ****
--- 1,274 ----
+ /*
+ ** OSSP ui64 - 64-Bit Arithmetic
+ ** Copyright (c) 2002 Ralf S. Engelschall <rse@engelschall.com>
+ ** Copyright (c) 2002 The OSSP Project <http://www.ossp.org/>
+ ** Copyright (c) 2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
+ **
+ ** 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 <stdio.h>
+ #include <stdlib.h>
+ #include <time.h>
+
+ #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: 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: 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;
+ }
+
|