various bugfixes for decn arithmetic
This commit is contained in:
parent
43edb291cf
commit
4ed3d1654e
@ -191,6 +191,11 @@ void build_dec80(dec80* dest, const char* signif_str, int16_t exponent){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
nibble_i++;
|
nibble_i++;
|
||||||
|
//track number of digits R of decimal point
|
||||||
|
//must do this before changing is_zero
|
||||||
|
if (curr_sign == SIGN_ZERO_SEEN_POINT || curr_sign == SIGN_NEG_ZERO_SEEN_POINT){
|
||||||
|
num_lr_points = -1;
|
||||||
|
}
|
||||||
//track sign
|
//track sign
|
||||||
if (curr_sign == SIGN_ZERO){
|
if (curr_sign == SIGN_ZERO){
|
||||||
curr_sign = SIGN_POS;
|
curr_sign = SIGN_POS;
|
||||||
@ -201,7 +206,7 @@ void build_dec80(dec80* dest, const char* signif_str, int16_t exponent){
|
|||||||
} else if (curr_sign == SIGN_NEG_ZERO_SEEN_POINT){
|
} else if (curr_sign == SIGN_NEG_ZERO_SEEN_POINT){
|
||||||
curr_sign = SIGN_NEG_SEEN_POINT;
|
curr_sign = SIGN_NEG_SEEN_POINT;
|
||||||
}
|
}
|
||||||
//track number digits L/R of decimal point
|
//track number digits L of decimal point
|
||||||
if (!SEEN_POINT(curr_sign)){ //haven't seen decimal point yet
|
if (!SEEN_POINT(curr_sign)){ //haven't seen decimal point yet
|
||||||
num_lr_points++; //increase left count
|
num_lr_points++; //increase left count
|
||||||
}
|
}
|
||||||
@ -220,7 +225,9 @@ void build_dec80(dec80* dest, const char* signif_str, int16_t exponent){
|
|||||||
//track number digits L/R of decimal point
|
//track number digits L/R of decimal point
|
||||||
if (SEEN_POINT(curr_sign)){
|
if (SEEN_POINT(curr_sign)){
|
||||||
if (IS_ZERO(curr_sign)){ //tracking 0s to right of point
|
if (IS_ZERO(curr_sign)){ //tracking 0s to right of point
|
||||||
if (num_lr_points <= 0){ //no left count exists
|
if (num_lr_points == 0){ //no left count exists
|
||||||
|
num_lr_points = -2;
|
||||||
|
} else if (num_lr_points < 0){ //continue tracking count
|
||||||
num_lr_points--; //increase right count
|
num_lr_points--; //increase right count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,10 +269,9 @@ void build_dec80(dec80* dest, const char* signif_str, int16_t exponent){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else if (num_lr_points < 0) { //right count exists
|
} else if (num_lr_points < 0) { //right count exists
|
||||||
// (-num_past_point represents #0s right of decimal)
|
// (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;
|
||||||
new_exponent -= 1; //decimal point after 1st non-zero number
|
|
||||||
//check for underflow
|
//check for underflow
|
||||||
#ifdef EXTRA_CHECKS
|
#ifdef EXTRA_CHECKS
|
||||||
if (new_exponent > exponent || exponent < DEC80_MIN_EXP){
|
if (new_exponent > exponent || exponent < DEC80_MIN_EXP){
|
||||||
@ -284,6 +290,8 @@ void build_dec80(dec80* dest, const char* signif_str, int16_t exponent){
|
|||||||
exponent = new_exponent;
|
exponent = new_exponent;
|
||||||
//set negative bit
|
//set negative bit
|
||||||
set_exponent(dest, exponent, IS_NEG(curr_sign));
|
set_exponent(dest, exponent, IS_NEG(curr_sign));
|
||||||
|
//normalize
|
||||||
|
remove_leading_zeros(dest);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf(" num_lr_points (%d), new_exp (%d), sign (%d), exp (%d)\n",
|
printf(" num_lr_points (%d), new_exp (%d), sign (%d), exp (%d)\n",
|
||||||
num_lr_points, new_exponent, curr_sign, exponent);
|
num_lr_points, new_exponent, curr_sign, exponent);
|
||||||
@ -673,7 +681,7 @@ void mult_decn(dec80* acc, const dec80* x){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//handle last carry
|
//handle last carry
|
||||||
if (carry > 10){
|
if (carry >= 10){
|
||||||
//shift
|
//shift
|
||||||
shift_right(&acc_tmp);
|
shift_right(&acc_tmp);
|
||||||
shift_right(&acc_tmp);
|
shift_right(&acc_tmp);
|
||||||
@ -698,6 +706,7 @@ void div_decn(dec80* acc, const dec80* x){
|
|||||||
static __xdata dec80 tmp; //copy of x, holds current 1/x estimate
|
static __xdata dec80 tmp; //copy of x, holds current 1/x estimate
|
||||||
static __xdata dec80 acc_copy; //holds copy of original acc
|
static __xdata dec80 acc_copy; //holds copy of original acc
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
int16_t initial_exp;
|
||||||
//check divide by zero
|
//check divide by zero
|
||||||
#ifdef EXTRA_CHECKS
|
#ifdef EXTRA_CHECKS
|
||||||
if (decn_is_zero(x)){
|
if (decn_is_zero(x)){
|
||||||
@ -708,14 +717,27 @@ void div_decn(dec80* acc, const dec80* x){
|
|||||||
//store copy of acc for final multiply by 1/x
|
//store copy of acc for final multiply by 1/x
|
||||||
copy_decn(&acc_copy, acc);
|
copy_decn(&acc_copy, acc);
|
||||||
//get initial estimate for 1/x, by negating exponent, and setting signif. to 1
|
//get initial estimate for 1/x, by negating exponent, and setting signif. to 1
|
||||||
set_exponent(&tmp, -get_exponent(x), (x->exponent < 0));
|
initial_exp = get_exponent(x);
|
||||||
|
#ifdef DEBUG_DIV
|
||||||
|
printf("exponent %d", initial_exp);
|
||||||
|
#endif
|
||||||
|
if (initial_exp >= 0){
|
||||||
|
//necessary to subtract 1 for convergence
|
||||||
|
initial_exp = -initial_exp - 1;
|
||||||
|
} else {
|
||||||
|
initial_exp = -initial_exp;
|
||||||
|
}
|
||||||
|
#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
|
tmp.lsu[0] = 10; //1 with implicit point
|
||||||
for (i = 1; i < DEC80_NUM_LSU; i++){
|
for (i = 1; i < DEC80_NUM_LSU; i++){
|
||||||
tmp.lsu[i] = 0;
|
tmp.lsu[i] = 0;
|
||||||
}
|
}
|
||||||
copy_decn(acc, &tmp);
|
copy_decn(acc, &tmp);
|
||||||
//do newton raphson iterations
|
//do newton raphson iterations
|
||||||
for (i = 0; i < 20; i++){ //just fix number of iterations for now
|
for (i = 0; i < DEC80_NUM_LSU + 4; i++){ //just fix number of iterations for now
|
||||||
#ifdef DEBUG_DIV
|
#ifdef DEBUG_DIV
|
||||||
extern char Buf[80];
|
extern char Buf[80];
|
||||||
dec80_to_str(Buf, &tmp);
|
dec80_to_str(Buf, &tmp);
|
||||||
@ -806,7 +828,8 @@ void dec80_to_str(char* buf, const dec80* x){
|
|||||||
}
|
}
|
||||||
//print 2nd digit
|
//print 2nd digit
|
||||||
buf[i] = (tmp.lsu[0] % 10) + '0';
|
buf[i] = (tmp.lsu[0] % 10) + '0';
|
||||||
if (tmp.lsu[0] % 10 == 0){
|
if (tmp.lsu[0] % 10 == 0 && (use_sci || exponent < 0)){
|
||||||
|
|
||||||
trailing_zeros = 1;
|
trailing_zeros = 1;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
@ -843,9 +866,11 @@ void dec80_to_str(char* buf, const dec80* x){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//track trailing 0s
|
//track trailing 0s
|
||||||
if (tmp.lsu[digit100] == 0){
|
if (tmp.lsu[digit100] == 0 && (use_sci || exponent < -1)){
|
||||||
trailing_zeros += 2;
|
trailing_zeros += 2;
|
||||||
} else if (tmp.lsu[digit100] == 10){
|
} else if (tmp.lsu[digit100] == 0 && (use_sci || exponent < 0)){
|
||||||
|
trailing_zeros += 1;
|
||||||
|
} else if (tmp.lsu[digit100] == 10 && (use_sci || exponent < 0)){
|
||||||
trailing_zeros = 1;
|
trailing_zeros = 1;
|
||||||
} else {
|
} else {
|
||||||
trailing_zeros = 0;
|
trailing_zeros = 0;
|
||||||
|
@ -34,14 +34,14 @@ int main(void){
|
|||||||
//compare result of b - acc
|
//compare result of b - acc
|
||||||
add_decn(&acc, &b);
|
add_decn(&acc, &b);
|
||||||
dec80_to_str(Buf, &acc);
|
dec80_to_str(Buf, &acc);
|
||||||
printf("\nb - a: %s", Buf);
|
printf("b - a: %s\n", Buf);
|
||||||
printf("\n : %s", "-10158.0246791358016");
|
printf(" : %s\n", "-10158.0246791358016");
|
||||||
dec80 diff;
|
dec80 diff;
|
||||||
build_dec80(&diff, "-1.01580246791358016", 4);
|
build_dec80(&diff, "-1.01580246791358016", 4);
|
||||||
negate_decn(&diff);
|
negate_decn(&diff);
|
||||||
add_decn(&diff, &acc);
|
add_decn(&diff, &acc);
|
||||||
dec80_to_str(Buf, &diff);
|
dec80_to_str(Buf, &diff);
|
||||||
printf("\n : %s\n\n", Buf);
|
printf(" : %s\n\n", Buf);
|
||||||
|
|
||||||
//new acc for acc - b test
|
//new acc for acc - b test
|
||||||
dec80_to_str(Buf, &acc);
|
dec80_to_str(Buf, &acc);
|
||||||
@ -96,6 +96,88 @@ int main(void){
|
|||||||
dec80_to_str(Buf, &diff);
|
dec80_to_str(Buf, &diff);
|
||||||
printf(" : %s\n\n", Buf);
|
printf(" : %s\n\n", Buf);
|
||||||
|
|
||||||
|
//new acc and b for divide test
|
||||||
|
build_dec80(&acc, "4", 0);
|
||||||
|
build_dec80(&b, "4", 0);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf(" acc: %s\n", Buf);
|
||||||
|
dec80_to_str(Buf, &b);
|
||||||
|
printf(" b: %s\n", Buf);
|
||||||
|
div_decn(&acc, &b);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf("acc/b: %s\n", Buf);
|
||||||
|
printf(" : %s\n", "1.00000000");
|
||||||
|
build_dec80(&diff, "1", 0);
|
||||||
|
negate_decn(&diff);
|
||||||
|
add_decn(&diff, &acc);
|
||||||
|
dec80_to_str(Buf, &diff);
|
||||||
|
printf(" : %s\n\n", Buf);
|
||||||
|
|
||||||
|
//new acc and b for divide test
|
||||||
|
build_dec80(&acc, "1", 0);
|
||||||
|
build_dec80(&b, "3", 0);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf(" acc: %s\n", Buf);
|
||||||
|
dec80_to_str(Buf, &b);
|
||||||
|
printf(" b: %s\n", Buf);
|
||||||
|
div_decn(&acc, &b);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf("acc/b: %s\n", Buf);
|
||||||
|
printf(" : %s\n", "0.333333333333333336");
|
||||||
|
build_dec80(&diff, "3.33333333333333336", -1);
|
||||||
|
dec80_to_str(Buf, &diff);
|
||||||
|
printf(" : %s\n", Buf);
|
||||||
|
negate_decn(&diff);
|
||||||
|
add_decn(&diff, &acc);
|
||||||
|
dec80_to_str(Buf, &diff);
|
||||||
|
printf(" : %s\n\n", Buf);
|
||||||
|
|
||||||
|
//small fractions >= 1/10
|
||||||
|
build_dec80(&acc, "0.333", 0);
|
||||||
|
build_dec80(&b, "3.33", -1);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf(" a : %s\n", Buf);
|
||||||
|
dec80_to_str(Buf, &b);
|
||||||
|
printf(" b : %s\n", Buf);
|
||||||
|
negate_decn(&b);
|
||||||
|
add_decn(&acc, &b);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf("a - b: %s\n", Buf);
|
||||||
|
|
||||||
|
//new acc and b for divide test
|
||||||
|
build_dec80(&acc, "500", 0);
|
||||||
|
build_dec80(&b, "99", 0);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf(" acc: %s\n", Buf);
|
||||||
|
dec80_to_str(Buf, &b);
|
||||||
|
printf(" b: %s\n", Buf);
|
||||||
|
div_decn(&acc, &b);
|
||||||
|
dec80_to_str(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);
|
||||||
|
dec80_to_str(Buf, &diff);
|
||||||
|
printf(" : %s\n\n", Buf);
|
||||||
|
|
||||||
|
//new acc and b for divide test
|
||||||
|
build_dec80(&acc, "500", 0);
|
||||||
|
build_dec80(&b, "2", 0);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf(" acc: %s\n", Buf);
|
||||||
|
dec80_to_str(Buf, &b);
|
||||||
|
printf(" b: %s\n", Buf);
|
||||||
|
div_decn(&acc, &b);
|
||||||
|
dec80_to_str(Buf, &acc);
|
||||||
|
printf("acc/b: %s\n", Buf);
|
||||||
|
printf(" : %s\n", "250.0");
|
||||||
|
build_dec80(&diff, "250", 0);
|
||||||
|
negate_decn(&diff);
|
||||||
|
add_decn(&diff, &acc);
|
||||||
|
dec80_to_str(Buf, &diff);
|
||||||
|
printf(" : %s\n\n", Buf);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user