ossp-pkg/ui64/ui64_test.c
/*
** OSSP ui64 - 64-Bit Arithmetic
** Copyright (c) 2002-2005 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 2002-2005 The OSSP Project <http://www.ossp.org/>
**
** 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: 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;
}