From 6399cbf44f414df657005c77d8b1186333fee863 Mon Sep 17 00:00:00 2001 From: Jeff Wang Date: Wed, 1 May 2019 03:51:29 -0400 Subject: [PATCH] modify code to use accumulator architecture to minimize pointer usage --- .gitignore | 2 + src/calc.c | 14 +- src/decn/decn.c | 248 ++++++++++++++++--------------- src/decn/decn.h | 13 +- src/decn/decn_test.c | 269 +++++++++++++++------------------- src/decn/decn_test_refout.txt | 66 +++++++++ src/main.c | 2 +- src/utils.h | 1 + 8 files changed, 339 insertions(+), 276 deletions(-) create mode 100644 src/decn/decn_test_refout.txt diff --git a/.gitignore b/.gitignore index df76334..10bfdec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ *.hex +*.bak CMakeLists.txt.user build*/* .project .cproject +*.kdev4 .settings/* diff --git a/src/calc.c b/src/calc.c index ee1e412..5e78d0a 100644 --- a/src/calc.c +++ b/src/calc.c @@ -7,6 +7,8 @@ #include "decn/decn.h" #include "utils.h" +#include "calc.h" + #define STACK_SIZE 4 //must be a power of 2 #define STACK_X 0 @@ -29,7 +31,7 @@ void push_decn(const char* signif_str, exp_t exponent, uint8_t no_lift){ if (!no_lift){ StackPtr--; } - build_dec80(&stack(STACK_X), signif_str, exponent); + set_x(signif_str, exponent); } void clear_x(void){ @@ -37,7 +39,8 @@ void clear_x(void){ } void set_x(const char* signif_str, exp_t exponent){ - build_dec80(&stack(STACK_X), signif_str, exponent); + build_dec80(signif_str, exponent); + copy_decn(&stack(STACK_X), &AccDecn); } __xdata dec80* get_x(void){ @@ -47,11 +50,14 @@ __xdata dec80* get_y(void){ return &stack(STACK_Y); } -static void do_binary_op(void (*f_ptr)(dec80*, const dec80*)){ +static void do_binary_op(void (*f_ptr)(void)){ if (decn_is_nan(&stack(STACK_Y)) || decn_is_nan(&stack(STACK_X))){ set_dec80_NaN(&stack(STACK_Y)); } else { - f_ptr(&stack(STACK_Y), &stack(STACK_X)); + copy_decn(&AccDecn, &stack(STACK_Y)); + copy_decn(&BDecn, &stack(STACK_X)); + f_ptr(); + copy_decn(&stack(STACK_Y), &AccDecn); } pop(); } diff --git a/src/decn/decn.c b/src/decn/decn.c index 80a0b50..fd93dcc 100644 --- a/src/decn/decn.c +++ b/src/decn/decn.c @@ -7,13 +7,16 @@ #include "../utils.h" +#include "decn.h" + + #define EXTRA_CHECKS -//#define DEBUG -//#define DEBUG_COMPARE_MAGN -//#define DEBUG_ADD -//#define DEBUG_MULT -//#define DEBUG_MULT_ALL //even more verbose -//#define DEBUG_DIV +// #define DEBUG +// #define DEBUG_COMPARE_MAGN +// #define DEBUG_ADD +// #define DEBUG_MULT +// #define DEBUG_MULT_ALL //even more verbose +// #define DEBUG_DIV #ifndef DESKTOP //#undef EXTRA_CHECKS @@ -34,14 +37,14 @@ #define assert(x) #endif -#include "decn.h" - #ifdef DESKTOP static const uint8_t num_digits_display = DEC80_NUM_LSU*2; #else static const uint8_t num_digits_display = 16; #endif +__idata dec80 AccDecn, BDecn; + void copy_decn(dec80* dest, const dec80* src){ uint8_t i; @@ -149,7 +152,7 @@ static void remove_leading_zeros(dec80* x){ set_exponent(x, exponent, is_negative); } -void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ +void build_dec80(const char* signif_str, exp_t exponent){ enum { SIGN_ZERO, SIGN_ZERO_SEEN_POINT, @@ -175,7 +178,7 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ //check first digit if (signif_str[0] == '\0'){ - set_dec80_zero(dest); + set_dec80_zero(&AccDecn); return; } else if (signif_str[0] == '-'){ curr_sign = SIGN_NEG_ZERO; @@ -194,14 +197,14 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ #ifdef DEBUG printf(" ERROR: multiple '.'s in string\n"); #endif - set_dec80_NaN(dest); + set_dec80_NaN(&AccDecn); return; } #endif } else if (signif_str[i] >= '1' && signif_str[i] <= '9'){ if (nibble_i < DEC80_NUM_LSU*2){ if (nibble_i & 1) { //odd - dest->lsu[nibble_i/2] = save_nibble * 10 + (signif_str[i] - '0'); + AccDecn.lsu[nibble_i/2] = save_nibble * 10 + (signif_str[i] - '0'); } else { save_nibble = signif_str[i] - '0'; } @@ -233,7 +236,7 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ if (!IS_ZERO(curr_sign)){ //non-zero value if (nibble_i < DEC80_NUM_LSU*2){ if (nibble_i & 1) { //odd - dest->lsu[nibble_i/2] = save_nibble * 10 + 0; + AccDecn.lsu[nibble_i/2] = save_nibble * 10 + 0; } else { save_nibble = 0; } @@ -257,7 +260,7 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ } else if (signif_str[i] == '\0'){ //done if (IS_ZERO(curr_sign)){ //zero - set_dec80_zero(dest); + set_dec80_zero(&AccDecn); return; } else { //not zero @@ -265,11 +268,11 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ //write out saved nibble, if it exists // (saved while nibble_i even, nibble_i then incremented to odd) if (nibble_i & 1){ //odd - dest->lsu[nibble_i/2] = save_nibble * 10; + AccDecn.lsu[nibble_i/2] = save_nibble * 10; nibble_i++; //increment for zeroing out } //zero out any old data - zero_remaining_dec80(dest, nibble_i/2); + zero_remaining_dec80(&AccDecn, nibble_i/2); // adjust exponent for left-aligned significand input // or for number of digits past decimal point if (num_lr_points > 0){ //left count exists @@ -282,7 +285,7 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ printf(" overflow (new_exp, exp)=(%d,%d)\n", new_exponent, exponent); #endif - set_dec80_NaN(dest); + set_dec80_NaN(&AccDecn); return; } #endif @@ -297,7 +300,7 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ printf(" underflow (new_exp, exp)=(%d,%d)\n", new_exponent, exponent); #endif - set_dec80_NaN(dest); + set_dec80_NaN(&AccDecn); return; } #endif @@ -307,15 +310,15 @@ void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){ } exponent = new_exponent; //set negative bit - set_exponent(dest, exponent, IS_NEG(curr_sign)); + set_exponent(&AccDecn, exponent, IS_NEG(curr_sign)); //normalize - remove_leading_zeros(dest); + remove_leading_zeros(&AccDecn); #ifdef DEBUG printf(" num_lr_points (%d), new_exp (%d), sign (%d), exp (%d)\n", num_lr_points, new_exponent, curr_sign, exponent); printf(" "); for (i = 0; i < DEC80_NUM_LSU; i++){ - printf("%02d,", dest->lsu[i]); + printf("%02d,", AccDecn.lsu[i]); } printf("\n"); #endif @@ -390,14 +393,14 @@ void negate_decn(dec80* x){ (x->exponent) ^= xor_val; } -int8_t compare_magn(const dec80* a, const dec80* b){ //ab: 1 +static int8_t compare_magn(void){ //returns ab: 1 uint8_t a_i, b_i; exp_t a_exp=0, b_exp=0; int8_t a_signif_b = 0; //ab: 1 static __xdata dec80 a_tmp, b_tmp; //copy - copy_decn(&a_tmp, a); - copy_decn(&b_tmp, b); + copy_decn(&a_tmp, &AccDecn); + copy_decn(&b_tmp, &BDecn); //normalize remove_leading_zeros(&a_tmp); remove_leading_zeros(&b_tmp); @@ -445,35 +448,35 @@ int8_t compare_magn(const dec80* a, const dec80* b){ //ab: 1 return a_signif_b; } -int8_t compare_decn(const dec80* a, const dec80* b){ //ab: 1 +static int8_t compare_decn(void){ //returns ab: 1 int8_t is_neg; //handle zero special cases - if (decn_is_zero(a) && decn_is_zero(b)){ + if (decn_is_zero(&AccDecn) && decn_is_zero(&BDecn)){ return 0; - } else if (decn_is_zero(a)){ - if (b->exponent < 0){ + } else if (decn_is_zero(&AccDecn)){ + if (BDecn.exponent < 0){ return 1; } else { return -1; } - } else if (decn_is_zero(b)){ - if (a->exponent < 0){ + } else if (decn_is_zero(&BDecn)){ + if (AccDecn.exponent < 0){ return -1; } else { return 1; } } //handle cases where signs differ - if (a->exponent < 0 && b->exponent > 0){ + if (AccDecn.exponent < 0 && BDecn.exponent > 0){ return -1; - } else if (a->exponent > 0 && b->exponent < 0){ + } else if (AccDecn.exponent > 0 && BDecn.exponent < 0){ return 1; } //signs must now be the same, either both pos, or both neg - is_neg = (a->exponent < 0 ? -1 : 1); + is_neg = (AccDecn.exponent < 0 ? -1 : 1); - return is_neg * compare_magn(a, b); + return is_neg * compare_magn(); } //WARNING: for add_decn() and sub_mag() functions only @@ -513,8 +516,8 @@ static void sub_mag(dec80* acc, const dec80* x){ } #ifdef DEBUG_ADD extern char Buf[DECN_BUF_SIZE]; - decn_to_str_complete(buf, &tmp); - printf(" incr_exp tmp: %s\n", buf); + decn_to_str_complete(Buf, &tmp); + printf(" incr_exp tmp: %s\n", Buf); #endif //do subtraction for (i = DEC80_NUM_LSU - 1; i >=0; i--){ @@ -532,128 +535,128 @@ static void sub_mag(dec80* acc, const dec80* x){ assert(carry == 0); //shouldn't be carry out if |acc| > |x| } -void add_decn(dec80* acc, const dec80* x){ +void add_decn(void){ static __xdata dec80 tmp; int8_t rel; uint8_t carry = 0; int8_t i; //check if zero - if (decn_is_zero(x)){ + if (decn_is_zero(&BDecn)){ return; - } else if (decn_is_zero(acc)){ - copy_decn(acc, x); + } else if (decn_is_zero(&AccDecn)){ + copy_decn(&AccDecn, &BDecn); return; } //handle cases where signs differ - if (acc->exponent < 0 && x->exponent >= 0){ + if (AccDecn.exponent < 0 && BDecn.exponent >= 0){ // -acc, +x - rel = compare_magn(acc, x); + rel = compare_magn(); if (rel == 1){ #ifdef DEBUG_ADD printf("|-acc| > |+x|\n"); #endif - sub_mag(acc, x); + sub_mag(&AccDecn, &BDecn); return; } else if (rel == -1){ #ifdef DEBUG_ADD printf("|-acc| < |+x|\n"); #endif - copy_decn(&tmp, x); - sub_mag(&tmp, acc); - copy_decn(acc, &tmp); + copy_decn(&tmp, &BDecn); + sub_mag(&tmp, &AccDecn); + copy_decn(&AccDecn, &tmp); return; } else { //equal #ifdef DEBUG_ADD printf("|-acc| == |+x|\n"); #endif - set_dec80_zero(acc); + set_dec80_zero(&AccDecn); return; } - } else if (acc->exponent >= 0 && x->exponent < 0){ + } else if (AccDecn.exponent >= 0 && BDecn.exponent < 0){ // +acc, -x - rel = compare_magn(acc, x); + rel = compare_magn(); if (rel == 1){ #ifdef DEBUG_ADD printf("|+acc| > |-x|\n"); #endif - sub_mag(acc, x); + sub_mag(&AccDecn, &BDecn); return; } else if (rel == -1){ #ifdef DEBUG_ADD printf("|+acc| < |-x|\n"); #endif - copy_decn(&tmp, x); - sub_mag(&tmp, acc); - copy_decn(acc, &tmp); + copy_decn(&tmp, &BDecn); + sub_mag(&tmp, &AccDecn); + copy_decn(&AccDecn, &tmp); return; } else { //equal #ifdef DEBUG_ADD printf("|+acc| == |-x|\n"); #endif - set_dec80_zero(acc); + set_dec80_zero(&AccDecn); return; } } //signs must now be the same, begin adding - copy_decn(&tmp, x); + copy_decn(&tmp, &BDecn); //normalize - remove_leading_zeros(acc); + remove_leading_zeros(&AccDecn); remove_leading_zeros(&tmp); #ifdef DEBUG_ADD extern char Buf[DECN_BUF_SIZE]; - decn_to_str_complete(buf, acc); - printf(" rem_leading_zeros acc: %s\n", buf); - decn_to_str_complete(buf, &tmp); - printf(" rem_leading_zeros tmp: %s\n", buf); + decn_to_str_complete(Buf, &AccDecn); + printf(" rem_leading_zeros acc: %s\n", Buf); + decn_to_str_complete(Buf, &tmp); + printf(" rem_leading_zeros tmp: %s\n", Buf); #endif - if (get_exponent(acc) > get_exponent(&tmp)){ - _incr_exp(&tmp, get_exponent(acc)); - } else if (get_exponent(acc) < get_exponent(&tmp)){ + if (get_exponent(&AccDecn) > get_exponent(&tmp)){ + _incr_exp(&tmp, get_exponent(&AccDecn)); + } else if (get_exponent(&AccDecn) < get_exponent(&tmp)){ //shift significand and adjust exponent to match - for (i = 0; i < get_exponent(&tmp) - get_exponent(acc); i++){ - shift_right(acc); + for (i = 0; i < get_exponent(&tmp) - get_exponent(&AccDecn); i++){ + shift_right(&AccDecn); } - set_exponent(acc, get_exponent(&tmp), (acc->exponent < 0)); + set_exponent(&AccDecn, get_exponent(&tmp), (AccDecn.exponent < 0)); } #ifdef DEBUG_ADD extern char Buf[DECN_BUF_SIZE]; - decn_to_str_complete(buf, acc); - printf(" incr_exp acc: %s\n", buf); - decn_to_str_complete(buf, &tmp); - printf(" incr_exp tmp: %s\n", buf); + decn_to_str_complete(Buf, &AccDecn); + printf(" incr_exp acc: %s\n", Buf); + decn_to_str_complete(Buf, &tmp); + printf(" incr_exp tmp: %s\n", Buf); #endif //do addition for (i = DEC80_NUM_LSU - 1; i >= 0; i--){ - uint8_t digit100 = acc->lsu[i] + tmp.lsu[i] + carry; - acc->lsu[i] = digit100 % 100; + uint8_t digit100 = AccDecn.lsu[i] + tmp.lsu[i] + carry; + AccDecn.lsu[i] = digit100 % 100; carry = digit100 / 100; assert(carry < 100); } //may need to rescale number if (carry > 0){ - exp_t curr_exp = get_exponent(acc); - rel = (acc->exponent < 0); //is_neg? + exp_t curr_exp = get_exponent(&AccDecn); + rel = (AccDecn.exponent < 0); //is_neg? #ifdef DEBUG_ADD printf(" carry out: %d", carry); #endif //shift right if (carry < 10){ - shift_right(acc); - acc->lsu[0] += carry*10; //carry gets shifted into most significant digit + shift_right(&AccDecn); + AccDecn.lsu[0] += carry*10; //carry gets shifted into most significant digit curr_exp++; } else { - shift_right(acc); - shift_right(acc); - acc->lsu[0] = carry; + shift_right(&AccDecn); + shift_right(&AccDecn); + AccDecn.lsu[0] = carry; curr_exp+=2; } //track sign - set_exponent(acc, curr_exp, rel); //rel==is_neg? + set_exponent(&AccDecn, curr_exp, rel); //rel==is_neg? } } -void mult_decn(dec80* acc, const dec80* x){ +void mult_decn(void){ static __xdata dec80 tmp; //copy of x static __xdata dec80 acc_tmp; //holds sum int8_t i, j; @@ -661,23 +664,23 @@ void mult_decn(dec80* acc, const dec80* x){ uint8_t is_neg; exp_t new_exponent; //initialize values - copy_decn(&tmp, x); + copy_decn(&tmp, &BDecn); set_dec80_zero(&acc_tmp); //normalize - remove_leading_zeros(acc); + remove_leading_zeros(&AccDecn); remove_leading_zeros(&tmp); //store new sign #ifdef EXP16 - if ((acc->exponent & 0x8000) ^ (tmp.exponent & 0x8000)){ //signs differ + if ((AccDecn.exponent & 0x8000) ^ (tmp.exponent & 0x8000)){ //signs differ #else - if ((acc->exponent & 0x80) ^ (tmp.exponent & 0x80)){ //signs differ + if ((AccDecn.exponent & 0x80) ^ (tmp.exponent & 0x80)){ //signs differ #endif is_neg = 1; } else { is_neg = 0; } //calculate new exponent - new_exponent = get_exponent(acc) + get_exponent(&tmp); + new_exponent = get_exponent(&AccDecn) + get_exponent(&tmp); #ifdef DEBUG_MULT printf("\n new exponent: %d:", new_exponent); #endif @@ -685,7 +688,7 @@ void mult_decn(dec80* acc, const dec80* x){ for (i = DEC80_NUM_LSU - 1; i >= 0; i--){ //partial product for (j = DEC80_NUM_LSU - 1; j >= 0; j--){ - uint16_t digit100 = acc_tmp.lsu[j] + (tmp.lsu[i] * acc->lsu[j]) + carry; + uint16_t digit100 = acc_tmp.lsu[j] + (tmp.lsu[i] * AccDecn.lsu[j]) + carry; acc_tmp.lsu[j] = digit100 % 100; carry = digit100 / 100; assert(carry < 100); @@ -694,7 +697,7 @@ void mult_decn(dec80* acc, const dec80* x){ printf("\n%d:", i); printf("\n acc:"); for (j = 0; j < DEC80_NUM_LSU; j++){ - printf(" %3d", acc->lsu[j]); + printf(" %3d", AccDecn.lsu[j]); } printf("\n x:"); for (j = 0; j < DEC80_NUM_LSU; j++){ @@ -737,24 +740,25 @@ void mult_decn(dec80* acc, const dec80* x){ if (new_exponent < DEC80_MAX_EXP && new_exponent > DEC80_MIN_EXP){ set_exponent(&acc_tmp, new_exponent, is_neg); } else { - set_dec80_NaN(acc); + set_dec80_NaN(&AccDecn); return; } //copy back to acc - copy_decn(acc, &acc_tmp); + copy_decn(&AccDecn, &acc_tmp); //normalize - remove_leading_zeros(acc); + remove_leading_zeros(&AccDecn); } -void div_decn(dec80* acc, const dec80* x){ - static __xdata dec80 tmp; //copy of x, holds current 1/x estimate +void div_decn(void){ + static __xdata dec80 curr_recip; //copy of x, holds current 1/x estimate + static __xdata dec80 x_copy; //holds copy of original x static __xdata dec80 acc_copy; //holds copy of original acc uint8_t i; exp_t initial_exp; //check divide by zero #ifdef EXTRA_CHECKS - if (decn_is_zero(x)){ - set_dec80_NaN(acc); + if (decn_is_zero(&BDecn)){ + set_dec80_NaN(&AccDecn); #ifdef DESKTOP printf("error division by 0\n"); #endif @@ -762,9 +766,11 @@ void div_decn(dec80* acc, const dec80* x){ } #endif //store copy of acc for final multiply by 1/x - copy_decn(&acc_copy, acc); + copy_decn(&acc_copy, &AccDecn); + //store copy of x + copy_decn(&x_copy, &BDecn); //get initial estimate for 1/x, by negating exponent, and setting signif. to 1 - initial_exp = get_exponent(x); + initial_exp = get_exponent(&BDecn); #ifdef DEBUG_DIV printf("exponent %d", initial_exp); #endif @@ -773,41 +779,45 @@ void div_decn(dec80* acc, const dec80* x){ #ifdef DEBUG_DIV printf(" -> %d\n", initial_exp); #endif - set_exponent(&tmp, initial_exp, (x->exponent < 0)); //set exponent, copy sign - tmp.lsu[0] = 10; //1 with implicit point + set_exponent(&curr_recip, initial_exp, (BDecn.exponent < 0)); //set exponent, copy sign + curr_recip.lsu[0] = 10; //1 with implicit point for (i = 1; i < DEC80_NUM_LSU; i++){ - tmp.lsu[i] = 0; + curr_recip.lsu[i] = 0; } - copy_decn(acc, &tmp); + copy_decn(&AccDecn, &curr_recip); //do newton raphson iterations for (i = 0; i < DEC80_NUM_LSU; i++){ //just fix number of iterations for now #ifdef DEBUG_DIV - extern char Buf[80]; - decn_to_str_complete(Buf, &tmp); + extern char Buf[DECN_BUF_SIZE]; + decn_to_str_complete(Buf, &curr_recip); printf("%2d: %s\n", i, Buf); #endif - mult_decn(acc, x); + copy_decn(&BDecn, &x_copy); + mult_decn(); #ifdef DEBUG_DIV - decn_to_str_complete(Buf, acc); + decn_to_str_complete(Buf, &AccDecn); printf(" %20s: %s\n", "recip*x", Buf); #endif - negate_decn(acc); - add_decn(acc, &DECN_1); + negate_decn(&AccDecn); + copy_decn(&BDecn, &DECN_1); + add_decn(); #ifdef DEBUG_DIV - decn_to_str_complete(Buf, acc); + decn_to_str_complete(Buf, &AccDecn); printf(" %20s: %s\n", "(1-recip*x)", Buf); #endif - mult_decn(acc, &tmp); + copy_decn(&BDecn, &curr_recip); + mult_decn(); #ifdef DEBUG_DIV - decn_to_str_complete(Buf, acc); + decn_to_str_complete(Buf, &AccDecn); printf(" %20s: %s\n", "recip * (1-recip*x)", Buf); #endif - add_decn(acc, &tmp); + add_decn(); //new_est(acc) = recip + (1 - recip*x)*recip, where tmp is current recip estimate - copy_decn(&tmp, acc); + copy_decn(&curr_recip, &AccDecn); } //acc now holds 1/x, multiply by original acc to complete division - mult_decn(acc, &acc_copy); + copy_decn(&BDecn, &acc_copy); + mult_decn(); } static void set_str_error(char* buf){ @@ -983,8 +993,16 @@ void decn_to_str_complete(char* buf, const dec80* x){ u32str(exponent, &buf[i], 10); //adds null terminator automatically } } - } -#endif + +void build_decn_at(dec80* dest, const char* signif_str, exp_t exponent){ + dec80 tmp; + copy_decn(&tmp, &AccDecn); //save + build_dec80(signif_str, exponent); + copy_decn(dest, &AccDecn); + copy_decn(&AccDecn, &tmp); //restore +} + +#endif //DESKTOP diff --git a/src/decn/decn.h b/src/decn/decn.h index 166f9a3..58cb6c6 100644 --- a/src/decn/decn.h +++ b/src/decn/decn.h @@ -50,21 +50,19 @@ static const dec80 DECN_1 = { //remove sign bit, and return 15 bit exponent sign-extended to 16 bits exp_t get_exponent(const dec80* x); -//void dec64to80(dec80* dest, const dec64* src); - void copy_decn(dec80* dest, const dec80* src); +extern __idata dec80 AccDecn, BDecn; -void build_dec80(dec80* dest, const char* signif_str, exp_t exponent); +void build_dec80(const char* signif_str, exp_t exponent); void set_dec80_zero(dec80* dest); void set_dec80_NaN(dec80* dest); uint8_t decn_is_nan(const dec80* x); void negate_decn(dec80* x); -int8_t compare_decn(const dec80* a, const dec80* b); //ab: 1 -void add_decn(dec80* acc, const dec80* x); -void mult_decn(dec80* acc, const dec80* x); -void div_decn(dec80* acc, const dec80* x); +void add_decn(void); +void mult_decn(void); +void div_decn(void); //buf should hold at least 18 + 4 + 5 + 1 = 28 #define DECN_BUF_SIZE 28 @@ -73,6 +71,7 @@ int8_t decn_to_str(char* buf, const dec80* x); #ifdef DESKTOP //complete string including exponent void decn_to_str_complete(char* buf, const dec80* x); +void build_decn_at(dec80* dest, const char* signif_str, exp_t exponent); #endif #ifdef __cplusplus diff --git a/src/decn/decn_test.c b/src/decn/decn_test.c index 420dabe..ed931d9 100644 --- a/src/decn/decn_test.c +++ b/src/decn/decn_test.c @@ -9,209 +9,180 @@ char Buf[DECN_BUF_SIZE]; + +static dec80 diff; + +static void take_diff(void){ //diff = acc - diff + negate_decn(&diff); + dec80 tmp_copy, tmp_copy2; + copy_decn(&tmp_copy, &AccDecn); //save + copy_decn(&tmp_copy2, &BDecn); //save + copy_decn(&BDecn, &diff); + add_decn(); + copy_decn(&diff, &AccDecn); + copy_decn(&AccDecn, &tmp_copy); //restore + copy_decn(&BDecn, &tmp_copy2); //restore +} + +static void div_test( + const char* a_str, int a_exp, + const char* b_str, int b_exp, + const char* res_str, + const char* res_calc, int res_exp) +{ + build_dec80(a_str, a_exp); + build_decn_at(&BDecn, b_str, b_exp); + decn_to_str_complete(Buf, &AccDecn); + printf(" acc: %s\n", Buf); + decn_to_str_complete(Buf, &BDecn); + printf(" b: %s\n", Buf); + div_decn(); + decn_to_str_complete(Buf, &AccDecn); + printf("acc/b: %s\n", Buf); + printf(" : %s\n", res_str); + build_decn_at(&diff, res_calc, res_exp); + take_diff(); + decn_to_str_complete(Buf, &diff); + printf(" : %s\n\n", Buf); +} + int main(void){ - dec80 acc, b; +// dec80 acc, b; - build_dec80(&acc, "0.0009234567890123456", 7); - decn_to_str_complete(Buf, &acc); + build_dec80("0.0009234567890123456", 7); + decn_to_str_complete(Buf, &AccDecn); printf(" acc: %s\n", Buf); - build_dec80(&acc, "9.234567890123456", 3); - decn_to_str_complete(Buf, &acc); + build_dec80("9.234567890123456", 3); + decn_to_str_complete(Buf, &AccDecn); printf(" acc: %s\n", Buf); - negate_decn(&acc); - decn_to_str_complete(Buf, &acc); + negate_decn(&AccDecn); + decn_to_str_complete(Buf, &AccDecn); printf("-acc: %s\n", Buf); - build_dec80(&b, "-92.3456789012345678", 1); - decn_to_str_complete(Buf, &b); + dec80 tmp_copy; + copy_decn(&tmp_copy, &AccDecn); //save + build_dec80("-92.3456789012345678", 1); + copy_decn(&BDecn, &AccDecn); + copy_decn(&AccDecn, &tmp_copy); //restore + decn_to_str_complete(Buf, &BDecn); printf(" b: %s\n", Buf); - decn_to_str_complete(Buf, &acc); + decn_to_str_complete(Buf, &AccDecn); printf("-acc: %s\n", Buf); //compare result of b - acc - add_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); + add_decn(); + decn_to_str_complete(Buf, &AccDecn); printf("b - a: %s\n", Buf); printf(" : %s\n", "-10158.0246791358016"); - dec80 diff; - build_dec80(&diff, "-1.01580246791358016", 4); - negate_decn(&diff); - add_decn(&diff, &acc); + build_decn_at(&diff, "-1.01580246791358016", 4); + take_diff(); decn_to_str_complete(Buf, &diff); printf(" : %s\n\n", Buf); //new acc for acc - b test - decn_to_str_complete(Buf, &acc); + decn_to_str_complete(Buf, &AccDecn); printf("acc: %s\n", Buf); - negate_decn(&b); - decn_to_str_complete(Buf, &b); + negate_decn(&BDecn); + decn_to_str_complete(Buf, &BDecn); printf(" -b: %s\n", Buf); - add_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); + add_decn(); + decn_to_str_complete(Buf, &AccDecn); //compare result of new acc - b printf("acc - b: %s\n", Buf); printf(" : %s\n", "-9234.567890123456"); - build_dec80(&diff, "-9.234567890123456", 3); - negate_decn(&diff); - add_decn(&diff, &acc); + build_decn_at(&diff, "-9.234567890123456", 3); + take_diff(); decn_to_str_complete(Buf, &diff); printf(" : %s\n\n", Buf); //new acc and b for multiply test -// build_dec80(&acc, "7", 2); - build_dec80(&acc, "92.34567890123456", 2); - build_dec80(&b, "-92.3456789012345678", 1); - decn_to_str_complete(Buf, &acc); +// build_dec80("7", 2); + build_dec80("92.34567890123456", 2); + build_decn_at(&BDecn, "-92.3456789012345678", 1); + decn_to_str_complete(Buf, &AccDecn); printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); + decn_to_str_complete(Buf, &BDecn); printf(" b: %s\n", Buf); - mult_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); + mult_decn(); + decn_to_str_complete(Buf, &AccDecn); printf("acc*b: %s\n", Buf); printf(" : %s\n", "-8527724.41172991849"); - build_dec80(&diff, "-8.52772441172991849", 6); - negate_decn(&diff); - add_decn(&diff, &acc); + build_decn_at(&diff, "-8.52772441172991849", 6); + take_diff(); decn_to_str_complete(Buf, &diff); printf(" : %s\n\n", Buf); //new acc and b for divide test - build_dec80(&acc, "3.14", 60); - build_dec80(&b, "-1.5", -2); - decn_to_str_complete(Buf, &acc); - printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); - printf(" b: %s\n", Buf); - div_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); - printf("acc/b: %s\n", Buf); - printf(" : %s\n", "-2.09333333333333334E62"); - build_dec80(&diff, "-2.09333333333333334", 62); - negate_decn(&diff); - add_decn(&diff, &acc); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n\n", Buf); + div_test( + "3.14", 60, + "-1.5", -2, + "-2.09333333333333334E62", + "-2.09333333333333334", 62 + ); //new acc and b for divide test - build_dec80(&acc, "4", 0); - build_dec80(&b, "4", 0); - decn_to_str_complete(Buf, &acc); - printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); - printf(" b: %s\n", Buf); - div_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); - printf("acc/b: %s\n", Buf); - printf(" : %s\n", "1."); - build_dec80(&diff, "1", 0); - negate_decn(&diff); - add_decn(&diff, &acc); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n\n", Buf); + div_test( + "4", 0, + "4", 0, + "1.", + "1", 0 + ); //new acc and b for divide test - build_dec80(&acc, "1", 0); - build_dec80(&b, "3", 0); - decn_to_str_complete(Buf, &acc); - printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); - printf(" b: %s\n", Buf); - div_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); - printf("acc/b: %s\n", Buf); - printf(" : %s\n", "0.333333333333333336"); - build_dec80(&diff, "3.33333333333333336", -1); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n", Buf); - negate_decn(&diff); - add_decn(&diff, &acc); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n\n", Buf); + div_test( + "1", 0, + "3", 0, + "0.333333333333333336", + "3.33333333333333336", -1 + ); //small fractions >= 1/10 - build_dec80(&acc, "0.333", 0); - build_dec80(&b, "3.33", -1); - decn_to_str_complete(Buf, &acc); + build_dec80("0.333", 0); + build_decn_at(&BDecn, "3.33", -1); + decn_to_str_complete(Buf, &AccDecn); printf(" a : %s\n", Buf); - decn_to_str_complete(Buf, &b); + decn_to_str_complete(Buf, &BDecn); printf(" b : %s\n", Buf); - negate_decn(&b); - add_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); + negate_decn(&BDecn); + add_decn(); + decn_to_str_complete(Buf, &AccDecn); printf("a - b: %s\n", Buf); //new acc and b for divide test - build_dec80(&acc, "500", 0); - build_dec80(&b, "99", 0); - decn_to_str_complete(Buf, &acc); - printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); - printf(" b: %s\n", Buf); - div_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); - printf("acc/b: %s\n", Buf); - printf(" : %s\n", "5.05050505050505055"); - build_dec80(&diff, "5.05050505050505055", 0); - negate_decn(&diff); - add_decn(&diff, &acc); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n\n", Buf); + div_test( + "500", 0, + "99", 0, + "5.05050505050505055", + "5.05050505050505055", 0 + ); //new acc and b for divide test - build_dec80(&acc, "500", 0); - build_dec80(&b, "2", 0); - decn_to_str_complete(Buf, &acc); - printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); - printf(" b: %s\n", Buf); - div_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); - printf("acc/b: %s\n", Buf); - printf(" : %s\n", "250."); - build_dec80(&diff, "250", 0); - negate_decn(&diff); - add_decn(&diff, &acc); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n\n", Buf); + div_test( + "500", 0, + "2", 0, + "250.", + "250", 0 + ); //new acc and b for divide test - build_dec80(&acc, "3", 0); - build_dec80(&b, "25", -15); - decn_to_str_complete(Buf, &acc); - printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); - printf(" b: %s\n", Buf); - div_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); - printf("acc/b: %s\n", Buf); - printf(" : %s\n", "120000000000000"); - build_dec80(&diff, "1.2", 14); - negate_decn(&diff); - add_decn(&diff, &acc); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n\n", Buf); + div_test( + "3", 0, + "25", -15, + "120000000000000", + "1.2", 14 + ); //new acc and b for divide test - build_dec80(&acc, "0.02", 0); - build_dec80(&b, "0.03", 0); - decn_to_str_complete(Buf, &acc); - printf(" acc: %s\n", Buf); - decn_to_str_complete(Buf, &b); - printf(" b: %s\n", Buf); - div_decn(&acc, &b); - decn_to_str_complete(Buf, &acc); - printf("acc/b: %s\n", Buf); - printf(" : %s\n", "0.666666666666666672"); - build_dec80(&diff, "0.666666666666666672", 0); - negate_decn(&diff); - add_decn(&diff, &acc); - decn_to_str_complete(Buf, &diff); - printf(" : %s\n\n", Buf); - + div_test( + "0.02", 0, + "0.03", 0, + "0.666666666666666672", + "0.666666666666666672", 0 + ); return 0; } diff --git a/src/decn/decn_test_refout.txt b/src/decn/decn_test_refout.txt new file mode 100644 index 0000000..0a9f095 --- /dev/null +++ b/src/decn/decn_test_refout.txt @@ -0,0 +1,66 @@ + acc: 9234.567890123456 + acc: 9234.567890123456 +-acc: -9234.567890123456 + b: -923.456789012345678 +-acc: -9234.567890123456 +b - a: -10158.0246791358016 + : -10158.0246791358016 + : 0 + +acc: -10158.0246791358016 + -b: 923.456789012345678 +acc - b: -9234.567890123456 + : -9234.567890123456 + : 0 + + acc: 9234.567890123456 + b: -923.456789012345678 +acc*b: -8527724.41172991849 + : -8527724.41172991849 + : 0 + + acc: 3.14E60 + b: -0.015 +acc/b: -2.09333333333333334E62 + : -2.09333333333333334E62 + : 0 + + acc: 4. + b: 4. +acc/b: 1. + : 1. + : 0 + + acc: 1. + b: 3. +acc/b: 0.333333333333333336 + : 0.333333333333333336 + : 0 + + a : 0.333 + b : 0.333 +a - b: 0 + acc: 500. + b: 99. +acc/b: 5.05050505050505055 + : 5.05050505050505055 + : 0 + + acc: 500. + b: 2. +acc/b: 250. + : 250. + : 0 + + acc: 3. + b: 2.5E-14 +acc/b: 120000000000000. + : 120000000000000 + : 0 + + acc: 0.02 + b: 0.03 +acc/b: 0.666666666666666672 + : 0.666666666666666672 + : 0 + diff --git a/src/main.c b/src/main.c index 1e79870..ea958ba 100644 --- a/src/main.c +++ b/src/main.c @@ -172,7 +172,7 @@ int main() ExpBuf[0] = 0; ExpBuf[1] = 0; - LCD_OutString("STC RPN Calculator v1.01", 32); + LCD_OutString("STC RPN Calculator v1.02", 32); #ifdef DESKTOP LcdAvailable.release(); #endif diff --git a/src/utils.h b/src/utils.h index 5fef534..5c729c6 100644 --- a/src/utils.h +++ b/src/utils.h @@ -37,6 +37,7 @@ char* u32str(uint32_t x, char* buf, uint8_t base); #if defined(DESKTOP) || defined(IS_ECLIPSE) #define __xdata +#define __idata #define __sfr #define __at uint8_t* #define SDCC_ISR(isr, reg)