Revision ef18eb33
Added by David Sorber about 4 years ago
| software/fixed/CMakeLists.txt | ||
|---|---|---|
|
ADD_EXECUTABLE(parse_test ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/parse_test.cc)
|
||
|
|
||
|
# Test executables
|
||
|
ADD_EXECUTABLE(fixed_test ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/fixed_test.cc)
|
||
|
TARGET_LINK_LIBRARIES(fixed_test ${EXTERNAL_LIBS})
|
||
|
ADD_EXECUTABLE(fixed64_test ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/fixed64_test.cc)
|
||
|
TARGET_LINK_LIBRARIES(fixed64_test ${EXTERNAL_LIBS})
|
||
|
|
||
|
ADD_EXECUTABLE(fixed128_test ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/fixed128_test.cc)
|
||
|
TARGET_LINK_LIBRARIES(fixed128_test ${EXTERNAL_LIBS})
|
||
|
|
||
|
ADD_EXECUTABLE(int128_test ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/int128_test.cc)
|
||
|
TARGET_LINK_LIBRARIES(int128_test ${EXTERNAL_LIBS})
|
||
| software/fixed/fixed.h | ||
|---|---|---|
|
constexpr inline fixed<I, F, STI, STF> operator*(
|
||
|
const fixed<I, F, STI, STF>& x, const int64_t& y)
|
||
|
{
|
||
|
fixed<I, F, STI, STF> newVal;
|
||
|
//~ bool negativeDivisorFlag = (y < 0);
|
||
|
//~ bool negativeDividendFlag = (x.m_integer < 0) ||
|
||
|
//~ (x.m_integer == fixed<I, F, STI, STF>::NEGATIVE_ZERO);
|
||
|
//~ bool negativeZeroFlag = false;
|
||
|
//~ I integerX = x.m_integer;
|
||
|
//~ if (__unlikely((integerX == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
|
||
|
//~ {
|
||
|
//~ integerX = 0;
|
||
|
//~ negativeZeroFlag = true;
|
||
|
//~ }
|
||
|
|
||
|
// Straight multiply for integer portion
|
||
|
newVal.m_integer = x.m_integer * y;
|
||
|
// Set flag to indicate if result should be negative
|
||
|
bool negativeResultFlag = false;
|
||
|
I integerX = x.m_integer;
|
||
|
if (__unlikely((integerX == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
|
||
|
{
|
||
|
integerX = 0;
|
||
|
negativeResultFlag = true;
|
||
|
}
|
||
|
else if (integerX < 0)
|
||
|
{
|
||
|
integerX *= -1;
|
||
|
negativeResultFlag = true;
|
||
|
}
|
||
|
|
||
|
std::cout << "INTEGER: " << newVal.m_integer << std::endl;
|
||
|
int64_t multiplier = y;
|
||
|
if (multiplier < 0)
|
||
|
{
|
||
|
// Ensure that multiplier is positive to avoid issues with
|
||
|
// signed/unsigned operations
|
||
|
multiplier *= -1;
|
||
|
|
||
|
// Toggle negative results flag
|
||
|
negativeResultFlag = !negativeResultFlag;
|
||
|
}
|
||
|
|
||
|
std::cout << "Frac digits: " << fixed<I, F, STI, STF>::fractional_decimal_digits << std::endl;
|
||
|
std::cout << "Half Frac digits: " << (fixed<I, F, STI, STF>::fractional_decimal_digits / 2) << std::endl;
|
||
|
// Multiply integer portion first
|
||
|
fixed<I, F, STI, STF> newVal;
|
||
|
newVal.m_integer = integerX * multiplier;
|
||
|
|
||
|
uint32_t index = (fixed<I, F, STI, STF>::fractional_decimal_digits / 2);
|
||
|
uint32_t indexUpper = (fixed<I, F, STI, STF>::fractional_decimal_digits / 2);
|
||
|
uint32_t indexLower = (fixed<I, F, STI, STF>::fractional_decimal_digits - indexUpper);
|
||
|
|
||
|
#if SUPPORT_128_INTS
|
||
|
uint128_t scaler = fixed<I, F, STI, STF>::SCALE_VALUES[index];
|
||
|
uint128_t scalerUpper = fixed<I, F, STI, STF>::SCALE_VALUES[indexUpper];
|
||
|
uint128_t scalerLower = fixed<I, F, STI, STF>::SCALE_VALUES[indexLower];
|
||
|
#else
|
||
|
uint64_t scaler = fixed<I, F, STI, STF>::SCALE_VALUES[index];
|
||
|
uint64_t scalerUpper = fixed<I, F, STI, STF>::SCALE_VALUES[indexUpper];
|
||
|
uint64_t scalerLower = fixed<I, F, STI, STF>::SCALE_VALUES[indexLower];
|
||
|
#endif
|
||
|
|
||
|
// Compute the lower portion
|
||
|
F fracLower = (x.m_fractional % scalerLower) * multiplier;
|
||
|
|
||
|
// Handle upper and lower portions of fractional value separarely so that
|
||
|
// the integer carry can be handled
|
||
|
std::cout << "[1] FRAC upper: " << (x.m_fractional / scaler) << std::endl;
|
||
|
F fracUpper = (x.m_fractional / scaler) * y;
|
||
|
std::cout << "[2] FRAC upper: " << fracUpper << std::endl;
|
||
|
newVal.m_fractional = (fracUpper % (scaler * 10)) * scaler;
|
||
|
std::cout << "NEW FRAC upper: " << newVal.m_fractional << std::endl;
|
||
|
// Compute lower carry explicitly as it may trigger an additional carry,
|
||
|
// then rescale lower portion to remove carry
|
||
|
F carryLower = fracLower / scalerLower;
|
||
|
fracLower %= scalerLower;
|
||
|
|
||
|
F carry = (fracUpper / (scaler * 10));
|
||
|
std::cout << "Carry: " << carry << std::endl;
|
||
|
newVal.m_integer += carry;
|
||
|
// Compute upper portion
|
||
|
F fracUpper = ((x.m_fractional / scalerLower) * multiplier) + carryLower;
|
||
|
newVal.m_fractional = (fracUpper % scalerUpper) * scalerLower;
|
||
|
|
||
|
F fracLower = (x.m_fractional % scaler) * y;
|
||
|
std::cout << "FRAC lower: " << fracLower << std::endl;
|
||
|
// Computer integer carry then add it to integer portion
|
||
|
newVal.m_integer += (fracUpper / scalerUpper);
|
||
|
|
||
|
// Finally add the lower fractional portion, which at this point will not
|
||
|
// trigger a carry
|
||
|
newVal.m_fractional += fracLower;
|
||
|
|
||
|
// If negative result flag was set ensure that final result is negative
|
||
|
if (negativeResultFlag)
|
||
|
{
|
||
|
if (newVal.m_integer == 0 && newVal.m_fractional > 0)
|
||
|
{
|
||
|
newVal.m_integer = fixed<I, F, STI, STF>::NEGATIVE_ZERO;
|
||
|
}
|
||
|
else if (newVal.m_integer > 0)
|
||
|
{
|
||
|
newVal.m_integer *= -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return newVal;
|
||
|
}
|
||
|
|
||
| software/fixed/fixed128_test.cc | ||
|---|---|---|
|
|
||
|
#include <cstdint>
|
||
|
#include <limits>
|
||
|
#include <random>
|
||
|
#include <stdexcept>
|
||
|
#include <sstream>
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
#define BOOST_TEST_MAIN 1
|
||
|
#include <boost/test/unit_test.hpp>
|
||
|
|
||
|
#include "fixed.h"
|
||
|
|
||
|
// Helper macros
|
||
|
#define VALUE_CHECK(val) \
|
||
|
output.str(""); \
|
||
|
output << value; \
|
||
|
/*std::cout << "CHECK: " << output.str() << " == " << val << std::endl;*/ \
|
||
|
BOOST_CHECK(output.str() == val);
|
||
|
|
||
|
#define PARSE_VALUE_CHECK(val) \
|
||
|
value.parse(input); \
|
||
|
output.str(""); \
|
||
|
output << value; \
|
||
|
/*std::cout << "CHECK: " << output.str() << " == " << val << std::endl;*/ \
|
||
|
BOOST_CHECK(output.str() == val);
|
||
|
|
||
|
// "in" is the string to be parsed
|
||
|
// "val" is the expected serialized output
|
||
|
#define PARSE_VALUE_CHECK_2(in, val) \
|
||
|
input = in; \
|
||
|
value.parse(input); \
|
||
|
output.str(""); \
|
||
|
output << value; \
|
||
|
/*std::cout << "CHECK: " << output.str() << " == " << val << std::endl;*/ \
|
||
|
BOOST_CHECK(output.str() == val);
|
||
|
|
||
|
#define PARSE_EXCEPTION_CHECK \
|
||
|
exception = false; \
|
||
|
try \
|
||
|
{ \
|
||
|
value.parse(input); \
|
||
|
} \
|
||
|
catch (const std::out_of_range& exp) \
|
||
|
{ \
|
||
|
exception = true; \
|
||
|
} \
|
||
|
BOOST_CHECK(exception);
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t000)
|
||
|
{
|
||
|
/* TEST CASE 0: Check storage sizes (in bytes) of all predefined fixed
|
||
|
* point types.
|
||
|
*/
|
||
|
fixed_8_8 f_8_8;
|
||
|
fixed_8_32 f_8_32;
|
||
|
fixed_8_16 f_8_16;
|
||
|
fixed_8_64 f_8_64;
|
||
|
fixed_8_128 f_8_128;
|
||
|
BOOST_CHECK(sizeof(f_8_8) == 2);
|
||
|
BOOST_CHECK(sizeof(f_8_16) == 4);
|
||
|
BOOST_CHECK(sizeof(f_8_32) == 8);
|
||
|
BOOST_CHECK(sizeof(f_8_64) == 16);
|
||
|
BOOST_CHECK(sizeof(f_8_128) == 32);
|
||
|
|
||
|
fixed_16_8 f_16_8;
|
||
|
fixed_16_16 f_16_16;
|
||
|
fixed_16_32 f_16_32;
|
||
|
fixed_16_64 f_16_64;
|
||
|
fixed_16_128 f_16_128;
|
||
|
BOOST_CHECK(sizeof(f_16_8) == 4);
|
||
|
BOOST_CHECK(sizeof(f_16_16) == 4);
|
||
|
BOOST_CHECK(sizeof(f_16_32) == 8);
|
||
|
BOOST_CHECK(sizeof(f_16_64) == 16);
|
||
|
BOOST_CHECK(sizeof(f_16_128) == 32);
|
||
|
|
||
|
fixed_32_8 f_32_8;
|
||
|
fixed_32_16 f_32_16;
|
||
|
fixed_32_32 f_32_32;
|
||
|
fixed_32_64 f_32_64;
|
||
|
fixed_32_128 f_32_128;
|
||
|
BOOST_CHECK(sizeof(f_32_8) == 8);
|
||
|
BOOST_CHECK(sizeof(f_32_16) == 8);
|
||
|
BOOST_CHECK(sizeof(f_32_32) == 8);
|
||
|
BOOST_CHECK(sizeof(f_32_64) == 16);
|
||
|
BOOST_CHECK(sizeof(f_32_128) == 32);
|
||
|
|
||
|
fixed_64_8 f_64_8;
|
||
|
fixed_64_16 f_64_16;
|
||
|
fixed_64_32 f_64_32;
|
||
|
fixed_64_64 f_64_64;
|
||
|
fixed_64_128 f_64_128;
|
||
|
BOOST_CHECK(sizeof(f_64_8) == 16);
|
||
|
BOOST_CHECK(sizeof(f_64_16) == 16);
|
||
|
BOOST_CHECK(sizeof(f_64_32) == 16);
|
||
|
BOOST_CHECK(sizeof(f_64_64) == 16);
|
||
|
BOOST_CHECK(sizeof(f_64_128) == 32);
|
||
|
|
||
|
fixed_128_8 f_128_8;
|
||
|
fixed_128_16 f_128_16;
|
||
|
fixed_128_32 f_128_32;
|
||
|
fixed_128_64 f_128_64;
|
||
|
fixed_128_128 f_128_128;
|
||
|
BOOST_CHECK(sizeof(f_128_8) == 32);
|
||
|
BOOST_CHECK(sizeof(f_128_16) == 32);
|
||
|
BOOST_CHECK(sizeof(f_128_32) == 32);
|
||
|
BOOST_CHECK(sizeof(f_128_64) == 32);
|
||
|
BOOST_CHECK(sizeof(f_128_128) == 32);
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t001)
|
||
|
{
|
||
|
/* TEST CASE 1: Test basic comparisons
|
||
|
*/
|
||
|
fixed_128_128 val1(100, 1, 0);
|
||
|
fixed_128_128 val2(100, 1);
|
||
|
|
||
|
BOOST_CHECK( (val1 == val2));
|
||
|
BOOST_CHECK(! (val1 != val2));
|
||
|
BOOST_CHECK(! (val1 > val2));
|
||
|
BOOST_CHECK(! (val1 < val2));
|
||
|
BOOST_CHECK( (val1 >= val2));
|
||
|
BOOST_CHECK( (val1 <= val2));
|
||
|
|
||
|
val2.assignUnscaledFrac(100, 1, 18);
|
||
|
|
||
|
BOOST_CHECK(! (val1 == val2));
|
||
|
BOOST_CHECK( (val1 != val2));
|
||
|
BOOST_CHECK( (val1 > val2));
|
||
|
BOOST_CHECK(! (val1 < val2));
|
||
|
BOOST_CHECK( (val1 >= val2));
|
||
|
BOOST_CHECK(! (val1 <= val2));
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t002)
|
||
|
{
|
||
|
/* TEST CASE 2: Test parsing with leading zeros.
|
||
|
*/
|
||
|
fixed_128_128 val1;
|
||
|
fixed_128_128 val2;
|
||
|
|
||
|
// 1
|
||
|
val1.assign(1, 20000000000000000000000000000000000000_u128);
|
||
|
val2.parse("1.2");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 2
|
||
|
val1.assign(1, 2000000000000000000000000000000000000_u128);
|
||
|
val2.parse("1.02");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 3
|
||
|
val1.assign(1, 200000000000000000000000000000000000_u128);
|
||
|
val2.parse("1.002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 4
|
||
|
val1.assign(1, 20000000000000000000000000000000000_u128);
|
||
|
val2.parse("1.0002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 5
|
||
|
val1.assign(1, 2000000000000000000000000000000000_u128);
|
||
|
val2.parse("1.00002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 6
|
||
|
val1.assign(1, 200000000000000000000000000000000_u128);
|
||
|
val2.parse("1.000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 7
|
||
|
val1.assign(1, 20000000000000000000000000000000_u128);
|
||
|
val2.parse("1.0000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 8
|
||
|
val1.assign(1, 2000000000000000000000000000000_u128);
|
||
|
val2.parse("1.00000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 9
|
||
|
val1.assign(1, 200000000000000000000000000000_u128);
|
||
|
val2.parse("1.000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 10
|
||
|
val1.assign(1, 20000000000000000000000000000_u128);
|
||
|
val2.parse("1.0000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 11
|
||
|
val1.assign(1, 2000000000000000000000000000_u128);
|
||
|
val2.parse("1.00000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 12
|
||
|
val1.assign(1, 200000000000000000000000000_u128);
|
||
|
val2.parse("1.000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 13
|
||
|
val1.assign(1, 20000000000000000000000000_u128);
|
||
|
val2.parse("1.0000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 14
|
||
|
val1.assign(1, 2000000000000000000000000_u128);
|
||
|
val2.parse("1.00000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 15
|
||
|
val1.assign(1, 200000000000000000000000_u128);
|
||
|
val2.parse("1.000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 16
|
||
|
val1.assign(1, 20000000000000000000000_u128);
|
||
|
val2.parse("1.0000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 17
|
||
|
val1.assign(1, 2000000000000000000000_u128);
|
||
|
val2.parse("1.00000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 18
|
||
|
val1.assign(1, 200000000000000000000_u128);
|
||
|
val2.parse("1.000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 19
|
||
|
val1.assign(1, 20000000000000000000_u128);
|
||
|
val2.parse("1.0000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 20
|
||
|
val1.assign(1, 2000000000000000000_u128);
|
||
|
val2.parse("1.00000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 21
|
||
|
val1.assign(1, 200000000000000000_u128);
|
||
|
val2.parse("1.000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 22
|
||
|
val1.assign(1, 20000000000000000_u128);
|
||
|
val2.parse("1.0000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 23
|
||
|
val1.assign(1, 2000000000000000_u128);
|
||
|
val2.parse("1.00000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 24
|
||
|
val1.assign(1, 200000000000000_u128);
|
||
|
val2.parse("1.000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 25
|
||
|
val1.assign(1, 20000000000000_u128);
|
||
|
val2.parse("1.0000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 26
|
||
|
val1.assign(1, 2000000000000_u128);
|
||
|
val2.parse("1.00000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 27
|
||
|
val1.assign(1, 200000000000_u128);
|
||
|
val2.parse("1.000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 28
|
||
|
val1.assign(1, 20000000000_u128);
|
||
|
val2.parse("1.0000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 29
|
||
|
val1.assign(1, 2000000000_u128);
|
||
|
val2.parse("1.00000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 30
|
||
|
val1.assign(1, 200000000_u128);
|
||
|
val2.parse("1.000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 31
|
||
|
val1.assign(1, 20000000_u128);
|
||
|
val2.parse("1.0000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 32
|
||
|
val1.assign(1, 2000000_u128);
|
||
|
val2.parse("1.00000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 33
|
||
|
val1.assign(1, 200000_u128);
|
||
|
val2.parse("1.000000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 34
|
||
|
val1.assign(1, 20000_u128);
|
||
|
val2.parse("1.0000000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 35
|
||
|
val1.assign(1, 2000_u128);
|
||
|
val2.parse("1.00000000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 36
|
||
|
val1.assign(1, 200_u128);
|
||
|
val2.parse("1.000000000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 37
|
||
|
val1.assign(1, 20_u128);
|
||
|
val2.parse("1.0000000000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
|
||
|
// 38
|
||
|
val1.assign(1, 2_u128);
|
||
|
val2.parse("1.00000000000000000000000000000000000002");
|
||
|
BOOST_CHECK(val1 == val2);
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t003)
|
||
|
{
|
||
|
/* TEST CASE 3: Test parsing and printing randomly generated values
|
||
|
*/
|
||
|
using theType = fixed_128_128;
|
||
|
|
||
|
uint32_t NUMBER = 1000000;
|
||
|
uint64_t SEED = 0xDEADBEEF123;
|
||
|
|
||
|
std::random_device dev;
|
||
|
std::mt19937 rng;
|
||
|
rng.seed(SEED);
|
||
|
|
||
|
std::uniform_int_distribution<std::mt19937::result_type> negative(0, 1);
|
||
|
std::uniform_int_distribution<std::mt19937::result_type> intDigits(1, theType::integer_decimal_digits);
|
||
|
std::uniform_int_distribution<std::mt19937::result_type> fracDigits(1, theType::fractional_decimal_digits);
|
||
|
std::uniform_int_distribution<std::mt19937::result_type> digits(0, 9);
|
||
|
|
||
|
// Generate NUMBER worth of parsable decimal number strings
|
||
|
std::vector<std::string> values;
|
||
|
for (uint32_t idx = 0; idx < NUMBER; ++idx)
|
||
|
{
|
||
|
std::ostringstream output;
|
||
|
|
||
|
// Decide if the number should be negative
|
||
|
if (negative(rng) == 1)
|
||
|
{
|
||
|
output << "-";
|
||
|
}
|
||
|
|
||
|
// Generate random integer number digits
|
||
|
for (uint32_t integerIdx = 0; integerIdx < intDigits(rng); ++integerIdx)
|
||
|
{
|
||
|
int digit = digits(rng);
|
||
|
|
||
|
// Integer part cannot start with a zero
|
||
|
if (integerIdx == 0)
|
||
|
{
|
||
|
while (digit == 0)
|
||
|
{
|
||
|
digit = digits(rng);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
output << digit;
|
||
|
}
|
||
|
|
||
|
output << ".";
|
||
|
|
||
|
// Generate random fractional number digits
|
||
|
uint32_t numFracDigits = fracDigits(rng);
|
||
|
for (uint32_t fracIdx = 0; fracIdx < numFracDigits; ++fracIdx)
|
||
|
{
|
||
|
int digit = digits(rng);
|
||
|
|
||
|
// Fractional part cannot end with a zero
|
||
|
if (fracIdx == (numFracDigits - 1))
|
||
|
{
|
||
|
while (digit == 0)
|
||
|
{
|
||
|
digit = digits(rng);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
output << digit;
|
||
|
}
|
||
|
|
||
|
values.emplace_back(output.str());
|
||
|
//~ std::cout << "VAL: " << values.back() << std::endl;
|
||
|
}
|
||
|
|
||
|
// Now validate that the output of the parsed
|
||
|
theType fixedValue;
|
||
|
std::ostringstream output;
|
||
|
for (auto& value : values)
|
||
|
{
|
||
|
fixedValue.parse(value.c_str());
|
||
|
output << fixedValue;
|
||
|
|
||
|
//~ std::cout << "TEST: " << output.str() << " -- " << value << std::endl;
|
||
|
BOOST_CHECK(output.str() == value);
|
||
|
output.str("");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t004)
|
||
|
{
|
||
|
/* TEST CASE 4: Basic test division by unsigned integer
|
||
|
*/
|
||
|
fixed_128_128 val1(18, 55, 0);
|
||
|
fixed_128_128 val2(0, 1855, 0);
|
||
|
|
||
|
fixed_128_128 answer = val1 / 100;
|
||
|
BOOST_CHECK(answer == val2);
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t005)
|
||
|
{
|
||
|
/* TEST CASE 5: Test parsing a decimal number with a larger than supported
|
||
|
* fractional part.
|
||
|
*/
|
||
|
|
||
|
const char* input = ".101010101010101010100010102030508132134";
|
||
|
|
||
|
fixed_128_128 value;
|
||
|
#if 0
|
||
|
value.parse(input);
|
||
|
|
||
|
std::ostringstream output;
|
||
|
output << value;
|
||
|
|
||
|
BOOST_CHECK(output.str() == "0.0001010203050813213");
|
||
|
#else
|
||
|
bool exception = false;
|
||
|
try
|
||
|
{
|
||
|
value.parse(input);
|
||
|
}
|
||
|
catch (const std::out_of_range& exp)
|
||
|
{
|
||
|
exception = true;
|
||
|
}
|
||
|
BOOST_CHECK(exception);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t006)
|
||
|
{
|
||
|
/* TEST CASE 6: zero integer, positive exponent, walking one positive test
|
||
|
* cases
|
||
|
*/
|
||
|
fixed_128_128 value;
|
||
|
std::ostringstream output;
|
||
|
|
||
|
const char* input = "0.00000000000000000000000000000000000001e75";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e74";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e73";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e72";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e71";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e70";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e69";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e68";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e67";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e66";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e65";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e64";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e63";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e62";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e61";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e60";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e59";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e58";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e57";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e56";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e55";
|
||
|
PARSE_VALUE_CHECK("100000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e54";
|
||
|
PARSE_VALUE_CHECK("10000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e53";
|
||
|
PARSE_VALUE_CHECK("1000000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e52";
|
||
|
PARSE_VALUE_CHECK("100000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e51";
|
||
|
PARSE_VALUE_CHECK("10000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e50";
|
||
|
PARSE_VALUE_CHECK("1000000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e49";
|
||
|
PARSE_VALUE_CHECK("100000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e48";
|
||
|
PARSE_VALUE_CHECK("10000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e47";
|
||
|
PARSE_VALUE_CHECK("1000000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e46";
|
||
|
PARSE_VALUE_CHECK("100000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e45";
|
||
|
PARSE_VALUE_CHECK("10000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e44";
|
||
|
PARSE_VALUE_CHECK("1000000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e43";
|
||
|
PARSE_VALUE_CHECK("100000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e42";
|
||
|
PARSE_VALUE_CHECK("10000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e41";
|
||
|
PARSE_VALUE_CHECK("1000.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e40";
|
||
|
PARSE_VALUE_CHECK("100.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e39";
|
||
|
PARSE_VALUE_CHECK("10.0");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e38";
|
||
|
PARSE_VALUE_CHECK("1.0");
|
||
|
|
||
|
// Cross over
|
||
|
input = "0.00000000000000000000000000000000000001e37";
|
||
|
PARSE_VALUE_CHECK("0.1");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e37";
|
||
|
PARSE_VALUE_CHECK("0.1");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e36";
|
||
|
PARSE_VALUE_CHECK("0.01");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e35";
|
||
|
PARSE_VALUE_CHECK("0.001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e34";
|
||
|
PARSE_VALUE_CHECK("0.0001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e33";
|
||
|
PARSE_VALUE_CHECK("0.00001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e32";
|
||
|
PARSE_VALUE_CHECK("0.000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e31";
|
||
|
PARSE_VALUE_CHECK("0.0000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e30";
|
||
|
PARSE_VALUE_CHECK("0.00000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e29";
|
||
|
PARSE_VALUE_CHECK("0.000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e28";
|
||
|
PARSE_VALUE_CHECK("0.0000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e27";
|
||
|
PARSE_VALUE_CHECK("0.00000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e26";
|
||
|
PARSE_VALUE_CHECK("0.000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e25";
|
||
|
PARSE_VALUE_CHECK("0.0000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e24";
|
||
|
PARSE_VALUE_CHECK("0.00000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e23";
|
||
|
PARSE_VALUE_CHECK("0.000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e22";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e21";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e20";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e19";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e18";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e17";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e16";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e15";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e14";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e13";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e12";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e11";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e10";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e9";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e8";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e7";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e6";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e5";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e4";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e3";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e2";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e1";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000000000000001");
|
||
|
|
||
|
input = "0.00000000000000000000000000000000000001e0";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000000000000001");
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t007)
|
||
|
{
|
||
|
/* TEST CASE 7: non-zero integer, positive exponent, walking value
|
||
|
* positive+negative test cases
|
||
|
*/
|
||
|
fixed_128_128 value;
|
||
|
std::ostringstream output;
|
||
|
|
||
|
const char* input = "1.00000000000000000000000000000000000001e1";
|
||
|
PARSE_VALUE_CHECK("10.0000000000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e2";
|
||
|
PARSE_VALUE_CHECK("100.000000000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e3";
|
||
|
PARSE_VALUE_CHECK("1000.00000000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e4";
|
||
|
PARSE_VALUE_CHECK("10000.0000000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e5";
|
||
|
PARSE_VALUE_CHECK("100000.000000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e6";
|
||
|
PARSE_VALUE_CHECK("1000000.00000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e7";
|
||
|
PARSE_VALUE_CHECK("10000000.0000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e8";
|
||
|
PARSE_VALUE_CHECK("100000000.000000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e9";
|
||
|
PARSE_VALUE_CHECK("1000000000.00000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e10";
|
||
|
PARSE_VALUE_CHECK("10000000000.0000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e11";
|
||
|
PARSE_VALUE_CHECK("100000000000.000000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e12";
|
||
|
PARSE_VALUE_CHECK("1000000000000.00000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e13";
|
||
|
PARSE_VALUE_CHECK("10000000000000.0000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e14";
|
||
|
PARSE_VALUE_CHECK("100000000000000.000000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e15";
|
||
|
PARSE_VALUE_CHECK("1000000000000000.00000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e16";
|
||
|
PARSE_VALUE_CHECK("10000000000000000.0000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e17";
|
||
|
PARSE_VALUE_CHECK("100000000000000000.000000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e18";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000.00000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e19";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000.0000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e20";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000.000000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e21";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000.00000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e22";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000.0000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e23";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000.000000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e24";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000.00000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e25";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000.0000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e26";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000.000000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e27";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000.00000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e28";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000.0000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e29";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000.000000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e30";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000.00000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e31";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000.0000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e32";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000.000001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e33";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000000.00001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e34";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000000.0001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e35";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000000.001");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e36";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000000000.01");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e37";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000000000.1");
|
||
|
|
||
|
input = "1.00000000000000000000000000000000000001e38";
|
||
|
bool exception = false;
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t008)
|
||
|
{
|
||
|
/* TEST CASE 8: zero integer, positive exponent, walking one negative test
|
||
|
* cases
|
||
|
*/
|
||
|
fixed_64_64 value;
|
||
|
std::ostringstream output;
|
||
|
|
||
|
const char* input = "0.00000000000000000000000000000000000001e76";
|
||
|
bool exception = false;
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000000000000000000000000001e75";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000000000000000000000000001e74";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000000000000000000000000001e73";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000000000000000000000001e72";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000000000000000000000001e71";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000000000000000000000001e70";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000000000000000000001e69";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000000000000000000001e68";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000000000000000000001e67";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000000000000000001e66";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000000000000000001e65";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000000000000000001e64";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000000000000001e63";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000000000000001e62";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000000000000001e61";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000000000001e60";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000000000001e59";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000000000001e58";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000000001e57";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000000001e56";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000000001e55";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000000001e54";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000000001e53";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000000001e52";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000000001e51";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000000001e50";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000000001e49";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000000001e48";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000000001e47";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00000001e46";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0000001e45";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.000001e44";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.00001e43";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.0001e42";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.001e41";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.01e40";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "0.1e39";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
// Cross over
|
||
|
input = "1.0e38";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10.0e37";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100.0e36";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000.0e35";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000.0e34";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000.0e33";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000.0e32";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000.0e31";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000.0e30";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000.0e29";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000.0e28";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000.0e27";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000.0e26";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000.0e25";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000.0e24";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000.0e23";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000.0e22";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000000.0e21";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000000.0e20";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000.0e19";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000000000.0e18";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000000000.0e17";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000000.0e16";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000000000000.0e15";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000000000000.0e14";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000000000.0e13";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000000000000000.0e12";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000000000000000.0e11";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000000000000.0e10";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000000000000000000.0e9";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000000000000000000.0e8";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000000000000000.0e7";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000000000000000000000.0e6";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000000000000000000000.0e5";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000000000000000000.0e4";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "100000000000000000000000000000000000.0e3";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "1000000000000000000000000000000000000.0e2";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e1";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e0";
|
||
|
PARSE_EXCEPTION_CHECK
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t009)
|
||
|
{
|
||
|
/* TEST CASE 9: zero factional, negative exponent, walking one positive test
|
||
|
* cases
|
||
|
*/
|
||
|
fixed_128_128 value;
|
||
|
std::ostringstream output;
|
||
|
|
||
|
const char* input = "10000000000000000000000000000000000000.0e-1";
|
||
|
PARSE_VALUE_CHECK( "1000000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-2";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-3";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-4";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-5";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-6";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-7";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-8";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-9";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-10";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-11";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-12";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-13";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-14";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-15";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-16";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-17";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-18";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-19";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-20";
|
||
|
PARSE_VALUE_CHECK("100000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-21";
|
||
|
PARSE_VALUE_CHECK("10000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-22";
|
||
|
PARSE_VALUE_CHECK("1000000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-23";
|
||
|
PARSE_VALUE_CHECK("100000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-24";
|
||
|
PARSE_VALUE_CHECK("10000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-25";
|
||
|
PARSE_VALUE_CHECK("1000000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-26";
|
||
|
PARSE_VALUE_CHECK("100000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-27";
|
||
|
PARSE_VALUE_CHECK("10000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-28";
|
||
|
PARSE_VALUE_CHECK("1000000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-29";
|
||
|
PARSE_VALUE_CHECK("100000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-30";
|
||
|
PARSE_VALUE_CHECK("10000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-31";
|
||
|
PARSE_VALUE_CHECK("1000000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-32";
|
||
|
PARSE_VALUE_CHECK("100000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-33";
|
||
|
PARSE_VALUE_CHECK("10000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-34";
|
||
|
PARSE_VALUE_CHECK("1000.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-35";
|
||
|
PARSE_VALUE_CHECK("100.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-36";
|
||
|
PARSE_VALUE_CHECK("10.0");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-37";
|
||
|
PARSE_VALUE_CHECK("1.0");
|
||
|
|
||
|
// Cross over
|
||
|
input = "10000000000000000000000000000000000000.0e-38";
|
||
|
PARSE_VALUE_CHECK("0.1");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-39";
|
||
|
PARSE_VALUE_CHECK("0.01");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-40";
|
||
|
PARSE_VALUE_CHECK("0.001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-41";
|
||
|
PARSE_VALUE_CHECK("0.0001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-42";
|
||
|
PARSE_VALUE_CHECK("0.00001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-43";
|
||
|
PARSE_VALUE_CHECK("0.000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-44";
|
||
|
PARSE_VALUE_CHECK("0.0000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-45";
|
||
|
PARSE_VALUE_CHECK("0.00000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-46";
|
||
|
PARSE_VALUE_CHECK("0.000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-47";
|
||
|
PARSE_VALUE_CHECK("0.0000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-48";
|
||
|
PARSE_VALUE_CHECK("0.00000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-49";
|
||
|
PARSE_VALUE_CHECK("0.000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-50";
|
||
|
PARSE_VALUE_CHECK("0.0000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-51";
|
||
|
PARSE_VALUE_CHECK("0.00000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-52";
|
||
|
PARSE_VALUE_CHECK("0.000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-53";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-54";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-55";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-56";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-57";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-58";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-59";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-60";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-61";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-62";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-63";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-64";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-65";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-66";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-67";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-68";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-69";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-70";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-71";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-72";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-73";
|
||
|
PARSE_VALUE_CHECK("0.000000000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-74";
|
||
|
PARSE_VALUE_CHECK("0.0000000000000000000000000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.0e-75";
|
||
|
PARSE_VALUE_CHECK("0.00000000000000000000000000000000000001");
|
||
|
}
|
||
|
|
||
|
BOOST_AUTO_TEST_CASE(t010)
|
||
|
{
|
||
|
/* TEST CASE 10: non-zero factional, negative exponent, walking value
|
||
|
* positive+negative test cases
|
||
|
*/
|
||
|
fixed_128_128 value;
|
||
|
std::ostringstream output;
|
||
|
|
||
|
const char* input = "10000000000000000000000000000000000000.1e-1";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000000000.01");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-2";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000000.001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-3";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000000.0001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-4";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000000.00001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-5";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000000.000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-6";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000000.0000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-7";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000000.00000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-8";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000000.000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-9";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000000.0000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-10";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000000.00000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-11";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000000.000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-12";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000000.0000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-13";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000000.00000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-14";
|
||
|
PARSE_VALUE_CHECK("100000000000000000000000.000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-15";
|
||
|
PARSE_VALUE_CHECK("10000000000000000000000.0000000000000001");
|
||
|
|
||
|
input = "10000000000000000000000000000000000000.1e-16";
|
||
|
PARSE_VALUE_CHECK("1000000000000000000000.00000000000000001");
|
||
Correct multiply by integer operator. Also add test cases.