From: Fabien P. <fab...@re...> - 2002-05-16 16:39:02
|
Hi for all. Is there any news for a float support (* / + and -) in gbdk? I've tried to compile some basic float calc and print (from newlib), but it doesn't compile! Fabien If anynody could help, it works with other compilers (have tried with gcc). Just need these ones to make trigonometric calc with * and +. #include <stdio.h> /* the following deal with IEEE single-precision numbers */ #define EXCESS 126 #define SIGNBIT ((unsigned long)0x80000000) #define HIDDEN (unsigned long)(1 << 23) #define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1) #define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF) #define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN) #define PACK(s,e,m) ((s) | ((e) << 23) | (m)) #define DEFAULT_FLOAT_PRECISION 6 union float_long { float f; long l; }; char output_ptr[256] ; int charsOutputted = 0; static void output_char( char c ) { output_ptr[charsOutputted++] = c; } static void output_float (float f, unsigned char reqWidth, signed char reqDecimals, unsigned char left, unsigned char zero, unsigned char sign, unsigned char space) { unsigned char minWidth, i; char negative=0; long integerPart; float decimalPart; char fpBuffer[128]; char fpBI=0, fpBD; volatile union float_long IntegerPart; volatile union float_long tmp; // save the sign if (f<0) { negative=1; f=-f; } // split the float integerPart = f; decimalPart = f - integerPart; // fill the buffer with the integerPart (in reversed order!) while (integerPart) { fpBuffer[fpBI++]='0' + integerPart%10; integerPart /= 10; } if (!fpBI) { // we need at least a 0 fpBuffer[fpBI++]='0'; } // display some decimals as default if (reqDecimals==-1) reqDecimals=DEFAULT_FLOAT_PRECISION; // fill buffer with the decimalPart (in normal order) fpBD=fpBI; if (i=reqDecimals ) { // that's an assignment do { decimalPart *= 10.0; // truncate the float integerPart=decimalPart; fpBuffer[fpBD++]='0' + integerPart; decimalPart-=integerPart; } while (--i); } minWidth=fpBI; // we need at least these minWidth+=reqDecimals?reqDecimals+1:0; // maybe these if (negative || sign || space) minWidth++; // and maybe even this :) if (!left && reqWidth>i) { if (zero) { if (negative) output_char('-'); else if (sign) output_char('+'); else if (space) output_char(' '); while (reqWidth-->minWidth) output_char ('0'); } else { while (reqWidth-->minWidth) output_char (' '); if (negative) output_char('-'); else if (sign) output_char('+'); else if (space) output_char (' '); } } else { if (negative) output_char('-'); else if (sign) output_char('+'); else if (space) output_char(' '); } // output the integer part i=fpBI-1; do { output_char (fpBuffer[i]); } while (i--); // ouput the decimal part if (reqDecimals) { output_char ('.'); i=fpBI; while (reqDecimals--) output_char (fpBuffer[i++]); } if (left && reqWidth>minWidth) { while (reqWidth-->minWidth) output_char(' '); } } /* multiply two floats */ float fmul (float a1, float a2) { volatile union float_long fl1, fl2; volatile unsigned long result; volatile int exp; char sign; fl1.f = a1; fl2.f = a2; if (!fl1.l || !fl2.l) return (0); // compute sign and exponent sign = SIGN (fl1.l) ^ SIGN (fl2.l); exp = EXP (fl1.l) - EXCESS; exp += EXP (fl2.l); fl1.l = MANT (fl1.l); fl2.l = MANT (fl2.l); // the multiply is done as one 16x16 multiply and two 16x8 multiples result = (fl1.l >> 8) * (fl2.l >> 8); result += ((fl1.l & (unsigned long) 0xFF) * (fl2.l >> 8)) >> 8; result += ((fl2.l & (unsigned long) 0xFF) * (fl1.l >> 8)) >> 8; if (result & (unsigned long)0x80000000) { // round result += 0x80; result >>= 8; } else { // round result += 0x40; result >>= 7; exp--; } result &= ~HIDDEN; // pack up and go home fl1.l = PACK (sign ? ((unsigned long) 0x80000000) : 0 , (unsigned long)exp, result); return (fl1.f); } float Sin(float a, float b) { return fmul(a,b); } main() { float a = 018.01; float b = 0.002; float c; c = Sin(a,b); output_float (c, 0, -1, 0, 0, 0, 0); printf("%s", output_ptr); } |