allow number of exponent bits to be adjustable
This commit is contained in:
parent
4b87ad27c8
commit
58a162fe4d
@ -25,7 +25,7 @@ static void pop(){
|
|||||||
StackPtr++; //adjust pointer
|
StackPtr++; //adjust pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_decn(const char* signif_str, int8_t exponent, uint8_t no_lift){
|
void push_decn(const char* signif_str, exp_t exponent, uint8_t no_lift){
|
||||||
if (!no_lift){
|
if (!no_lift){
|
||||||
StackPtr--;
|
StackPtr--;
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ void clear_x(void){
|
|||||||
set_dec80_zero(&stack(STACK_X));
|
set_dec80_zero(&stack(STACK_X));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_x(const char* signif_str, int8_t exponent){
|
void set_x(const char* signif_str, exp_t exponent){
|
||||||
build_dec80(&stack(STACK_X), signif_str, exponent);
|
build_dec80(&stack(STACK_X), signif_str, exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,10 +16,10 @@ extern "C" {
|
|||||||
|
|
||||||
void process_cmd(char cmd);
|
void process_cmd(char cmd);
|
||||||
|
|
||||||
void push_decn(const char* signif_str, int8_t exponent, uint8_t no_lift);
|
void push_decn(const char* signif_str, exp_t exponent, uint8_t no_lift);
|
||||||
|
|
||||||
void clear_x(void);
|
void clear_x(void);
|
||||||
void set_x(const char* signif_str, int8_t exponent);
|
void set_x(const char* signif_str, exp_t exponent);
|
||||||
__xdata dec80* get_x(void);
|
__xdata dec80* get_x(void);
|
||||||
__xdata dec80* get_y(void);
|
__xdata dec80* get_y(void);
|
||||||
|
|
||||||
|
@ -53,21 +53,37 @@ void copy_decn(dec80* dest, const dec80* src){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t get_exponent(const dec80* x){
|
exp_t get_exponent(const dec80* x){
|
||||||
int8_t exponent = x->exponent;
|
exp_t exponent = x->exponent;
|
||||||
|
#ifdef EXP16
|
||||||
|
if (exponent & 0x4000){ //negative
|
||||||
|
return exponent | 0x8000;
|
||||||
|
} else { //positive
|
||||||
|
return exponent & 0x7fff;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (exponent & 0x40){ //negative
|
if (exponent & 0x40){ //negative
|
||||||
return exponent | 0x80;
|
return exponent | 0x80;
|
||||||
} else { //positive
|
} else { //positive
|
||||||
return exponent & 0x7f;
|
return exponent & 0x7f;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_exponent(dec80* acc, int8_t exponent, uint8_t num_is_neg){
|
static void set_exponent(dec80* acc, exp_t exponent, uint8_t num_is_neg){
|
||||||
|
#ifdef EXP16
|
||||||
|
if (num_is_neg){
|
||||||
|
exponent |= 0x8000;
|
||||||
|
} else {
|
||||||
|
exponent &= 0x7fff;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (num_is_neg){
|
if (num_is_neg){
|
||||||
exponent |= 0x80;
|
exponent |= 0x80;
|
||||||
} else {
|
} else {
|
||||||
exponent &= 0x7f;
|
exponent &= 0x7f;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
acc->exponent = exponent;
|
acc->exponent = exponent;
|
||||||
}
|
}
|
||||||
@ -103,7 +119,7 @@ static void shift_left(dec80* x){
|
|||||||
static void remove_leading_zeros(dec80* x){
|
static void remove_leading_zeros(dec80* x){
|
||||||
uint8_t digit100;
|
uint8_t digit100;
|
||||||
uint8_t is_negative = (x->exponent < 0);
|
uint8_t is_negative = (x->exponent < 0);
|
||||||
int8_t exponent = get_exponent(x);
|
exp_t exponent = get_exponent(x);
|
||||||
|
|
||||||
//find first non-zero digit100
|
//find first non-zero digit100
|
||||||
for (digit100 = 0; digit100 < DEC80_NUM_LSU; digit100++){
|
for (digit100 = 0; digit100 < DEC80_NUM_LSU; digit100++){
|
||||||
@ -133,7 +149,7 @@ static void remove_leading_zeros(dec80* x){
|
|||||||
set_exponent(x, exponent, is_negative);
|
set_exponent(x, exponent, is_negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
void build_dec80(dec80* dest, const char* signif_str, int8_t exponent){
|
void build_dec80(dec80* dest, const char* signif_str, exp_t exponent){
|
||||||
enum {
|
enum {
|
||||||
SIGN_ZERO,
|
SIGN_ZERO,
|
||||||
SIGN_ZERO_SEEN_POINT,
|
SIGN_ZERO_SEEN_POINT,
|
||||||
@ -341,7 +357,11 @@ static uint8_t decn_is_zero(const dec80* x){
|
|||||||
|
|
||||||
uint8_t decn_is_nan(const dec80* x){
|
uint8_t decn_is_nan(const dec80* x){
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
if (x->exponent & 0x7f != DEC80_NAN_EXP){
|
#ifdef EXP16
|
||||||
|
if ((x->exponent & 0x7fff) != DEC80_NAN_EXP){
|
||||||
|
#else
|
||||||
|
if ((x->exponent & 0x7f) != DEC80_NAN_EXP){
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (i = 0; i < DEC80_NUM_LSU; i++){
|
for (i = 0; i < DEC80_NUM_LSU; i++){
|
||||||
@ -366,13 +386,17 @@ void set_dec80_NaN(dec80* dest){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void negate_decn(dec80* x){
|
void negate_decn(dec80* x){
|
||||||
static const int8_t xor_val = -(0x7f) - 1;
|
#ifdef EXP16
|
||||||
|
static const exp_t xor_val = -(0x7fff) - 1;
|
||||||
|
#else
|
||||||
|
static const exp_t xor_val = -(0x7f) - 1;
|
||||||
|
#endif
|
||||||
(x->exponent) ^= xor_val;
|
(x->exponent) ^= xor_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t compare_magn(const dec80* a, const dec80* b){ //a<b: -1, a==b: 0, a>b: 1
|
int8_t compare_magn(const dec80* a, const dec80* b){ //a<b: -1, a==b: 0, a>b: 1
|
||||||
uint8_t a_i, b_i;
|
uint8_t a_i, b_i;
|
||||||
int8_t a_exp=0, b_exp=0;
|
exp_t a_exp=0, b_exp=0;
|
||||||
int8_t a_signif_b = 0; //a<b: -1, a==b: 0, a>b: 1
|
int8_t a_signif_b = 0; //a<b: -1, a==b: 0, a>b: 1
|
||||||
static __xdata dec80 a_tmp, b_tmp;
|
static __xdata dec80 a_tmp, b_tmp;
|
||||||
//copy
|
//copy
|
||||||
@ -460,8 +484,8 @@ int8_t compare_decn(const dec80* a, const dec80* b){ //a<b: -1, a==b: 0, a>b: 1
|
|||||||
//acc and the number from which exponent was taken MUST be stripped of leading 0s first
|
//acc and the number from which exponent was taken MUST be stripped of leading 0s first
|
||||||
//rescales acc up to exponent (increase exponent of acc, while shifting right)
|
//rescales acc up to exponent (increase exponent of acc, while shifting right)
|
||||||
//the actual value of acc->exponent remains unchanged
|
//the actual value of acc->exponent remains unchanged
|
||||||
static void _incr_exp(dec80* acc, int8_t exponent){
|
static void _incr_exp(dec80* acc, exp_t exponent){
|
||||||
int8_t curr_exp = get_exponent(acc);
|
exp_t curr_exp = get_exponent(acc);
|
||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
uint8_t is_neg = (acc->exponent < 0);
|
uint8_t is_neg = (acc->exponent < 0);
|
||||||
printf(" (is_neg,curr_exp,exponent)=(%d,%d,%d)\n",
|
printf(" (is_neg,curr_exp,exponent)=(%d,%d,%d)\n",
|
||||||
@ -612,7 +636,7 @@ void add_decn(dec80* acc, const dec80* x){
|
|||||||
}
|
}
|
||||||
//may need to rescale number
|
//may need to rescale number
|
||||||
if (carry > 0){
|
if (carry > 0){
|
||||||
int8_t curr_exp = get_exponent(acc);
|
exp_t curr_exp = get_exponent(acc);
|
||||||
rel = (acc->exponent < 0); //is_neg?
|
rel = (acc->exponent < 0); //is_neg?
|
||||||
#ifdef DEBUG_ADD
|
#ifdef DEBUG_ADD
|
||||||
printf(" carry out: %d", carry);
|
printf(" carry out: %d", carry);
|
||||||
@ -639,7 +663,7 @@ void mult_decn(dec80* acc, const dec80* x){
|
|||||||
int8_t i, j;
|
int8_t i, j;
|
||||||
uint8_t carry = 0;
|
uint8_t carry = 0;
|
||||||
uint8_t is_neg;
|
uint8_t is_neg;
|
||||||
int8_t new_exponent;
|
exp_t new_exponent;
|
||||||
//initialize values
|
//initialize values
|
||||||
copy_decn(&tmp, x);
|
copy_decn(&tmp, x);
|
||||||
set_dec80_zero(&acc_tmp);
|
set_dec80_zero(&acc_tmp);
|
||||||
@ -647,7 +671,11 @@ void mult_decn(dec80* acc, const dec80* x){
|
|||||||
remove_leading_zeros(acc);
|
remove_leading_zeros(acc);
|
||||||
remove_leading_zeros(&tmp);
|
remove_leading_zeros(&tmp);
|
||||||
//store new sign
|
//store new sign
|
||||||
|
#ifdef EXP16
|
||||||
|
if ((acc->exponent & 0x8000) ^ (tmp.exponent & 0x8000)){ //signs differ
|
||||||
|
#else
|
||||||
if ((acc->exponent & 0x80) ^ (tmp.exponent & 0x80)){ //signs differ
|
if ((acc->exponent & 0x80) ^ (tmp.exponent & 0x80)){ //signs differ
|
||||||
|
#endif
|
||||||
is_neg = 1;
|
is_neg = 1;
|
||||||
} else {
|
} else {
|
||||||
is_neg = 0;
|
is_neg = 0;
|
||||||
@ -726,7 +754,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;
|
||||||
int8_t initial_exp;
|
exp_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)){
|
||||||
@ -800,7 +828,7 @@ int8_t decn_to_str(char* buf, 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;
|
||||||
int8_t exponent = 0;
|
exp_t exponent = 0;
|
||||||
uint8_t trailing_zeros = 0;
|
uint8_t trailing_zeros = 0;
|
||||||
uint8_t use_sci = 0;
|
uint8_t use_sci = 0;
|
||||||
static __xdata dec80 tmp;
|
static __xdata dec80 tmp;
|
||||||
@ -923,6 +951,7 @@ int8_t decn_to_str(char* buf, const dec80* x){
|
|||||||
#endif
|
#endif
|
||||||
//print exponent
|
//print exponent
|
||||||
if (use_sci){
|
if (use_sci){
|
||||||
|
//check for overflow
|
||||||
if (exponent > DEC80_MAX_EXP || exponent < DEC80_MIN_EXP){
|
if (exponent > DEC80_MAX_EXP || exponent < DEC80_MIN_EXP){
|
||||||
set_str_error(buf);
|
set_str_error(buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -16,15 +16,27 @@ extern "C" {
|
|||||||
|
|
||||||
#define DEC80_NUM_LSU 9
|
#define DEC80_NUM_LSU 9
|
||||||
|
|
||||||
|
//#define EXP16
|
||||||
|
|
||||||
|
#ifdef EXP16
|
||||||
|
typedef int16_t exp_t;
|
||||||
|
//allow full range, but reserve -16384 for special numbers
|
||||||
|
#define DEC80_MIN_EXP (-16383)
|
||||||
|
#define DEC80_MAX_EXP 16383
|
||||||
|
#define DEC80_NAN_EXP (-16383 - 1)
|
||||||
|
#else
|
||||||
|
typedef int8_t exp_t;
|
||||||
//allow full range, but reserve -128 for special numbers
|
//allow full range, but reserve -128 for special numbers
|
||||||
#define DEC80_MIN_EXP (-63)
|
#define DEC80_MIN_EXP (-63)
|
||||||
#define DEC80_MAX_EXP 63
|
#define DEC80_MAX_EXP 63
|
||||||
#define DEC80_NAN_EXP (-63 - 1) //-64
|
#define DEC80_NAN_EXP (-63 - 1) //-64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//decimal80 unpacked into 80 bits
|
//decimal80 unpacked into 80 bits
|
||||||
// for computation
|
// for computation
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int8_t exponent; //MSBit is sign of dec80 number, bottom 15 bits are 2's Compl exponent
|
exp_t exponent; //MSBit is sign of dec80 number, bottom 15 or 7 bits are 2's Compl exponent
|
||||||
uint8_t lsu[DEC80_NUM_LSU]; //lsu[0] holds most-significant 2 digits (base 100)
|
uint8_t lsu[DEC80_NUM_LSU]; //lsu[0] holds most-significant 2 digits (base 100)
|
||||||
//implicit decimal point between (lsu[0]/10) and (lsu[0]%10)
|
//implicit decimal point between (lsu[0]/10) and (lsu[0]%10)
|
||||||
} dec80;
|
} dec80;
|
||||||
@ -36,13 +48,13 @@ static const dec80 DECN_1 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//remove sign bit, and return 15 bit exponent sign-extended to 16 bits
|
//remove sign bit, and return 15 bit exponent sign-extended to 16 bits
|
||||||
int8_t get_exponent(const dec80* x);
|
exp_t get_exponent(const dec80* x);
|
||||||
|
|
||||||
//void dec64to80(dec80* dest, const dec64* src);
|
//void dec64to80(dec80* dest, const dec64* src);
|
||||||
|
|
||||||
void copy_decn(dec80* dest, const dec80* src);
|
void copy_decn(dec80* dest, const dec80* src);
|
||||||
|
|
||||||
void build_dec80(dec80* dest, const char* signif_str, int8_t exponent);
|
void build_dec80(dec80* dest, const char* signif_str, exp_t exponent);
|
||||||
|
|
||||||
void set_dec80_zero(dec80* dest);
|
void set_dec80_zero(dec80* dest);
|
||||||
void set_dec80_NaN(dec80* dest);
|
void set_dec80_NaN(dec80* dest);
|
||||||
|
Loading…
Reference in New Issue
Block a user