OSSP CVS Repository

ossp - ossp-pkg/ui64/ui64_test.c
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

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;
}


CVSTrac 2.0.1