Skip to content

Commit

Permalink
[ISSUE-0082]: tests on bigdecimal order of magnitude.
Browse files Browse the repository at this point in the history
  • Loading branch information
SzigetiJ committed Jan 26, 2024
1 parent fa3307d commit 94a7975
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 4 deletions.
6 changes: 3 additions & 3 deletions src/bigdecimal128.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ static inline buint_bool gen_common_loprec_safe_(UInt *aprec, UInt *bprec, BigUI
static inline UInt oom_estimation_(UInt base, UInt corr_step, UInt prec, const BigUInt128 *val) {
buint_size_t lzb = biguint128_lzb(val);
buint_size_t correction = lzb / corr_step;
return base + 3 + 10 * prec - 3 * lzb - correction;
return base + 10 * prec - 3 * lzb - correction;
}

static inline UInt oom_lb_(UInt prec, const BigUInt128 *val) {
return oom_estimation_(3 * 128, 96, prec, val);
return oom_estimation_(4 * 128, 96, prec, val);
}

/**
Expand All @@ -102,7 +102,7 @@ static inline UInt oom_lb_(UInt prec, const BigUInt128 *val) {
* @return
*/
static inline UInt oom_ub_(UInt prec, const BigUInt128 *val) {
return oom_estimation_(3 * 128 + 3, 100, prec, val);
return oom_estimation_(4 * 128 + 3, 100, prec, val);
}

/**
Expand Down
9 changes: 8 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ TESTS = \
bigdecimal128_mul_test \
bigdecimal128_eq_test \
bigdecimal128_pval_test \
bigdecimal128_oom_test \
bigdecimal128_prec_test

check_PROGRAMS = $(TESTS)
Expand All @@ -29,7 +30,8 @@ if WITH_BIGUINT256
biguint@bits256@_bit_test \
biguint@bits256@_add_test \
biguint@bits256@_mul_test \
bigdecimal@bits256@_io_test
bigdecimal@bits256@_io_test \
bigdecimal@bits256@_oom_test

TESTS += $(ADDITIONAL256)
check_PROGRAMS += $(ADDITIONAL256)
Expand Down Expand Up @@ -74,6 +76,9 @@ biguint256_mul_test.c: biguint128_mul_test.c
bigdecimal256_io_test.c: bigdecimal128_io_test.c
$(SED) 's/128/256/g' < $< > $@

bigdecimal256_oom_test.c: bigdecimal128_oom_test.c
$(SED) 's/128/256/g' < $< > $@

test_common256.c: test_common128.c
$(SED) 's/128/256/g' < $< > $@

Expand All @@ -86,6 +91,7 @@ test_common256.h: test_common128.h
biguint@bits256@_add_test_LDADD = test_common.o test_common256.o ../src/libbiguint.a
biguint@bits256@_bit_test_LDADD = test_common.o test_common256.o ../src/libbiguint.a
bigdecimal@bits256@_io_test_LDADD = test_common.o ../src/libbiguint.a
bigdecimal@bits256@_oom_test_LDADD = test_common.o ../src/libbiguint.a

DISTCLEANFILES += $(DEPDIR)/test_common256.Po
endif
Expand All @@ -101,6 +107,7 @@ biguint128_mul_test_LDADD = test_common.o test_common128.o ../src/libbiguint.a
biguint128_add_test_LDADD = test_common.o test_common128.o ../src/libbiguint.a
biguint128_bit_test_LDADD = test_common.o test_common128.o ../src/libbiguint.a
bigdecimal128_io_test_LDADD = test_common.o ../src/libbiguint.a
bigdecimal128_oom_test_LDADD = test_common.o ../src/libbiguint.a
bigdecimal128_prec_test_LDADD = test_common.o ../src/libbiguint.a

SUBDIRS=performance
123 changes: 123 additions & 0 deletions tests/bigdecimal128_oom_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**********************************************
* Checks the oom estimation on consecutive
* numbers with many different precision values.
* We estimate oom(a) with a range: oomrng(a)
* (lower and upper bound).
* There are two properties to assure:
* - if a is lower than b, oomrng(a) must not be lower
* than oomrng(b).
* - if a equals to b (but has different precision),
* oomrng(a) must not be lower than oomrng(b) and
* oomrng(a) must not be higher than oomrng(b).
* Here, 'must not be lower' means that the upper bound of
* 'a' is not allowed to be lower than the lower bound of 'b'.
* 'Must not be higher' is defined in a similar way.
* This test accepts command line arguments:
* [$1]: test range (given in bits, default: 16,
* i.e., 2^16 numbers are tested).
* [$2]: precision range (starting at 0,
* default: ~max valid precision).
* [$3]: test range begin point (given in bits,
* default: 0, i.e., test begins with value '1').
**********************************************/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#include "bigdecimal128.h"
#include "test_common.h"

#define DEFAULT_LIMIT_BITS 16
#define DEFAULT_LIMIT_PREC ((128 - DEFAULT_LIMIT_BITS) * 3 / 10) // altogether we are still below biguint limit

// copied from bigdecimal128.c
static inline UInt oom_estimation_(UInt base, UInt corr_step, UInt prec, const BigUInt128 *val) {
buint_size_t lzb = biguint128_lzb(val);
buint_size_t correction = lzb / corr_step;
return base + 10 * prec - 3 * lzb - correction;
}

static inline UInt oom_lb_(UInt prec, const BigUInt128 *val) {
return oom_estimation_(4 * 128, 96, prec, val);
}

static inline UInt oom_ub_(UInt prec, const BigUInt128 *val) {
return oom_estimation_(4 * 128 + 3, 100, prec, val);
}
// copy end

bool test_oom(const BigUInt128 *a, int maxprec, bool has_predecessor, UInt *lowest_ub, UInt *highest_lb) {
bool pass = true;
UInt lowest_ub_val;
int lowest_ub_at;
UInt highest_lb_val;
int highest_lb_at;
BigUInt128 ai = *a;
for (int i = 0; i < maxprec; ++i) {
UInt lbi = oom_lb_(i, &ai);
UInt ubi = oom_ub_(i, &ai);
if (i == 0 || highest_lb_val < lbi) {
highest_lb_at = i;
highest_lb_val = lbi;
}
if (i == 0 || ubi < lowest_ub_val) {
lowest_ub_at = i;
lowest_ub_val = ubi;
}
ai = biguint128_mul10(&ai);
}
if (lowest_ub_val < highest_lb_val) {
char buf[128 + 1];
buf[biguint128_print_dec(a, buf, 128)] = 0;
fprintf(stderr, "OOM failed for %s. ub@%d: %d, lb@%d: %d\n", buf, lowest_ub_at, (int) lowest_ub_val, highest_lb_at, (int) highest_lb_val);
pass = false;
}
if (has_predecessor) { // check relation to neighbor oom value
// current number is higher than the neighbor, i.e., current oom cannot be higher.
if (*lowest_ub < highest_lb_val) {
char buf[128 + 1];
buf[biguint128_print_dec(a, buf, 128)] = 0;
fprintf(stderr, "OOM failed for %s. ub@%d: %d, former lb: %d\n", buf, lowest_ub_at, (int) lowest_ub_val, (int) *highest_lb);
pass = false;
}
}

*lowest_ub = lowest_ub_val;
*highest_lb = highest_lb_val;

return pass;
}

int main(int argc, const char *argv[]) {
int limit_bits = DEFAULT_LIMIT_BITS;
int limit_prec = DEFAULT_LIMIT_PREC;
BigUInt128 a = biguint128_ctor_unit();
if (1 < argc) { // test range given in power of 2.
limit_bits = atoi(argv[1]);
}
if (2 < argc) { // precision depth
limit_prec = atoi(argv[2]);
}
if (3 < argc) { // ai offset given in power of 2.
a = biguint128_shl(&a, atoi(argv[3]));
}

BigUInt128 lim = biguint128_ctor_unit();
biguint128_shl_tiny(&lim, limit_bits);
biguint128_add_assign(&lim, &a);
UInt lowest_ub;
UInt highest_lb;
int i = 0;
while (biguint128_lt(&a, &lim)) {
if ((i & 0xFFFF) == 0) { // show progress
fprintf(stderr, ".");
}
assert(test_oom(&a, limit_prec, i != 0, &lowest_ub, &highest_lb));
biguint128_inc(&a);
++i;
}

return 0;
}

0 comments on commit 94a7975

Please sign in to comment.