Skip to content

Commit

Permalink
[ISSUE-0090]: bigint abs(x) function
Browse files Browse the repository at this point in the history
  • Loading branch information
SzigetiJ committed Jan 30, 2024
1 parent 9bccc32 commit 64b3259
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 32 deletions.
36 changes: 14 additions & 22 deletions src/bigdecimal128.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,9 @@ static buint_bool compare_(const BigDecimal128 *a, const BigDecimal128 *b, buint
// at this point ltz(a)==ltz(b) is sure.

// check #2: order of magnitude
BigUInt128 av = a->val;
BigUInt128 bv = b->val;
if (altz) {
bigint128_negate_assign(&av);
bigint128_negate_assign(&bv);
}
BigUInt128 av = bigint128_abs(&a->val, NULL);
BigUInt128 bv = bigint128_abs(&b->val, NULL);

UInt ooma_lo = oom_lb_(a->prec, &av);
UInt ooma_hi = oom_ub_(a->prec, &av);
UInt oomb_lo = oom_lb_(b->prec, &bv);
Expand Down Expand Up @@ -237,16 +234,11 @@ static inline buint_bool addsub_safe_(BigDecimal128 *dest, const BigDecimal128 *
fun[!add](&dest->val, &a->val, &b->val, &carry);
dest->prec = a->prec;
} else {
BigDecimal128 av = *a;
BigDecimal128 bv = *b;
buint_bool altz = bigint128_ltz(&a->val);
buint_bool bltz = bigint128_ltz(&b->val);
if (altz) {
bigint128_negate_assign(&av.val);
}
if (bltz) {
bigint128_negate_assign(&bv.val);
}
buint_bool altz;
buint_bool bltz;
BigDecimal128 av = {bigint128_abs(&a->val, &altz),a->prec};
BigDecimal128 bv = {bigint128_abs(&b->val, &bltz),b->prec};

retv = gen_common_hiprec_safe_(&av.prec, &bv.prec, &av.val, &bv.val);
fun[!add != (altz != bltz)](&dest->val, &av.val, &bv.val, &carry);
if (altz) {
Expand Down Expand Up @@ -289,14 +281,14 @@ BigDecimal128 bigdecimal128_ctor_prec(const BigDecimal128 *a, UInt prec) {
}

buint_bool bigdecimal128_prec_safe(BigDecimal128 *dest, const BigDecimal128 *a, UInt prec) {
*dest = *a;
if (bigint128_ltz(&a->val)) {
bigint128_negate_assign(&dest->val);
buint_bool retv = tune_prec_(&dest->val, &dest->prec, prec, NULL);
buint_bool altz;
dest->val = bigint128_abs(&a->val, &altz);
dest->prec = a->prec;
buint_bool retv = tune_prec_(&dest->val, &dest->prec, prec, NULL);
if (altz) {
bigint128_negate_assign(&dest->val);
return retv;
}
return tune_prec_(&dest->val, &dest->prec, prec, NULL);
return retv;
}

BigDecimal128 bigdecimal128_add(const BigDecimal128 *a, const BigDecimal128 *b) {
Expand Down
31 changes: 21 additions & 10 deletions src/biguint128.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,25 @@ BigUInt128 bigint128_negate(const BigUInt128 *a) {
return retv;
}

BigUInt128 bigint128_abs(const BigUInt128 *a, buint_bool *result_inv) {
buint_bool inv = bigint128_ltz(a);
if (result_inv != NULL) {
*result_inv = inv;
}
return inv ? bigint128_negate(a) : *a;
}

BigUInt128 *bigint128_abs_assign(BigUInt128 *a, buint_bool *result_inv) {
buint_bool inv = bigint128_ltz(a);
if (result_inv != NULL) {
*result_inv = inv;
}
if (inv) {
bigint128_negate_assign(a);
}
return a;
}

// END SUB //
///////////////

Expand Down Expand Up @@ -855,17 +874,9 @@ BigUIntPair128 biguint128_div(const BigUInt128 *a, const BigUInt128 *b) {
}

BigUIntPair128 bigint128_div(const BigUInt128 *a, const BigUInt128 *b) {
buint_bool neg[2];
// work with copies
BigUInt128 ab[] = {biguint128_ctor_copy(a), biguint128_ctor_copy(b)};
// check signs
buint_bool neg[] = {is_bigint_negative_(a), is_bigint_negative_(b)};
// convert
for (unsigned int i = 0U; i<2; ++i) {
if (neg[i]) {
biguint128_dec(&ab[i]);
biguint128_not_assign(&ab[i]);
}
}
BigUInt128 ab[] = {bigint128_abs(a, &neg[0]), bigint128_abs(b, &neg[1])};

// calling the wrapped function
BigUIntPair128 retv = biguint128_div(&ab[0], &ab[1]);
Expand Down
2 changes: 2 additions & 0 deletions src/biguint128.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ void biguint128_sbc_replace(BigUInt128 *dest, const BigUInt128 *a, const BigUInt
*/
BigUInt128 bigint128_negate(const BigUInt128 *a);
BigUInt128 *bigint128_negate_assign(BigUInt128 *a);
BigUInt128 bigint128_abs(const BigUInt128 *a, buint_bool *result_inv);
BigUInt128 *bigint128_abs_assign(BigUInt128 *a, buint_bool *result_inv);

/**
@brief Sub-assignment of UInt to biguint.
Expand Down
53 changes: 53 additions & 0 deletions tests/biguint128_eq_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ CStr samplex[][SAMPLEX_W]= {
{STR("1"), STR("1"), STR("0"), STR("0"), STR("1")}
};

#define SAMPLEY_W 3U
// a, b, lt, ilt, eq
CStr sampley[][SAMPLEY_W]= {
{STR("0"), STR("0"), STR("0")},
{STR("1"), STR("1"), STR("0")},
{STR("-1"), STR("1"), STR("1")},
{STR("-0"), STR("0"), STR("0")}
};

#define SAMPLEZ_W 3U
// a, ltz, eqz
CStr samplez[][SAMPLEZ_W]={
Expand All @@ -34,6 +43,48 @@ CStr samplez[][SAMPLEZ_W]={
};
const unsigned int samplez_len = ARRAYSIZE(samplez);

bool test_abs() {
bool pass = true;
for (unsigned int i=0; i<ARRAYSIZE(sampley); ++i) {
unsigned int idx[]={0,1,2};
BigUInt128 ti[SAMPLEY_W];
read_more_cstr_biguint128(ti, &sampley[i][0], idx, SAMPLEY_W, FMT_SDEC);
buint_bool exp_inv = (ti[2].dat[0]==1);
buint_bool res_inv0;
BigUInt128 arg1 = ti[0];
buint_bool res_inv1;
BigUInt128 arg2 = ti[0];

BigUInt128 res0 = bigint128_abs(&ti[0], &res_inv0);
BigUInt128 *res1 = bigint128_abs_assign(&arg1, &res_inv1);
BigUInt128 *res2 = bigint128_abs_assign(&arg2, NULL);

if (!biguint128_eq(&res0, &ti[1])) {
fprintf(stderr, "abs(x) result mismatch\n");
pass = false;
}
if (!!exp_inv != !!res_inv0) {
fprintf(stderr, "abs(x) result_inv mismatch\n");
pass = false;
}

if (!biguint128_eq(res1, &ti[1]) || res1 != &arg1) {
fprintf(stderr, "abs_assign(x) result mismatch\n");
pass = false;
}
if (!!exp_inv != !!res_inv1) {
fprintf(stderr, "abs_assign(x) result_inv mismatch\n");
pass = false;
}

if (!biguint128_eq(res2, &ti[1]) || res2 != &arg2) {
fprintf(stderr, "abs_assign(x) result mismatch\n");
pass = false;
}
}
return pass;
}

int main() {
unsigned int lt_params[] = {0, 1, 2};
unsigned int ilt_params[] = {0, 1, 3};
Expand All @@ -59,5 +110,7 @@ int main() {
assert(test_genfun(&samplez[0][0], SAMPLEZ_W, samplez_len, FMT_SDEC, eqz_params, XUREL0V(biguint128_eqzv), "eqzv", NULL) == 0);
#endif

assert(test_abs());

return 0;
}

0 comments on commit 64b3259

Please sign in to comment.