/**************************************************************************** FILE: UTILITY.C, 6/29/00, 20:58, TVJM Revision History: -Saturday 8-July-2000, 18:24, TVJM: Moved decimal point restoration from function do_command in file UART.C to function dec2fp herein, added zero exit to same. -Friday 7-July-2000, 22:34, TVJM: Reformatted for printout. -Friday 7-July-2000, 20:50, TVJM: Enabled function dec2fp for testing. -Friday 7-July-2000, 12:01, TVJM: Removed base2_exponent & formatted for printout. -Friday 7-July-2000, 00:01, TVJM: Added while loop for function convert_to_ascii. -Thursday 6-July-2000, 01:40, TVJM: Corrected roundup bug. -Thursday 6-July-2000, 01:11, TVJM: Trimmed symbolic defines to file ARCHIVE.CCC. -Wednesday 5-July-2000, 16:12, TVJM: Disabled dec2fp and dec2bin for testing due to ldr21k memory malloc error. -Sunday 2-July-2000, 17:59, TVJM: Added FRAC_DIGITS & functions dec2fp & dec2bin. -Friday 30-June-2000, 23:05, TVJM: Disabled rounding to avoid malloc error. -Friday 30-June-2000, 23:02, TVJM: Added rounding in convert_to_ascii. -Friday 30-June-2000, 21:11, TVJM: Added dummy function dec2fp for testing. -Friday 30-June-2000, 20:26, TVJM: Formatted for printout. -Friday 30-June-2000, 19:47, TVJM: Corrected B2_EXP_LIMIT from 15 to 20. -Friday 30-June-2000, 19:22, TVJM: Updated code after base 10 exponent error. -Friday 30-June-2000, 15:11, TVJM: Added function get_exponent. ****************************************************************************/ /**************************************************************************** The next section defines symbolic codes used by the Floating-point to decimal ASCII and decimal ASCII to Floating-point conversion routines FP2DEC and DEC2FP, respectively. The maximum floating-point value is + or - 3.40E+38 = (-1)**s + (2**(+104)) * ((2**24)-1) The minimum floating-point value is + or - 5.88E-39 = (-1)**s + (2**(-127)) * (1) Since there is no sign digit on the mantissa, all mantissas are positive and are displayed with no sign character, implying a positive sign; Zero is displayed as 0.00000E+00. The maximum displayable floating point value is 3.40E+38 The maximum modifiable floating point value is 9.99E+32 The minimum displayable floating point value is 5.88E-39 The minimum modifiable floating point value is 0.01E-32 ****************************************************************************/ #define CHPEXP 2 /* # of ASCII digits in working exponent */ #define CHPMAN 6 /* # of ASCII digits in working mantissa */ #define BASE10_BASE 10 /* base 10 base */ #define FRAC_DIGITS 5 /* # of digits to the right of the decimal point */ #define B2_EXP_LIMIT 20 /* Base 2 unbiased exponent limit */ #define B2_EXP_MAX 255 /* Base 2 biased exponent maximum value */ #define B10_EXP_MAX 32 /* Base 10 unbiased exponent maximum magnitude */ /**************************************************************************** The next section defines symbols used to access the various fields of the floating-point numbers. These numbers are in the format: X.XXXXXEsYY ****************************************************************************/ #define FPN_MAN_MS_DIGIT 0 /* offset to mantissa MS digit */ #define FPN_MAN_PERIOD 1 /* offset to mantissa decimal point period */ #define FPN_MAN_LS_DIGIT 6 /* offset to mantissa LS digit */ #define FPN_EXP_CHAR 7 /* offset to exponent character */ #define FPN_EXP_SIGN 8 /* offset to exponent sign character */ #define FPN_EXP_MS_DIGIT 9 /* offset to exponent MS digit */ #define FPN_EXP_LS_DIGIT 10 /* offset to exponent LS digit */ static char buffer[20]; static char zero[]="0.00000E+00"; static const float fp_ten = 10.0; static int base10_exponent; extern int get_exponent (float); /* returns base-2 unbiased exponent */ extern int float_to_fix (float); /* returns float rounded to nearest integer */ /**************************************************************************** Begin of function "convert_to_ascii": ****************************************************************************/ char * convert_to_ascii (float input) { int temp, index, iexp; temp = float_to_fix(input); /* convert input to rounded integer */ index = FPN_MAN_LS_DIGIT; /* point to mantissa LS digit */ while (index >= 0) { buffer[index--] = (temp % BASE10_BASE) + '0'; /* one digit at a time */ temp /= BASE10_BASE; } /* if the first digit is non-zero, we must round the first 6 digits from the 7th digit and use the resulting rounded 6 digits */ /* if the first digit is zero, we must use the least-significant six digits starting with the second digit; */ if (buffer[FPN_MAN_MS_DIGIT] == '0') /* 1st digit zero? */ { buffer[FPN_MAN_MS_DIGIT] = buffer[FPN_MAN_PERIOD]; /* get new MS digit */ buffer[FPN_MAN_PERIOD] = '.'; /* load new period */ iexp = base10_exponent + FRAC_DIGITS; /* account for fixed-point display */ } else { /* round MS 6 digits from 7th digit: */ if (buffer[FPN_MAN_LS_DIGIT] >= '5') /* round-up from 7th digit? */ { /* round-up from 7th digit */ index = FPN_MAN_LS_DIGIT-1; /* point to mantissa new LS digit */ buffer[index]++; /* carry into new LS digit */ while (index > 0) { if (buffer[index] > '9') /* carry into next MS digit? */ { buffer[index] = '0'; /* for carry into next digit */ buffer[index-1]++; /* carry into next digit */ } index--; /* to next most-significant digit */ } } /* round-up from 7th digit */ /* at this point, use the first (most-significant) 6 digits: */ index = FPN_MAN_LS_DIGIT; /* point to mantissa LS digit */ while (index > FPN_MAN_PERIOD) { buffer[index] = buffer[index-1]; /* shift digit to the right */ index--; /* to next digit on the left */ } buffer[FPN_MAN_PERIOD] = '.'; /* load new period */ iexp = base10_exponent + FRAC_DIGITS+1; /* account for fixed-point display */ } /* round MS 6 digits from 7th digit: */ buffer[FPN_EXP_CHAR] = 'E'; /* exponent indicator character */ if (iexp < 0) { buffer[FPN_EXP_SIGN] = '-'; /* negative exponent */ iexp = -iexp; /* absolute value of exponent */ } else buffer[FPN_EXP_SIGN] = '+'; /* positive exponent */ buffer[FPN_EXP_LS_DIGIT] = (iexp % BASE10_BASE) + '0'; /* LS exponent digit */ iexp /= BASE10_BASE; /* decimate exponent */ buffer[FPN_EXP_MS_DIGIT] = (iexp % BASE10_BASE) + '0'; /* MS exponent digit */ buffer[FPN_EXP_LS_DIGIT+1] = 0; /* null-terminate ASCII string */ return(buffer); }; /* End of function "convert_to_ascii" */ /**************************************************************************** Begin of function "fp2dec": ****************************************************************************/ char * fp2dec (float input) { base10_exponent = 0; /* initialize working base-10 exponent value */ if (input == 0.0) { return (zero); } if (get_exponent(input) == B2_EXP_LIMIT) return(convert_to_ascii(input)); else while (get_exponent(input) < B2_EXP_LIMIT) { input *= fp_ten; /* multiply input */ base10_exponent--; /* decrement output */ } while (get_exponent(input) > B2_EXP_LIMIT) { input /= fp_ten; /* decimate input */ base10_exponent++; /* increment output */ } return(convert_to_ascii(input)); }; /* End of function "fp2dec" */ /**************************************************************************** Begin of function "dec2bin": ****************************************************************************/ #if 1 /* conditionally compile function "dec2bin" next: */ static int dec2bin (char inbuf[], int num_convert) { char ctemp; int result, power; num_convert--; /* index of LS char to convert */ result = 0; power = 1; while (num_convert >= 0) { ctemp = inbuf[num_convert--]; /* working digit */ if (isdigit(ctemp)) { result += ((ctemp-'0') * power); power *= 10; } else return(0); /* error: non-numeric digit detected */ } return (result); }; /* End of function "dec2bin" */ #endif /**************************************************************************** Begin of function "dec2fp": ****************************************************************************/ #if 1 /* conditionally compile function "dec2fp" next: */ float dec2fp (char inbuf[]) { int iexp, count; float mantissa; inbuf[FPN_MAN_PERIOD] = inbuf[FPN_MAN_MS_DIGIT]; /* form integer for convert */ mantissa /* start with fixed-point mantissa */ = (float) /* convert binary fixed-point to floating-point mantissa */ (dec2bin(&inbuf[FPN_MAN_PERIOD], /* begin of mantissa digits */ CHPMAN)); /* convert mantissa ASCII digits to binary */ inbuf[FPN_MAN_PERIOD] = '.'; /* Restore ASCII decimal point period character */ if (mantissa == 0.0) /* zeroed mantissa results in zero returned */ return (0.0); /* zeroed mantissa results in zero returned */ iexp = dec2bin(&inbuf[FPN_EXP_MS_DIGIT], /* begin of exponent digits */ CHPEXP); /* convert exponent ASCII digits to binary */ if (iexp >= B10_EXP_MAX) return (0.0); /* error: exponent over- or under-flow */ if (inbuf[FPN_EXP_SIGN] == '-') iexp = -iexp; /* handle negative sign, otherwise assume positive sign */ iexp -= FRAC_DIGITS; /* account for fixed decimal point location */ while (iexp < 0) { mantissa /= fp_ten; /* decimate working float result */ iexp++; /* account for one decade */ } while (iexp > 0) { mantissa *= fp_ten; /* multiply working float result */ iexp--; /* account for one decade */ } return (mantissa); }; /* End of function "dec2fp" */ #else float dec2fp (char inbuf[]) { return(65.0E+3); /* dummy return value */ }; /* End of dummy function "dec2fp" */ #endif /**************************************************************************** End of file "UTILILTY.C"... ****************************************************************************/