increase test coverage
This commit is contained in:
parent
38c4e4678c
commit
b04a95e420
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
# 3rd party tools
|
# 3rd party tools
|
||||||
find_package(Qt5 COMPONENTS Widgets Qml Quick REQUIRED)
|
find_package(Qt5 COMPONENTS Widgets Qml Quick REQUIRED)
|
||||||
|
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
|
|
||||||
|
#code coverage
|
||||||
|
add_library(coverage_config INTERFACE)
|
||||||
|
target_compile_options(coverage_config INTERFACE -O0 -g --coverage)
|
||||||
|
target_link_libraries(coverage_config INTERFACE --coverage)
|
||||||
|
|
||||||
# decn library
|
# decn library
|
||||||
add_library(decn decn.c)
|
add_library(decn decn.c)
|
||||||
|
|
||||||
|
# decn library with coverage
|
||||||
|
add_library(decn_cover decn.c)
|
||||||
|
target_link_libraries(decn_cover PUBLIC coverage_config)
|
||||||
|
|
||||||
add_executable(decn_test decn_test.c ../utils.c)
|
add_executable(decn_test decn_test.c ../utils.c)
|
||||||
target_link_libraries(decn_test decn)
|
target_link_libraries(decn_test decn_cover coverage_config)
|
||||||
|
|
||||||
add_executable(decn_tests catch_main.cpp decn_tests.cpp ../utils.c)
|
add_executable(decn_tests catch_main.cpp decn_tests.cpp ../utils.c)
|
||||||
target_link_libraries(decn_tests decn mpfr)
|
target_link_libraries(decn_tests decn_cover coverage_config mpfr)
|
||||||
|
|
||||||
# decn prototyping
|
# decn prototyping
|
||||||
add_subdirectory(proto)
|
add_subdirectory(proto)
|
||||||
|
101
src/decn/decn.c
101
src/decn/decn.c
@ -30,9 +30,9 @@
|
|||||||
// #define DEBUG_MULT
|
// #define DEBUG_MULT
|
||||||
// #define DEBUG_MULT_ALL //even more verbose
|
// #define DEBUG_MULT_ALL //even more verbose
|
||||||
// #define DEBUG_DIV
|
// #define DEBUG_DIV
|
||||||
#define DEBUG_LOG
|
// #define DEBUG_LOG
|
||||||
// #define DEBUG_LOG_ALL //even more verbose
|
// #define DEBUG_LOG_ALL //even more verbose
|
||||||
#define DEBUG_EXP
|
// #define DEBUG_EXP
|
||||||
// #define DEBUG_EXP_ALL //even more verbose
|
// #define DEBUG_EXP_ALL //even more verbose
|
||||||
|
|
||||||
#ifndef DESKTOP
|
#ifndef DESKTOP
|
||||||
@ -211,6 +211,7 @@ void build_dec80(__xdata const char* signif_str, exp_t exponent){
|
|||||||
return;
|
return;
|
||||||
} else if (signif_str[0] == '-'){
|
} else if (signif_str[0] == '-'){
|
||||||
curr_sign = SIGN_NEG_ZERO;
|
curr_sign = SIGN_NEG_ZERO;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//go through digits
|
//go through digits
|
||||||
@ -293,7 +294,7 @@ void build_dec80(__xdata const char* signif_str, exp_t exponent){
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
//not zero
|
//not zero
|
||||||
int8_t new_exponent;
|
exp_t new_exponent = exponent;
|
||||||
//write out saved nibble, if it exists
|
//write out saved nibble, if it exists
|
||||||
// (saved while nibble_i even, nibble_i then incremented to odd)
|
// (saved while nibble_i even, nibble_i then incremented to odd)
|
||||||
if (nibble_i & 1){ //odd
|
if (nibble_i & 1){ //odd
|
||||||
@ -307,37 +308,28 @@ void build_dec80(__xdata const char* signif_str, exp_t exponent){
|
|||||||
if (num_lr_points > 0){ //left count exists
|
if (num_lr_points > 0){ //left count exists
|
||||||
assert(DEC80_NUM_LSU*2 > num_lr_points);
|
assert(DEC80_NUM_LSU*2 > num_lr_points);
|
||||||
new_exponent = exponent + (num_lr_points - 1); //1 digit left of implicit point
|
new_exponent = exponent + (num_lr_points - 1); //1 digit left of implicit point
|
||||||
//check for overflow
|
//overflow is checked later, should be impossible to overflow int16_t:
|
||||||
#ifdef EXTRA_CHECKS
|
assert(new_exponent >= exponent);
|
||||||
if (new_exponent < exponent || exponent > DEC80_MAX_EXP){
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf(" overflow (new_exp, exp)=(%d,%d)\n",
|
|
||||||
new_exponent, exponent);
|
|
||||||
#endif
|
|
||||||
set_dec80_NaN(&AccDecn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else if (num_lr_points < 0) { //right count exists
|
} else if (num_lr_points < 0) { //right count exists
|
||||||
// (num_lr_points represents exponent shift)
|
// (num_lr_points represents exponent shift)
|
||||||
// (this ends up being a subtraction)
|
// (this ends up being a subtraction)
|
||||||
new_exponent = exponent + num_lr_points;
|
new_exponent = exponent + num_lr_points;
|
||||||
//check for underflow
|
//underflow is checked later, should be impossible to overflow int16_t:
|
||||||
#ifdef EXTRA_CHECKS
|
assert(new_exponent <= exponent);
|
||||||
if (new_exponent > exponent || exponent < DEC80_MIN_EXP){
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf(" underflow (new_exp, exp)=(%d,%d)\n",
|
|
||||||
new_exponent, exponent);
|
|
||||||
#endif
|
|
||||||
set_dec80_NaN(&AccDecn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
//no change
|
|
||||||
new_exponent = exponent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check for over/underflow of exponent
|
||||||
exponent = new_exponent;
|
exponent = new_exponent;
|
||||||
|
#ifdef EXTRA_CHECKS
|
||||||
|
if (exponent > DEC80_MAX_EXP || exponent < DEC80_MIN_EXP){
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf(" over/underflow (new_exp, exp)=(%d,%d)\n",
|
||||||
|
new_exponent, exponent);
|
||||||
|
#endif
|
||||||
|
set_dec80_NaN(&AccDecn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
//set negative bit
|
//set negative bit
|
||||||
set_exponent(&AccDecn, exponent, IS_NEG(curr_sign));
|
set_exponent(&AccDecn, exponent, IS_NEG(curr_sign));
|
||||||
//normalize
|
//normalize
|
||||||
@ -354,6 +346,12 @@ void build_dec80(__xdata const char* signif_str, exp_t exponent){
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else { //invalid character
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf(" invalid character %c at i=%d\n", signif_str[i], i);
|
||||||
|
#endif
|
||||||
|
set_dec80_NaN(&AccDecn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
assert(i < DECN_BUF_SIZE);
|
assert(i < DECN_BUF_SIZE);
|
||||||
@ -439,7 +437,7 @@ static int8_t compare_magn(void){ //returns a<b: -1, a==b: 0, a>b: 1
|
|||||||
//compare signifcands while tracking magnitude
|
//compare signifcands while tracking magnitude
|
||||||
for (
|
for (
|
||||||
a_i = 0, b_i = 0;
|
a_i = 0, b_i = 0;
|
||||||
a_i < DEC80_NUM_LSU && b_i < DEC80_NUM_LSU;
|
a_i < DEC80_NUM_LSU;
|
||||||
a_i++, b_i++, a_exp+=2, b_exp+=2
|
a_i++, b_i++, a_exp+=2, b_exp+=2
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -662,26 +660,17 @@ void add_decn(void){
|
|||||||
uint8_t digit100 = AccDecn.lsu[i] + BDecn.lsu[i] + carry;
|
uint8_t digit100 = AccDecn.lsu[i] + BDecn.lsu[i] + carry;
|
||||||
AccDecn.lsu[i] = digit100 % 100;
|
AccDecn.lsu[i] = digit100 % 100;
|
||||||
carry = digit100 / 100;
|
carry = digit100 / 100;
|
||||||
assert(carry < 100);
|
assert(carry <= 1);
|
||||||
}
|
}
|
||||||
//may need to rescale number
|
//may need to rescale number
|
||||||
if (carry > 0){
|
if (carry > 0){
|
||||||
|
assert(carry == 1);
|
||||||
exp_t curr_exp = get_exponent(&AccDecn);
|
exp_t curr_exp = get_exponent(&AccDecn);
|
||||||
rel = (AccDecn.exponent < 0); //is_neg?
|
rel = (AccDecn.exponent < 0); //is_neg?
|
||||||
#ifdef DEBUG_ADD
|
|
||||||
printf(" carry out: %d", carry);
|
|
||||||
#endif
|
|
||||||
//shift right
|
//shift right
|
||||||
if (carry < 10){
|
shift_right(&AccDecn);
|
||||||
shift_right(&AccDecn);
|
AccDecn.lsu[0] += 10; //carry gets shifted into most significant digit
|
||||||
AccDecn.lsu[0] += carry*10; //carry gets shifted into most significant digit
|
curr_exp++;
|
||||||
curr_exp++;
|
|
||||||
} else {
|
|
||||||
shift_right(&AccDecn);
|
|
||||||
shift_right(&AccDecn);
|
|
||||||
AccDecn.lsu[0] = carry;
|
|
||||||
curr_exp+=2;
|
|
||||||
}
|
|
||||||
//track sign
|
//track sign
|
||||||
set_exponent(&AccDecn, curr_exp, rel); //rel==is_neg?
|
set_exponent(&AccDecn, curr_exp, rel); //rel==is_neg?
|
||||||
}
|
}
|
||||||
@ -715,7 +704,8 @@ void mult_decn(void){
|
|||||||
//calculate new exponent
|
//calculate new exponent
|
||||||
new_exponent = get_exponent(&AccDecn) + get_exponent(&BDecn);
|
new_exponent = get_exponent(&AccDecn) + get_exponent(&BDecn);
|
||||||
#ifdef DEBUG_MULT
|
#ifdef DEBUG_MULT
|
||||||
printf("\n new exponent: %d, is_neg: %u", new_exponent, is_neg);
|
printf("\n a_exp: %d, b_exp: %d", get_exponent(&AccDecn), get_exponent(&BDecn));
|
||||||
|
printf("\n new exponent: %d, is_neg: %u", new_exponent, is_neg);
|
||||||
#endif
|
#endif
|
||||||
//do multiply
|
//do multiply
|
||||||
for (i = DEC80_NUM_LSU - 1; i >= 0; i--){
|
for (i = DEC80_NUM_LSU - 1; i >= 0; i--){
|
||||||
@ -1079,13 +1069,11 @@ void exp_decn(void){
|
|||||||
//check if in range
|
//check if in range
|
||||||
copy_decn(&SAVED, &AccDecn); //save = accum
|
copy_decn(&SAVED, &AccDecn); //save = accum
|
||||||
set_dec80_zero(&BDecn);
|
set_dec80_zero(&BDecn);
|
||||||
BDecn.lsu[0] = 23;
|
BDecn.lsu[0] = 29;
|
||||||
BDecn.lsu[1] = 02;
|
BDecn.lsu[1] = 47;
|
||||||
BDecn.lsu[2] = 58;
|
BDecn.exponent = 2; //b = 294.7
|
||||||
BDecn.lsu[2] = 51;
|
|
||||||
BDecn.exponent = 2; //b = 230.25851
|
|
||||||
negate_decn(&BDecn);
|
negate_decn(&BDecn);
|
||||||
add_decn(); //accum = x - 230.25851 (should be negative if in range)
|
add_decn(); //accum = x - 294.7 (should be negative if in range)
|
||||||
if (!(AccDecn.exponent < 0)){ //if not negative
|
if (!(AccDecn.exponent < 0)){ //if not negative
|
||||||
set_dec80_NaN(&AccDecn);
|
set_dec80_NaN(&AccDecn);
|
||||||
return;
|
return;
|
||||||
@ -1249,7 +1237,12 @@ static void set_str_error(void){
|
|||||||
Buf[5] = '\0';
|
Buf[5] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t decn_to_str(const dec80* x){
|
#ifdef DESKTOP
|
||||||
|
int
|
||||||
|
#else
|
||||||
|
int8_t
|
||||||
|
#endif
|
||||||
|
decn_to_str(const dec80* x){
|
||||||
#define INSERT_DOT() Buf[i++]='.'
|
#define INSERT_DOT() Buf[i++]='.'
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
uint8_t digit100;
|
uint8_t digit100;
|
||||||
@ -1377,7 +1370,11 @@ int8_t decn_to_str(const dec80* x){
|
|||||||
//print exponent
|
//print exponent
|
||||||
if (use_sci){
|
if (use_sci){
|
||||||
//check for overflow
|
//check for overflow
|
||||||
|
#ifdef DESKTOP
|
||||||
|
if (exponent > DEC80_MAX_EXP || exponent < DEC80_MIN_EXP){
|
||||||
|
#else
|
||||||
if (exponent > DECN_MAX_PRINT_EXP || exponent < DECN_MIN_PRINT_EXP){
|
if (exponent > DECN_MAX_PRINT_EXP || exponent < DECN_MIN_PRINT_EXP){
|
||||||
|
#endif
|
||||||
set_str_error();
|
set_str_error();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1398,7 +1395,7 @@ int8_t decn_to_str(const dec80* x){
|
|||||||
#ifdef DESKTOP
|
#ifdef DESKTOP
|
||||||
//complete string including exponent
|
//complete string including exponent
|
||||||
void decn_to_str_complete(const dec80* x){
|
void decn_to_str_complete(const dec80* x){
|
||||||
int8_t exponent = decn_to_str(x);
|
int exponent = decn_to_str(x);
|
||||||
int i;
|
int i;
|
||||||
//find end of string
|
//find end of string
|
||||||
for (i = 0; Buf[i] != '\0'; i++);
|
for (i = 0; Buf[i] != '\0'; i++);
|
||||||
|
@ -107,7 +107,13 @@ void exp10_decn(void);
|
|||||||
//Buf should hold at least 18 + 4 + 5 + 1 = 28
|
//Buf should hold at least 18 + 4 + 5 + 1 = 28
|
||||||
#define DECN_BUF_SIZE 28
|
#define DECN_BUF_SIZE 28
|
||||||
extern __xdata char Buf[DECN_BUF_SIZE];
|
extern __xdata char Buf[DECN_BUF_SIZE];
|
||||||
int8_t decn_to_str(const dec80* x);
|
|
||||||
|
#ifdef DESKTOP
|
||||||
|
int
|
||||||
|
#else
|
||||||
|
int8_t
|
||||||
|
#endif
|
||||||
|
decn_to_str(const dec80* x);
|
||||||
|
|
||||||
#ifdef DESKTOP
|
#ifdef DESKTOP
|
||||||
//complete string including exponent
|
//complete string including exponent
|
||||||
|
@ -20,10 +20,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string>
|
||||||
#include <boost/multiprecision/mpfr.hpp>
|
#include <boost/multiprecision/mpfr.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include "decn.h"
|
#include "decn.h"
|
||||||
|
#include "../utils.h"
|
||||||
|
|
||||||
|
|
||||||
namespace bmp = boost::multiprecision;
|
namespace bmp = boost::multiprecision;
|
||||||
@ -46,6 +47,119 @@ TEST_CASE("build decn"){
|
|||||||
negate_decn(&AccDecn);
|
negate_decn(&AccDecn);
|
||||||
decn_to_str_complete(&AccDecn);
|
decn_to_str_complete(&AccDecn);
|
||||||
CHECK_THAT(Buf, Equals("-9234.567890123456"));
|
CHECK_THAT(Buf, Equals("-9234.567890123456"));
|
||||||
|
|
||||||
|
//small positive
|
||||||
|
build_dec80(".1", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("100."));
|
||||||
|
|
||||||
|
build_dec80("0.1", -1);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("0.01"));
|
||||||
|
|
||||||
|
build_dec80("0.01", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("10."));
|
||||||
|
|
||||||
|
//zero
|
||||||
|
build_dec80(".", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("0"));
|
||||||
|
|
||||||
|
build_dec80(".0", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("0"));
|
||||||
|
|
||||||
|
build_dec80("0.", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("0"));
|
||||||
|
|
||||||
|
build_dec80("-0.0", -1);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("0"));
|
||||||
|
|
||||||
|
build_dec80("0", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("0"));
|
||||||
|
|
||||||
|
//small negative
|
||||||
|
build_dec80("-.1", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("-100."));
|
||||||
|
|
||||||
|
build_dec80("-0.1", -1);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("-0.01"));
|
||||||
|
|
||||||
|
build_dec80("-0.001", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("-1."));
|
||||||
|
|
||||||
|
//empty string -> 0
|
||||||
|
build_dec80("", 90);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("0"));
|
||||||
|
|
||||||
|
//too many .
|
||||||
|
build_dec80("..", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
|
||||||
|
//very long (truncated)
|
||||||
|
build_dec80("12345678901234567890", -2);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("123456789012345678."));
|
||||||
|
|
||||||
|
//overflow
|
||||||
|
build_dec80("100", DEC80_MAX_EXP-1);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
|
||||||
|
build_dec80("1", DEC80_MAX_EXP+1);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
|
||||||
|
build_dec80("0.1", DEC80_MAX_EXP+2);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
|
||||||
|
//underflow
|
||||||
|
build_dec80("10", DEC80_MIN_EXP-2);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
|
||||||
|
build_dec80("1", DEC80_MIN_EXP-1);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
|
||||||
|
build_dec80("0.3", DEC80_MIN_EXP);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
CHECK(decn_is_nan(&AccDecn) == 1);
|
||||||
|
|
||||||
|
//left/right count
|
||||||
|
build_dec80("-100.001", 3);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("-100001."));
|
||||||
|
|
||||||
|
//invalid
|
||||||
|
build_dec80(":", 0);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error"));
|
||||||
|
|
||||||
|
//special number that is not NaN
|
||||||
|
AccDecn.lsu[1] = 3;
|
||||||
|
CHECK(decn_is_nan(&AccDecn) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("build_large"){
|
||||||
|
int large_exp = DEC80_MAX_EXP/2 - 50;
|
||||||
|
build_dec80("9.99", large_exp);
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK(AccDecn.exponent == large_exp);
|
||||||
|
std::string expected = "9.99E";
|
||||||
|
expected += std::to_string(large_exp);
|
||||||
|
CHECK_THAT(Buf, Equals(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("small fractions >= 1/10"){
|
TEST_CASE("small fractions >= 1/10"){
|
||||||
@ -91,6 +205,24 @@ TEST_CASE("add"){
|
|||||||
decn_to_str_complete(&AccDecn);
|
decn_to_str_complete(&AccDecn);
|
||||||
//compare result of new acc - b
|
//compare result of new acc - b
|
||||||
CHECK_THAT(Buf, Equals("-9234.567890123456")); //acc-b
|
CHECK_THAT(Buf, Equals("-9234.567890123456")); //acc-b
|
||||||
|
|
||||||
|
//add 0
|
||||||
|
build_decn_at(&BDecn, "0", 0);
|
||||||
|
add_decn();
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("-9234.567890123456")); //same
|
||||||
|
|
||||||
|
//carry into MSB
|
||||||
|
build_dec80( "-82345678901234567.8", -1);
|
||||||
|
build_decn_at(&BDecn, "-87654321098765432.2", -1);
|
||||||
|
add_decn();
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf,Equals("-17000000000000000.")); //acc+b
|
||||||
|
|
||||||
|
//don't negate NaN
|
||||||
|
set_dec80_NaN(&AccDecn);
|
||||||
|
negate_decn(&AccDecn);
|
||||||
|
CHECK(decn_is_nan(&AccDecn));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("multiply"){
|
TEST_CASE("multiply"){
|
||||||
@ -103,6 +235,14 @@ TEST_CASE("multiply"){
|
|||||||
mult_decn();
|
mult_decn();
|
||||||
decn_to_str_complete(&AccDecn);
|
decn_to_str_complete(&AccDecn);
|
||||||
CHECK_THAT(Buf, Equals("-8527724.41172991849")); //acc*b
|
CHECK_THAT(Buf, Equals("-8527724.41172991849")); //acc*b
|
||||||
|
|
||||||
|
//overflow
|
||||||
|
build_dec80("9.99", DEC80_MAX_EXP/2);
|
||||||
|
build_decn_at(&BDecn, "9.99", DEC80_MAX_EXP/2);
|
||||||
|
mult_decn();
|
||||||
|
decn_to_str_complete(&AccDecn);
|
||||||
|
CHECK_THAT(Buf, Equals("Error")); //acc*b
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void div_test(
|
static void div_test(
|
||||||
@ -126,7 +266,6 @@ static void div_test(
|
|||||||
|
|
||||||
//calculate actual result
|
//calculate actual result
|
||||||
bmp::mpfr_float::default_precision(50);
|
bmp::mpfr_float::default_precision(50);
|
||||||
bmp::mpfr_float calculated(Buf);
|
|
||||||
std::string a_full_str(a_str);
|
std::string a_full_str(a_str);
|
||||||
a_full_str += "e" + std::to_string(a_exp);
|
a_full_str += "e" + std::to_string(a_exp);
|
||||||
std::string b_full_str(b_str);
|
std::string b_full_str(b_str);
|
||||||
@ -135,12 +274,24 @@ static void div_test(
|
|||||||
// CAPTURE(b_full_str);
|
// CAPTURE(b_full_str);
|
||||||
bmp::mpfr_float a_actual(a_full_str);
|
bmp::mpfr_float a_actual(a_full_str);
|
||||||
bmp::mpfr_float b_actual(b_full_str);
|
bmp::mpfr_float b_actual(b_full_str);
|
||||||
a_actual /= b_actual;
|
a_actual /= b_actual; //calculate actual result
|
||||||
bmp::mpfr_float rel_diff = abs((a_actual - calculated) / a_actual);
|
if (decn_is_nan(&AccDecn)){
|
||||||
CHECK(rel_diff < 1e-17);
|
//check that NaN result of division by 0
|
||||||
|
CAPTURE(a_actual);
|
||||||
|
CHECK(b_actual == 0);
|
||||||
|
} else {
|
||||||
|
bmp::mpfr_float calculated(Buf);
|
||||||
|
bmp::mpfr_float rel_diff = abs((a_actual - calculated) / a_actual);
|
||||||
|
CHECK(rel_diff < 1e-17);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("division"){
|
TEST_CASE("division"){
|
||||||
|
div_test(
|
||||||
|
"1", 0,
|
||||||
|
"0", 0
|
||||||
|
);
|
||||||
|
|
||||||
div_test(
|
div_test(
|
||||||
"3.14", 60,
|
"3.14", 60,
|
||||||
"-1.5", -2
|
"-1.5", -2
|
||||||
@ -198,22 +349,29 @@ static void log_test(
|
|||||||
|
|
||||||
//calculate actual result
|
//calculate actual result
|
||||||
bmp::mpfr_float::default_precision(50);
|
bmp::mpfr_float::default_precision(50);
|
||||||
bmp::mpfr_float calculated(Buf);
|
|
||||||
std::string x_full_str(x_str);
|
std::string x_full_str(x_str);
|
||||||
x_full_str += "e" + std::to_string(x_exp);
|
x_full_str += "e" + std::to_string(x_exp);
|
||||||
// CAPTURE(x_full_str);
|
CAPTURE(x_full_str);
|
||||||
bmp::mpfr_float x_actual(x_full_str);
|
bmp::mpfr_float x_actual(x_full_str);
|
||||||
if (base10){
|
|
||||||
x_actual = log10(x_actual);
|
|
||||||
} else {
|
|
||||||
x_actual = log(x_actual);
|
|
||||||
}
|
|
||||||
CAPTURE(x_actual);
|
CAPTURE(x_actual);
|
||||||
bmp::mpfr_float rel_diff = abs((x_actual - calculated) / x_actual);
|
if (decn_is_nan(&AccDecn)){
|
||||||
CHECK(rel_diff < 3e-16); //TODO
|
//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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("log"){
|
TEST_CASE("log"){
|
||||||
|
log_test("0", 0);
|
||||||
|
log_test("-1", 0);
|
||||||
log_test("0.155", 0);
|
log_test("0.155", 0);
|
||||||
log_test("10", 0);
|
log_test("10", 0);
|
||||||
log_test("1.1", 10);
|
log_test("1.1", 10);
|
||||||
@ -221,19 +379,27 @@ TEST_CASE("log"){
|
|||||||
log_test("2.02", 0);
|
log_test("2.02", 0);
|
||||||
log_test("1.5", 0, true);
|
log_test("1.5", 0, true);
|
||||||
log_test("9", 99);
|
log_test("9", 99);
|
||||||
|
log_test("123", 12345);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exp_test(
|
static void exp_test(
|
||||||
//input
|
//input
|
||||||
const char* x_str, int x_exp,
|
const char* x_str, int x_exp,
|
||||||
double epsilon=6e-16
|
double epsilon=6e-16,
|
||||||
|
bool base10=false
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
CAPTURE(x_str); CAPTURE(x_exp);
|
CAPTURE(x_str); CAPTURE(x_exp);
|
||||||
|
CAPTURE(base10);
|
||||||
build_dec80(x_str, x_exp);
|
build_dec80(x_str, x_exp);
|
||||||
exp_decn();
|
if (base10){
|
||||||
|
exp10_decn();
|
||||||
|
} else {
|
||||||
|
exp_decn();
|
||||||
|
}
|
||||||
decn_to_str_complete(&AccDecn);
|
decn_to_str_complete(&AccDecn);
|
||||||
CAPTURE(Buf); // exp(x)
|
CAPTURE(Buf); // exp(x)
|
||||||
|
CAPTURE(AccDecn.exponent);
|
||||||
|
|
||||||
//calculate actual result
|
//calculate actual result
|
||||||
bmp::mpfr_float::default_precision(50);
|
bmp::mpfr_float::default_precision(50);
|
||||||
@ -241,12 +407,24 @@ static void exp_test(
|
|||||||
std::string x_full_str(x_str);
|
std::string x_full_str(x_str);
|
||||||
x_full_str += "e" + std::to_string(x_exp);
|
x_full_str += "e" + std::to_string(x_exp);
|
||||||
bmp::mpfr_float x_actual(x_full_str);
|
bmp::mpfr_float x_actual(x_full_str);
|
||||||
|
if (base10){
|
||||||
|
x_actual *= log(10);
|
||||||
|
}
|
||||||
x_actual = exp(x_actual);
|
x_actual = exp(x_actual);
|
||||||
CAPTURE(x_actual);
|
CAPTURE(x_actual);
|
||||||
bmp::mpfr_float rel_diff = abs((x_actual - calculated) / x_actual);
|
bmp::mpfr_float rel_diff = abs((x_actual - calculated) / x_actual);
|
||||||
CHECK(rel_diff < epsilon);
|
CHECK(rel_diff < epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void exp10_test(
|
||||||
|
//input
|
||||||
|
const char* x_str, int x_exp,
|
||||||
|
double epsilon=3e-15
|
||||||
|
)
|
||||||
|
{
|
||||||
|
exp_test(x_str, x_exp, epsilon, true);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("exp"){
|
TEST_CASE("exp"){
|
||||||
exp_test("4.4", 0);
|
exp_test("4.4", 0);
|
||||||
exp_test("0.155", 0);
|
exp_test("0.155", 0);
|
||||||
@ -257,6 +435,25 @@ TEST_CASE("exp"){
|
|||||||
exp_test("2.02", -10);
|
exp_test("2.02", -10);
|
||||||
exp_test("2.02", 0);
|
exp_test("2.02", 0);
|
||||||
exp_test("1.5", 0);
|
exp_test("1.5", 0);
|
||||||
|
exp_test("294.69999999", 0, 8e-15);
|
||||||
|
|
||||||
|
//do not operate on NaN
|
||||||
|
set_dec80_NaN(&AccDecn);
|
||||||
|
exp_decn();
|
||||||
|
CHECK(decn_is_nan(&AccDecn)); //still NaN
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("exp10"){
|
||||||
|
exp10_test("4.4", 0);
|
||||||
|
exp10_test("0.155", 0);
|
||||||
|
exp10_test("9.999", 0);
|
||||||
|
exp10_test("10", 0);
|
||||||
|
exp10_test("10.001", 0);
|
||||||
|
exp10_test("2.02", -10);
|
||||||
|
exp10_test("2.02", 0);
|
||||||
|
exp10_test("1.5", 0);
|
||||||
|
exp10_test("127", 0, 3e-14);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pow_test(
|
static void pow_test(
|
||||||
@ -306,3 +503,8 @@ TEST_CASE("power"){
|
|||||||
"201", 0
|
"201", 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("u32str corner"){
|
||||||
|
u32str(0, &Buf[0], 10);
|
||||||
|
CHECK_THAT(Buf, Equals("0"));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user