Skip to content

Commit

Permalink
Add more testing and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Naoki Shibata committed May 23, 2024
1 parent 4d9a29c commit a63b539
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 65 deletions.
3 changes: 2 additions & 1 deletion doxygen.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ EXCLUDE_PATTERNS = test* */util/* auxiliary.hpp suppress.hpp tlfloatutil.h
EXCLUDE_SYMBOLS = *::detail yarray LCG64 RNG PSHA2_256_Internal CryptUtil tlfloat_bigint* \
BigUInt*<*6*> *toHexString to_string_d \
TLFloat*::getUnpacked detail::UnpackedFloat \
TLFLOAT_OVERLOAD_OP2 TLFLOAT_OVERLOAD_CMP
TLFLOAT_OVERLOAD_OP2 TLFLOAT_OVERLOAD_CMP TLFLOAT_OVERLOAD_CMPQ \
TLFLOAT_OVERLOAD_OP2I TLFLOAT_OVERLOAD_CMPI TLFLOAT_OVERLOAD_OP2Q
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
Expand Down
66 changes: 63 additions & 3 deletions src/include/testerutil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,18 @@ float rndf(shared_ptr<RNG> rng) {
}
}

bool cmpf(float x, float y, int t=0) {
if (isnan(x) && isnan(y)) return true;
uint32_t u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(int32_t(u) - int32_t(v));
return -t <= d && d <= t;
}

double rndd(shared_ptr<RNG> rng) {
uint64_t r = rng->nextLT(1000);

Expand Down Expand Up @@ -728,8 +740,20 @@ double rndd(shared_ptr<RNG> rng) {
}
}

bool cmpd(double x, double y, int t=0) {
if (isnan(x) && isnan(y)) return true;
uint64_t u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(int64_t(u) - int64_t(v));
return -t <= d && d <= t;
}

#ifdef __TLFLOAT_HPP_INCLUDED__
Quad rndq_(shared_ptr<RNG> rng) {
Quad rndQ(shared_ptr<RNG> rng) {
uint64_t r = rng->nextLT(1000);

if (r == 0) {
Expand Down Expand Up @@ -769,13 +793,37 @@ Quad rndq_(shared_ptr<RNG> rng) {
}

#ifdef ENABLE_QUAD
quad rndq(shared_ptr<RNG> rng) { return (quad)rndq_(rng); }
quad rndq(shared_ptr<RNG> rng) { return (quad)rndQ(rng); }
typedef quad quad_;

bool cmpq(quad x, quad y, int t=0) {
if (isnanq(x) && isnanq(y)) return true;
BigUInt<7> u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(BigInt<7>(u) - BigInt<7>(v));
return -t <= d && d <= t;
}
#else
Quad rndq(shared_ptr<RNG> rng) { return rndq_(rng); }
typedef Quad quad_;
quad_ rndq(shared_ptr<RNG> rng) { return rndQ(rng); }
#endif

bool cmpq(Quad x, Quad y, int t=0) {
if (isnan(x) && isnan(y)) return true;
BigUInt<7> u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(BigInt<7>(u) - BigInt<7>(v));
return -t <= d && d <= t;
}

Octuple rndo(shared_ptr<RNG> rng) {
uint64_t r = rng->nextLT(1000);

Expand Down Expand Up @@ -814,6 +862,18 @@ Octuple rndo(shared_ptr<RNG> rng) {
}
}
}

bool cmpo(Octuple x, Octuple y, int t=0) {
if (isnan(x) && isnan(y)) return true;
BigUInt<8> u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(BigInt<8>(u) - BigInt<8>(v));
return -t <= d && d <= t;
}
#endif // #ifdef __TLFLOAT_HPP_INCLUDED__

template<typename T>
Expand Down
16 changes: 15 additions & 1 deletion src/include/tlfloat/bigint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,22 @@ namespace tlfloat {

//

constexpr BigUInt(const char *p, const char **endptr = nullptr, const int base = 10) {
constexpr BigUInt(const char *p, const char **endptr = nullptr, const int base_ = 10) {
while(*p == ' ') p++;
int base = base_;
if (base_ == 0) {
if (*p == '0') {
if (*(p+1) == 'x') {
base = 16;
p += 2;
} else {
base = 8;
p++;
}
} else base = 10;
}
if (base < 2 || base > 36) { low = high = 0; return; }

BigUInt r;
uint64_t u = 0, d = 1;
while(*p != '\0') {
Expand Down
56 changes: 41 additions & 15 deletions src/include/tlfloat/tlfloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ extern "C" {
typedef __int128_t tlfloat_int128_t_;
typedef __uint128_t tlfloat_uint128_t_;
#else
/** tlfloat_int128_t_ and tlfloat_uint128_t_ are types for handling
* 128-bit integer numbers in C. The data size and data structure of
* these types are the same as ordinary integer types. These are POD
* types that can be safely passed with C ABI. If the compiler
* supports __int128_t and __uint128_t, these type are aliases for
* those types. */
typedef struct { uint64_t e[1 << 1]; } tlfloat_int128_t_;
typedef struct { uint64_t e[1 << 1]; } tlfloat_uint128_t_;
#endif
Expand All @@ -41,7 +47,7 @@ extern "C" {
/** This type is for handling quadruple-precision IEEE floating-point
* numbers in C. The data size and data structure of this type are the
* same as a quad-precision floating-point number. This is a POD type
* that can be safely passed with C ABI. If the comipler supports
* that can be safely passed with C ABI. If the compiler supports
* __float128, this type is an alias for __float128. When compling
* with a compiler on which long double is IEEE float 128, this type
* is an alias for long double. */
Expand Down Expand Up @@ -592,13 +598,13 @@ extern "C" {
#endif

#if (defined(__cplusplus) && !defined(TLFLOAT_COMPILER_SUPPORTS_FLOAT128) && !defined(TLFLOAT_LONGDOUBLE_IS_FLOAT128)) || defined(TLFLOAT_DOXYGEN)
/** This type is for handling quadruple-precision IEEE floating-point
* numbers in C and C++11. The data size and data structure of this
* type are the same as a quad-precision floating-point number. When
* compling C code, this type is an alias for tlfloat_quad_. When
* compling C++ code without IEEE float 128 support, this is a struct
* encapsulating a tlfloat_quad_ variable with operators
* overloaded. */
/** tlfloat_quad is a trivially copyable type for handling
* quadruple-precision IEEE floating-point numbers in C and C++11. The
* data size and data structure of this type are the same as a
* quad-precision floating-point number. When compling C code, this
* type is an alias for tlfloat_quad_. When compling C++ code without
* IEEE float 128 support, this is a struct encapsulating a
* tlfloat_quad_ variable with operators overloaded. */
struct tlfloat_quad {
tlfloat_quad_ value;

Expand Down Expand Up @@ -643,19 +649,22 @@ struct tlfloat_quad {
bool operator> (const tlfloat_quad& rhs) const { return tlfloat_gt_q_q(value, rhs.value); }
bool operator>=(const tlfloat_quad& rhs) const { return tlfloat_ge_q_q(value, rhs.value); }
};

/** This macro is defined iff tlfloat_quad is not an alias of
__float128, but a struct defined in tlfloat.h. */
#define TLFLOAT_QUAD_IS_STRUCT
#else // #if (defined(__cplusplus) && !defined(TLFLOAT_COMPILER_SUPPORTS_FLOAT128) && !defined(TLFLOAT_LONGDOUBLE_IS_FLOAT128)) || defined(TLFLOAT_DOXYGEN)
typedef tlfloat_quad_ tlfloat_quad;
#endif

#if defined(__cplusplus) || defined(TLFLOAT_DOXYGEN)
/** This type is for handling octuple-precision IEEE floating-point
* numbers in C and older C++11. The data size and data structure of
* this type are the same as an octuple-precision floating-point
* number. When compling C code, this type is an alias for
* tlfloat_octuple_. When compling C++ code, this is a struct
* encapsulating a tlfloat_octuple_ variable with operators
* overloaded. */
/** tlfloat_octuple is a trivially copyable type for handling
* octuple-precision IEEE floating-point numbers in C and older
* C++11. The data size and data structure of this type are the same
* as an octuple-precision floating-point number. When compling C
* code, this type is an alias for tlfloat_octuple_. When compling C++
* code, this is a struct encapsulating a tlfloat_octuple_ variable
* with operators overloaded. */
struct tlfloat_octuple {
tlfloat_octuple_ value;

Expand Down Expand Up @@ -706,6 +715,12 @@ typedef tlfloat_octuple_ tlfloat_octuple;
#endif

#if (defined(__cplusplus) && !defined(TLFLOAT_COMPILER_SUPPORTS_INT128)) || defined(TLFLOAT_DOXYGEN)
/** tlfloat_int128_t is a trivially copyable type for handling 128-bit
* signed integer in C and C++11. The data size and data structure of
* this type are the same as ordinary integer types. When compling C
* code, this type is an alias for tlfloat_int128_t_. When compling
* C++ code without __int128_t support, this is a struct encapsulating
* a tlfloat_int128_t variable with operators overloaded. */
struct tlfloat_int128_t {
tlfloat_int128_t_ value;

Expand Down Expand Up @@ -779,6 +794,13 @@ struct tlfloat_int128_t {
tlfloat_int128_t operator--(int) { tlfloat_int128_t t = *this; *this = tlfloat_sub_i128_i128(value, tlfloat_cast_i128_i64(1)); return t; }
};

/** tlfloat_uint128_t is a trivially copyable type for handling
* 128-bit unsigned integer in C and C++11. The data size and data
* structure of this type are the same as ordinary integer types. When
* compling C code, this type is an alias for tlfloat_uint128_t_. When
* compling C++ code without __uint128_t support, this is a struct
* encapsulating a tlfloat_int128_t variable with operators
* overloaded. */
struct tlfloat_uint128_t {
tlfloat_uint128_t_ value;

Expand Down Expand Up @@ -852,6 +874,10 @@ struct tlfloat_uint128_t {

inline tlfloat_int128_t::tlfloat_int128_t(const tlfloat_uint128_t_& d) { memcpy((void *)this, (void *)&d, sizeof(*this)); }
inline tlfloat_int128_t::operator tlfloat_uint128_t_() const { tlfloat_uint128_t v; memcpy((void *)&v, (void *)this, sizeof(v)); return v; }

/** This macro is defined iff tlfloat_int128_t and tlfloat_uint128_t
are not aliases of __int128_t and __uint128_t, but structs defined
in tlfloat.h. */
#define TLFLOAT_INT128_IS_STRUCT
#else
typedef tlfloat_int128_t_ tlfloat_int128_t;
Expand Down
38 changes: 0 additions & 38 deletions src/tester/test_arith.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,44 +22,6 @@ static_assert(is_trivially_copyable_v<Double> == true);
static_assert(is_trivially_copyable_v<Quad> == true);
static_assert(is_trivially_copyable_v<Octuple> == true);

static bool cmpf(float x, float y, int t=0) {
if (isnan(x) && isnan(y)) return true;
uint32_t u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(int32_t(u) - int32_t(v));
return -t <= d && d <= t;
}

static bool cmpd(double x, double y, int t=0) {
if (isnan(x) && isnan(y)) return true;
uint64_t u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(int64_t(u) - int64_t(v));
return -t <= d && d <= t;
}

#ifdef ENABLE_QUAD
static bool cmpq(quad x, quad y, int t=0) {
if (isnanq(x) && isnanq(y)) return true;
BigUInt<7> u, v;
memcpy((void *)&u, (void *)&x, sizeof(u));
memcpy((void *)&v, (void *)&y, sizeof(v));

if (t == 0) return u == v;

int d = int(BigInt<7>(u) - BigInt<7>(v));
return -t <= d && d <= t;
}
#endif

int main(int argc, char **argv) {
uint64_t niter = 100000;

Expand Down
2 changes: 1 addition & 1 deletion src/tester/test_bigint3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void checks(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double
if (!equal(i0 += 3, b0 += 3)) e("+=");
if (!equal(i0 -= 3, b0 -= 3)) e("-=");
if (!equal(i0 *= 3, b0 *= 3)) e("*=");
//if (!equal(i0 /= 3, b0 /= 3)) e("/=");
if (!equal(i0 /= 3, b0 /= 3)) e("/=");

if (!equal(i1 += i0, b1 += b0)) e("+=");
if (!equal(i1 -= i0, b1 -= b0)) e("-=");
Expand Down
18 changes: 12 additions & 6 deletions src/tester/test_bigint4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ void checks(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double
{
char str[256];
tlfloat_snprintf(str, sizeof(str), "%Qd", b0);
if (b0 != tlfloat_strtoi128(str, NULL, 10)) e("to/from string signed base 10");
if (b0 != tlfloat_strtoi128(str, NULL, 10)) e("Qd to/from string signed base 10");
if (b0 != tlfloat_strtoi128(str, NULL, 0)) e("Qd to/from string signed base 0");
}

if ((i0 == i1) != (b0 == b1)) e("==");
Expand Down Expand Up @@ -158,12 +159,12 @@ void checks(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double
if (!equal(i0 += 3, b0 += 3)) e("+=");
if (!equal(i0 -= 3ULL, b0 -= 3ULL)) e("-=");
if (!equal(i0 *= 3, b0 *= 3)) e("*=");
//if (!equal(i0 /= 3, b0 /= 3)) e("/=");
if (!equal(i0 /= 3, b0 /= 3)) e("/=");

if (!equal(i1 += i0, b1 += b0)) e("+=");
if (!equal(i1 -= i0, b1 -= tlfloat_int128_t_(b0))) e("-=");
if (!equal(i1 *= i0, b1 *= tlfloat_uint128_t(b0))) e("*=");
//if (!equal(i1 /= i0, b1 /= b0)) e("/=");
if (!equal(i1 /= i0, b1 /= b0)) e("/=");
}

void checku(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double d) {
Expand Down Expand Up @@ -223,13 +224,18 @@ void checku(uint64_t high0, uint64_t low0, uint64_t high1, uint64_t low1, double
char str[256];

tlfloat_snprintf(str, sizeof(str), "%Qu", b0);
if (b0 != tlfloat_strtou128(str, NULL, 10)) e("to/from string unsigned base 10");
if (b0 != tlfloat_strtou128(str, NULL, 10)) e("Qu to/from string unsigned base 10");
if (b0 != tlfloat_strtou128(str, NULL, 0)) e("Qu to/from string unsigned base 10");

tlfloat_snprintf(str, sizeof(str), "%Qo", b0);
if (b0 != tlfloat_strtou128(str, NULL, 8)) e("to/from string unsigned base 8");
if (b0 != tlfloat_strtou128(str, NULL, 8)) e("Qo to/from string unsigned base 8");
tlfloat_snprintf(str, sizeof(str), "0%Qo", b0);
if (b0 != tlfloat_strtou128(str, NULL, 0)) e("Qo to/from string unsigned base 0");

tlfloat_snprintf(str, sizeof(str), "%Qx", b0);
if (b0 != tlfloat_strtou128(str, NULL, 16)) e("to/from string unsigned base 16");
if (b0 != tlfloat_strtou128(str, NULL, 16)) e("Qx to/from string unsigned base 16");
tlfloat_snprintf(str, sizeof(str), "0x%Qx", b0);
if (b0 != tlfloat_strtou128(str, NULL, 0)) e("Qx to/from string unsigned base 0");
}

if ((i0 == i1) != (b0 == b1)) e("==");
Expand Down
Loading

0 comments on commit a63b539

Please sign in to comment.