use global registers for division, have sub_mag() operate directly on Accum and B
This commit is contained in:
parent
747355222d
commit
4f020da222
@ -44,7 +44,10 @@ static const uint8_t num_digits_display = 16;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
__idata dec80 AccDecn, BDecn;
|
__idata dec80 AccDecn, BDecn;
|
||||||
__idata dec80 TmpDecn;
|
__idata dec80 TmpDecn; //used by add_decn() and mult_decn()
|
||||||
|
__idata dec80 Tmp2Decn; //used by div_decn()
|
||||||
|
__idata dec80 Tmp3Decn; //used by div_decn()
|
||||||
|
__idata dec80 Tmp4Decn; //used by div_decn()
|
||||||
|
|
||||||
__xdata char Buf[DECN_BUF_SIZE];
|
__xdata char Buf[DECN_BUF_SIZE];
|
||||||
|
|
||||||
@ -504,18 +507,16 @@ static void _incr_exp(dec80* acc, exp_t exponent){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//for internal use only,
|
//for internal use only,
|
||||||
//acc must be larger than x in absolute value
|
//AccDecn must be larger than BDecn in absolute value
|
||||||
//subtract by equal addition algorithm
|
//subtract by equal addition algorithm
|
||||||
static void sub_mag(dec80* acc, const dec80* x){
|
static void sub_mag(){
|
||||||
int8_t i;
|
int8_t i;
|
||||||
uint8_t carry = 0;
|
uint8_t carry = 0;
|
||||||
static __xdata dec80 tmp;
|
|
||||||
copy_decn(&tmp, x);
|
|
||||||
//normalize
|
//normalize
|
||||||
remove_leading_zeros(acc);
|
remove_leading_zeros(&AccDecn);
|
||||||
remove_leading_zeros(&tmp);
|
remove_leading_zeros(&BDecn);
|
||||||
if (get_exponent(acc) != get_exponent(&tmp)){
|
if (get_exponent(&AccDecn) != get_exponent(&BDecn)){
|
||||||
_incr_exp(&tmp, get_exponent(acc));
|
_incr_exp(&BDecn, get_exponent(&AccDecn));
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
decn_to_str_complete(&tmp);
|
decn_to_str_complete(&tmp);
|
||||||
@ -524,15 +525,15 @@ static void sub_mag(dec80* acc, const dec80* x){
|
|||||||
//do subtraction
|
//do subtraction
|
||||||
for (i = DEC80_NUM_LSU - 1; i >=0; i--){
|
for (i = DEC80_NUM_LSU - 1; i >=0; i--){
|
||||||
uint8_t digit100;
|
uint8_t digit100;
|
||||||
if (acc->lsu[i] >= (tmp.lsu[i] + carry)){
|
if (AccDecn.lsu[i] >= (BDecn.lsu[i] + carry)){
|
||||||
digit100 = acc->lsu[i] - (tmp.lsu[i] + carry);
|
digit100 = AccDecn.lsu[i] - (BDecn.lsu[i] + carry);
|
||||||
carry = 0;
|
carry = 0;
|
||||||
} else {
|
} else {
|
||||||
digit100 = acc->lsu[i] + 100 - (tmp.lsu[i] + carry);
|
digit100 = AccDecn.lsu[i] + 100 - (BDecn.lsu[i] + carry);
|
||||||
carry = 1;
|
carry = 1;
|
||||||
}
|
}
|
||||||
assert(digit100 < 100);
|
assert(digit100 < 100);
|
||||||
acc->lsu[i] = digit100;
|
AccDecn.lsu[i] = digit100;
|
||||||
}
|
}
|
||||||
assert(carry == 0); //shouldn't be carry out if |acc| > |x|
|
assert(carry == 0); //shouldn't be carry out if |acc| > |x|
|
||||||
}
|
}
|
||||||
@ -557,15 +558,16 @@ void add_decn(void){
|
|||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
printf("|-acc| > |+x|\n");
|
printf("|-acc| > |+x|\n");
|
||||||
#endif
|
#endif
|
||||||
sub_mag(&AccDecn, &BDecn);
|
sub_mag();
|
||||||
return;
|
return;
|
||||||
} else if (rel == -1){
|
} else if (rel == -1){
|
||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
printf("|-acc| < |+x|\n");
|
printf("|-acc| < |+x|\n");
|
||||||
#endif
|
#endif
|
||||||
copy_decn(&TmpDecn, &BDecn);
|
copy_decn(&TmpDecn, &BDecn);
|
||||||
sub_mag(&TmpDecn, &AccDecn);
|
copy_decn(&BDecn, &AccDecn);
|
||||||
copy_decn(&AccDecn, &TmpDecn);
|
copy_decn(&AccDecn, &TmpDecn);
|
||||||
|
sub_mag();
|
||||||
return;
|
return;
|
||||||
} else { //equal
|
} else { //equal
|
||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
@ -581,15 +583,16 @@ void add_decn(void){
|
|||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
printf("|+acc| > |-x|\n");
|
printf("|+acc| > |-x|\n");
|
||||||
#endif
|
#endif
|
||||||
sub_mag(&AccDecn, &BDecn);
|
sub_mag();
|
||||||
return;
|
return;
|
||||||
} else if (rel == -1){
|
} else if (rel == -1){
|
||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
printf("|+acc| < |-x|\n");
|
printf("|+acc| < |-x|\n");
|
||||||
#endif
|
#endif
|
||||||
copy_decn(&TmpDecn, &BDecn);
|
copy_decn(&TmpDecn, &BDecn);
|
||||||
sub_mag(&TmpDecn, &AccDecn);
|
copy_decn(&BDecn, &AccDecn);
|
||||||
copy_decn(&AccDecn, &TmpDecn);
|
copy_decn(&AccDecn, &TmpDecn);
|
||||||
|
sub_mag();
|
||||||
return;
|
return;
|
||||||
} else { //equal
|
} else { //equal
|
||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
@ -745,9 +748,9 @@ void mult_decn(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void div_decn(void){
|
void div_decn(void){
|
||||||
static __xdata dec80 curr_recip; //copy of x, holds current 1/x estimate
|
#define CURR_RECIP Tmp2Decn //copy of x, holds current 1/x estimate
|
||||||
static __xdata dec80 x_copy; //holds copy of original x
|
#define X_COPY Tmp3Decn //holds copy of original x
|
||||||
static __xdata dec80 acc_copy; //holds copy of original acc
|
#define ACC_COPY Tmp4Decn //holds copy of original acc
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
exp_t initial_exp;
|
exp_t initial_exp;
|
||||||
//check divide by zero
|
//check divide by zero
|
||||||
@ -764,9 +767,9 @@ void div_decn(void){
|
|||||||
remove_leading_zeros(&AccDecn);
|
remove_leading_zeros(&AccDecn);
|
||||||
remove_leading_zeros(&BDecn);
|
remove_leading_zeros(&BDecn);
|
||||||
//store copy of acc for final multiply by 1/x
|
//store copy of acc for final multiply by 1/x
|
||||||
copy_decn(&acc_copy, &AccDecn);
|
copy_decn(&ACC_COPY, &AccDecn);
|
||||||
//store copy of x
|
//store copy of x
|
||||||
copy_decn(&x_copy, &BDecn);
|
copy_decn(&X_COPY, &BDecn);
|
||||||
//get initial exponent of estimate for 1/x
|
//get initial exponent of estimate for 1/x
|
||||||
initial_exp = get_exponent(&BDecn);
|
initial_exp = get_exponent(&BDecn);
|
||||||
#ifdef DEBUG_DIV
|
#ifdef DEBUG_DIV
|
||||||
@ -777,28 +780,28 @@ void div_decn(void){
|
|||||||
#ifdef DEBUG_DIV
|
#ifdef DEBUG_DIV
|
||||||
printf(" -> %d\n", initial_exp);
|
printf(" -> %d\n", initial_exp);
|
||||||
#endif
|
#endif
|
||||||
set_exponent(&curr_recip, initial_exp, (BDecn.exponent < 0)); //set exponent, copy sign
|
set_exponent(&CURR_RECIP, initial_exp, (BDecn.exponent < 0)); //set exponent, copy sign
|
||||||
//get initial estimate for 1/x
|
//get initial estimate for 1/x
|
||||||
if (BDecn.lsu[0] < 20){ //mantissa between 1 and 2
|
if (BDecn.lsu[0] < 20){ //mantissa between 1 and 2
|
||||||
curr_recip.lsu[0] = 50; //0.50 with implicit point and exponent
|
CURR_RECIP.lsu[0] = 50; //0.50 with implicit point and exponent
|
||||||
} else if (BDecn.lsu[0] < 33){
|
} else if (BDecn.lsu[0] < 33){
|
||||||
curr_recip.lsu[0] = 30;
|
CURR_RECIP.lsu[0] = 30;
|
||||||
} else if (BDecn.lsu[0] < 50){
|
} else if (BDecn.lsu[0] < 50){
|
||||||
curr_recip.lsu[0] = 20;
|
CURR_RECIP.lsu[0] = 20;
|
||||||
} else {
|
} else {
|
||||||
curr_recip.lsu[0] = 10; //0.1 with implicit point and exponent
|
CURR_RECIP.lsu[0] = 10; //0.1 with implicit point and exponent
|
||||||
}
|
}
|
||||||
for (i = 1; i < DEC80_NUM_LSU; i++){
|
for (i = 1; i < DEC80_NUM_LSU; i++){
|
||||||
curr_recip.lsu[i] = 0;
|
CURR_RECIP.lsu[i] = 0;
|
||||||
}
|
}
|
||||||
copy_decn(&AccDecn, &curr_recip);
|
copy_decn(&AccDecn, &CURR_RECIP);
|
||||||
//do newton raphson iterations
|
//do newton raphson iterations
|
||||||
for (i = 0; i < 6; i++){ //just fix number of iterations for now
|
for (i = 0; i < 6; i++){ //just fix number of iterations for now
|
||||||
#ifdef DEBUG_DIV
|
#ifdef DEBUG_DIV
|
||||||
decn_to_str_complete(&curr_recip);
|
decn_to_str_complete(&curr_recip);
|
||||||
printf("%2d: %s\n", i, Buf);
|
printf("%2d: %s\n", i, Buf);
|
||||||
#endif
|
#endif
|
||||||
copy_decn(&BDecn, &x_copy);
|
copy_decn(&BDecn, &X_COPY);
|
||||||
mult_decn();
|
mult_decn();
|
||||||
#ifdef DEBUG_DIV
|
#ifdef DEBUG_DIV
|
||||||
decn_to_str_complete(&AccDecn);
|
decn_to_str_complete(&AccDecn);
|
||||||
@ -811,7 +814,7 @@ void div_decn(void){
|
|||||||
decn_to_str_complete(&AccDecn);
|
decn_to_str_complete(&AccDecn);
|
||||||
printf(" %20s: %s\n", "(1-recip*x)", Buf);
|
printf(" %20s: %s\n", "(1-recip*x)", Buf);
|
||||||
#endif
|
#endif
|
||||||
copy_decn(&BDecn, &curr_recip);
|
copy_decn(&BDecn, &CURR_RECIP);
|
||||||
mult_decn();
|
mult_decn();
|
||||||
#ifdef DEBUG_DIV
|
#ifdef DEBUG_DIV
|
||||||
decn_to_str_complete(&AccDecn);
|
decn_to_str_complete(&AccDecn);
|
||||||
@ -819,11 +822,16 @@ void div_decn(void){
|
|||||||
#endif
|
#endif
|
||||||
add_decn();
|
add_decn();
|
||||||
//new_est(acc) = recip + (1 - recip*x)*recip, where tmp is current recip estimate
|
//new_est(acc) = recip + (1 - recip*x)*recip, where tmp is current recip estimate
|
||||||
copy_decn(&curr_recip, &AccDecn);
|
copy_decn(&CURR_RECIP, &AccDecn);
|
||||||
}
|
}
|
||||||
//acc now holds 1/x, multiply by original acc to complete division
|
//acc now holds 1/x, multiply by original acc to complete division
|
||||||
copy_decn(&BDecn, &acc_copy);
|
copy_decn(&BDecn, &ACC_COPY);
|
||||||
mult_decn();
|
mult_decn();
|
||||||
|
|
||||||
|
//try not to pollute namespace
|
||||||
|
#undef CURR_RECIP
|
||||||
|
#undef X_COPY
|
||||||
|
#undef ACC_COPY
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_str_error(){
|
static void set_str_error(){
|
||||||
|
Loading…
Reference in New Issue
Block a user