add random logarithm tests, extra tests near log(1.0)
This commit is contained in:
parent
89f442cae8
commit
08f1d199c1
@ -196,7 +196,7 @@ static void shift_left(dec80* x){
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_leading_zeros(dec80* x){
|
||||
void remove_leading_zeros(dec80* x){
|
||||
uint8_t digit100;
|
||||
uint8_t is_negative = (x->exponent < 0);
|
||||
exp_t exponent = get_exponent(x);
|
||||
|
@ -62,6 +62,8 @@ exp_t get_exponent(const dec80* const x);
|
||||
|
||||
void set_exponent(dec80* acc, exp_t exponent, uint8_t num_is_neg);
|
||||
|
||||
void remove_leading_zeros(dec80* x);
|
||||
|
||||
|
||||
void copy_decn(dec80* const dest, const dec80* const src);
|
||||
|
||||
|
@ -31,6 +31,8 @@
|
||||
namespace bmp = boost::multiprecision;
|
||||
using Catch::Matchers::Equals;
|
||||
|
||||
static const int NUM_RAND_TESTS = 1234567;
|
||||
|
||||
|
||||
TEST_CASE("build decn"){
|
||||
build_dec80("0.0009234567890123456", 7);
|
||||
@ -345,7 +347,7 @@ TEST_CASE("division random"){
|
||||
std::default_random_engine gen;
|
||||
std::uniform_int_distribution<int> distrib(0, 99);
|
||||
std::uniform_int_distribution<int> sign_distrib(0,1);
|
||||
for (int j = 0; j < 12345; j++){
|
||||
for (int j = 0; j < NUM_RAND_TESTS; j++){
|
||||
AccDecn.lsu[0] = distrib(gen);
|
||||
BDecn.lsu[0] = distrib(gen);
|
||||
for (int i = 1; i < DEC80_NUM_LSU; i++){
|
||||
@ -412,7 +414,7 @@ TEST_CASE("sqrt random"){
|
||||
std::uniform_int_distribution<int> distribution(0,99);
|
||||
std::uniform_int_distribution<int> exp_distrib(-99,99);
|
||||
std::uniform_int_distribution<int> sign_distrib(0,1);
|
||||
for (int j = 0; j < 12345; j++){
|
||||
for (int j = 0; j < NUM_RAND_TESTS; j++){
|
||||
for (int i = 0; i < DEC80_NUM_LSU; i++){
|
||||
AccDecn.lsu[i] = distribution(generator);
|
||||
}
|
||||
@ -422,6 +424,94 @@ TEST_CASE("sqrt random"){
|
||||
}
|
||||
}
|
||||
|
||||
static void log_test_(bool base10, double epsilon){
|
||||
bmp::mpfr_float::default_precision(50);
|
||||
CAPTURE(base10);
|
||||
decn_to_str_complete(&AccDecn);
|
||||
CAPTURE(Buf);
|
||||
//build mpfr float
|
||||
bmp::mpfr_float x_actual(Buf);
|
||||
//calculate result
|
||||
if (base10){
|
||||
log10_decn();
|
||||
} else {
|
||||
ln_decn();
|
||||
}
|
||||
decn_to_str_complete(&AccDecn);
|
||||
CAPTURE(Buf); // log(x)
|
||||
|
||||
//calculate actual result
|
||||
CAPTURE(x_actual);
|
||||
if (decn_is_nan(&AccDecn)){
|
||||
//check that NaN is from result of log(-)
|
||||
CHECK(x_actual <= 0);
|
||||
} else {
|
||||
if (base10){
|
||||
x_actual = log10(x_actual);
|
||||
} else {
|
||||
x_actual = log(x_actual);
|
||||
}
|
||||
bmp::mpfr_float calculated(Buf);
|
||||
CAPTURE(calculated);
|
||||
bmp::mpfr_float rel_diff = abs((x_actual - calculated) / x_actual);
|
||||
CHECK(rel_diff < epsilon);
|
||||
}
|
||||
}
|
||||
|
||||
static void log_test(bool base10=false){
|
||||
//check if near 1.0
|
||||
remove_leading_zeros(&AccDecn);
|
||||
double lsu0 = AccDecn.lsu[0];
|
||||
int exp = get_exponent(&AccDecn);
|
||||
if (exp == -1){
|
||||
lsu0 /= (double) 10;
|
||||
lsu0 += (double) AccDecn.lsu[1] / (10*100);
|
||||
lsu0 += (double) AccDecn.lsu[2] / (10*100*100);
|
||||
lsu0 += (double) AccDecn.lsu[3] / (10*100*100*100);
|
||||
} else if (exp == 0){
|
||||
lsu0 += (double) AccDecn.lsu[1] / 100;
|
||||
lsu0 += (double) AccDecn.lsu[2] / (100*100);
|
||||
lsu0 += (double) AccDecn.lsu[3] / (100*100*100);
|
||||
}
|
||||
CAPTURE((int) AccDecn.lsu[0]); CAPTURE((int) AccDecn.lsu[1]);
|
||||
CAPTURE(exp);
|
||||
CAPTURE(lsu0);
|
||||
if (exp == 0 || exp == -1){
|
||||
//check if near 1.0
|
||||
if (lsu0 >= 7 && lsu0 < 8){
|
||||
log_test_(base10, 7.5e-16);
|
||||
} else if (lsu0 >= 8 && lsu0 < 9){
|
||||
log_test_(base10, 1.5e-15);
|
||||
} else if (lsu0 >= 9 && lsu0 < 9.6){
|
||||
log_test_(base10, 1.0e-14);
|
||||
} else if (lsu0 >= 9.6 && lsu0 < 9.9){
|
||||
log_test_(base10, 4.1e-13);
|
||||
} else if (lsu0 >= 9.9 && lsu0 < 9.999){
|
||||
log_test_(base10, 1.5e-11);
|
||||
} else if (lsu0 >= 9.999 && lsu0 < 9.99999){
|
||||
log_test_(base10, 6.0e-10);
|
||||
} else if (lsu0 >= 9.99999 && lsu0 < 9.9999999){
|
||||
log_test_(base10, 3.0e-9);
|
||||
} else if (lsu0 >= 9.9999999 && lsu0 < 10.0){
|
||||
log_test_(base10, 1.3e-7);
|
||||
} else if (lsu0 >= 10.0 && lsu0 < 10.00001){
|
||||
log_test_(base10, 6.0e-10);
|
||||
} else if (lsu0 >= 10.00001 && lsu0 < 10.001){
|
||||
log_test_(base10, 6.0e-11);
|
||||
} else if (lsu0 >= 10.001 && lsu0 < 10.1){
|
||||
log_test_(base10, 1.5e-12);
|
||||
} else if (lsu0 >= 10.1 && lsu0 < 11){
|
||||
log_test_(base10, 1.6e-14);
|
||||
} else if (lsu0 >= 11 && lsu0 < 13){
|
||||
log_test_(base10, 2.0e-15);
|
||||
} else {
|
||||
log_test_(base10, 6.5e-16);
|
||||
}
|
||||
} else {
|
||||
log_test_(base10, 2e-16);
|
||||
}
|
||||
}
|
||||
|
||||
static void log_test(
|
||||
//input
|
||||
const char* x_str, int x_exp,
|
||||
@ -431,36 +521,7 @@ static void log_test(
|
||||
CAPTURE(x_str); CAPTURE(x_exp);
|
||||
CAPTURE(base10);
|
||||
build_dec80(x_str, x_exp);
|
||||
// decn_to_str_complete(&AccDecn);
|
||||
// printf(" acc: %s\n", Buf);
|
||||
if (base10){
|
||||
log10_decn();
|
||||
} else {
|
||||
ln_decn();
|
||||
}
|
||||
decn_to_str_complete(&AccDecn);
|
||||
CAPTURE(Buf); // log(x)
|
||||
|
||||
//calculate actual result
|
||||
bmp::mpfr_float::default_precision(50);
|
||||
std::string x_full_str(x_str);
|
||||
x_full_str += "e" + std::to_string(x_exp);
|
||||
CAPTURE(x_full_str);
|
||||
bmp::mpfr_float x_actual(x_full_str);
|
||||
CAPTURE(x_actual);
|
||||
if (decn_is_nan(&AccDecn)){
|
||||
//check that NaN is from result of log(-)
|
||||
CHECK(x_actual <= 0);
|
||||
} else {
|
||||
if (base10){
|
||||
x_actual = log10(x_actual);
|
||||
} else {
|
||||
x_actual = log(x_actual);
|
||||
}
|
||||
bmp::mpfr_float calculated(Buf);
|
||||
bmp::mpfr_float rel_diff = abs((x_actual - calculated) / x_actual);
|
||||
CHECK(rel_diff < 3e-16); //TODO
|
||||
}
|
||||
log_test(base10);
|
||||
}
|
||||
|
||||
TEST_CASE("log"){
|
||||
@ -476,6 +537,46 @@ TEST_CASE("log"){
|
||||
log_test("123", 12345);
|
||||
}
|
||||
|
||||
TEST_CASE("log random"){
|
||||
std::default_random_engine gen;
|
||||
std::uniform_int_distribution<int> distrib(0,99);
|
||||
std::uniform_int_distribution<int> exp_distrib(-99,99);
|
||||
std::uniform_int_distribution<int> sign_distrib(0,1);
|
||||
for (int j = 0; j < NUM_RAND_TESTS; j++){
|
||||
for (int i = 0; i < DEC80_NUM_LSU; i++){
|
||||
AccDecn.lsu[i] = distrib(gen);
|
||||
}
|
||||
int exp = exp_distrib(gen);
|
||||
set_exponent(&AccDecn, exp, 0);
|
||||
int base10 = sign_distrib(gen);
|
||||
log_test(base10);
|
||||
}
|
||||
}
|
||||
|
||||
static void log_test_near1(int lsu0_low, int lsu0_high, int exp){
|
||||
std::default_random_engine gen;
|
||||
std::uniform_int_distribution<int> lsu0_distrib(lsu0_low, lsu0_high);
|
||||
std::uniform_int_distribution<int> distrib(0,99);
|
||||
std::uniform_int_distribution<int> exp_distrib(-99,99);
|
||||
std::uniform_int_distribution<int> sign_distrib(0,1);
|
||||
for (int j = 0; j < NUM_RAND_TESTS; j++){
|
||||
AccDecn.lsu[0] = lsu0_distrib(gen);
|
||||
for (int i = 1; i < DEC80_NUM_LSU; i++){
|
||||
AccDecn.lsu[i] = distrib(gen);
|
||||
}
|
||||
set_exponent(&AccDecn, exp, 0);
|
||||
int base10 = sign_distrib(gen);
|
||||
log_test(base10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("log random near 1"){
|
||||
log_test_near1(0, 99, -1);
|
||||
log_test_near1(80, 99, -1);
|
||||
log_test_near1(10, 99, 0);
|
||||
log_test_near1(10, 20, 0);
|
||||
}
|
||||
|
||||
static void exp_test(
|
||||
//input
|
||||
const char* x_str, int x_exp,
|
||||
|
Loading…
Reference in New Issue
Block a user