Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wsieee754.c File Reference

#include "wsint.h"

Include dependency graph for wsieee754.c:

Include dependency graph

Go to the source code of this file.

Defines

#define WS_IEEE754_SINGLE_EXP_SIZE   8
#define WS_IEEE754_SINGLE_MANT_SIZE   23
#define WS_IEEE754_SINGLE_BIAS   127
#define WS_IEEE754_SINGLE_EXP_MIN   -126
#define WS_IEEE754_SINGLE_EXP_MAX   127
#define WS_IEEE754_POSITIVE_INFINITY   0x7f800000

Functions

WsIeee754Result ws_ieee754_encode_single (double value, unsigned char *buf)
WsIeee754Result ws_ieee754_decode_single (unsigned char *buf, double *value_return)
WsUInt32 ws_ieee754_single_get_sign (unsigned char *buf)
WsUInt32 ws_ieee754_single_get_exp (unsigned char *buf)
WsUInt32 ws_ieee754_single_get_mant (unsigned char *buf)

Variables

unsigned char ws_ieee754_nan [4] = {0xff, 0xff, 0xff, 0xff}
unsigned char ws_ieee754_positive_inf [4] = {0x7f, 0x80, 0x00, 0x00}
unsigned char ws_ieee754_negative_inf [4] = {0xff, 0x80, 0x00, 0x00}


Define Documentation

#define WS_IEEE754_POSITIVE_INFINITY   0x7f800000
 

Definition at line 82 of file wsieee754.c.

#define WS_IEEE754_SINGLE_BIAS   127
 

Definition at line 77 of file wsieee754.c.

#define WS_IEEE754_SINGLE_EXP_MAX   127
 

Definition at line 80 of file wsieee754.c.

#define WS_IEEE754_SINGLE_EXP_MIN   -126
 

Definition at line 79 of file wsieee754.c.

#define WS_IEEE754_SINGLE_EXP_SIZE   8
 

Definition at line 75 of file wsieee754.c.

#define WS_IEEE754_SINGLE_MANT_SIZE   23
 

Definition at line 76 of file wsieee754.c.


Function Documentation

WsIeee754Result ws_ieee754_decode_single unsigned char *  buf,
double *  value_return
 

Definition at line 199 of file wsieee754.c.

References WS_IEEE754_NEGATIVE_INF, ws_ieee754_single_get_exp(), ws_ieee754_single_get_mant(), ws_ieee754_single_get_sign(), WsIeee754Result, WsInt32, and WsUInt32.

Referenced by ws_bc_decode().

00201 {
00202     WsUInt32 sign = ws_ieee754_single_get_sign(buf);
00203     WsInt32 exp = (WsInt32) ws_ieee754_single_get_exp(buf);
00204     WsUInt32 mant = ws_ieee754_single_get_mant(buf);
00205     double value;
00206     int i;
00207 
00208     /* Check the special cases where exponent is all 1. */
00209     if (exp == 0xff) {
00210         if (mant == 0)
00211             return sign ? WS_IEEE754_NEGATIVE_INF : WS_IEEE754_POSITIVE_INF;
00212 
00213         return WS_IEEE754_NAN;
00214     }
00215 
00216     /* Expand the mantissa. */
00217     value = 0.0;
00218     for (i = 0; i < WS_IEEE754_SINGLE_MANT_SIZE; i++) {
00219         if (mant & 0x1)
00220             value += 1.0;
00221 
00222         value /= 2.0;
00223         mant >>= 1;
00224     }
00225 
00226     /* Check the `unnormalized' vs. `normal form'. */
00227     if (exp == 0)
00228         /* This is a `unnormalized' number. */
00229         exp = -126;
00230     else {
00231         /* This is a standard case. */
00232         value += 1.0;
00233         exp -= WS_IEEE754_SINGLE_BIAS;
00234     }
00235 
00236     /* Handle exponents. */
00237     while (exp > 0) {
00238         value *= 2;
00239         exp--;
00240     }
00241     while (exp < 0) {
00242         value /= 2;
00243         exp++;
00244     }
00245 
00246     /* Finally notify sign. */
00247     if (sign)
00248         value = -value;
00249 
00250     *value_return = value;
00251 
00252     return WS_IEEE754_OK;
00253 }

Here is the call graph for this function:

WsIeee754Result ws_ieee754_encode_single double  value,
unsigned char *  buf
 

Definition at line 94 of file wsieee754.c.

References gw_assert, result, WsIeee754Result, WsInt32, and WsUInt32.

Referenced by read_float_from_exp(), and ws_bc_encode().

00095 {
00096     int sign = 0;
00097     WsInt32 exp = 0;
00098     WsUInt32 mant = 0;
00099     int i;
00100     WsIeee754Result result = WS_IEEE754_OK;
00101 
00102     /* The sign bit. */
00103     if (value < 0.0) {
00104         sign = 1;
00105         value = -value;
00106     }
00107 
00108     /* Scale the value so that: 1 <= mantissa < 2. */
00109     if (value > 1.0) {
00110         /* The exponent is positive. */
00111         while (value >= 2.0 && exp <= WS_IEEE754_SINGLE_EXP_MAX) {
00112             value /= 2.0;
00113             exp++;
00114         }
00115         if (exp > WS_IEEE754_SINGLE_EXP_MAX) {
00116             /* Overflow => infinity. */
00117             exp = 0xff;
00118 
00119             if (sign)
00120                 result = WS_IEEE754_NEGATIVE_INF;
00121             else
00122                 result = WS_IEEE754_POSITIVE_INF;
00123 
00124             goto done;
00125         }
00126 
00127         /* The 1 is implicit. */
00128         value -= 1;
00129     } else {
00130         /* The exponent is negative. */
00131         while (value < 1.0 && exp > WS_IEEE754_SINGLE_EXP_MIN) {
00132             value *= 2.0;
00133             exp--;
00134         }
00135         if (value >= 1.0) {
00136             /* We managed to get the number to the normal form.  Let's
00137                       remote the implicit 1 from the value. */
00138             gw_assert(value >= 1.0);
00139             value -= 1.0;
00140         } else {
00141             /* The number is still smaller than 1.  We just try to
00142                       present the remaining stuff in our mantissa.  If that
00143                       fails, we fall back to 0.0.  We mark exp to -127 (after
00144                       bias it is 0) to mark this unnormalized form. */
00145             exp--;
00146             gw_assert(exp == -127);
00147         }
00148     }
00149 
00150     for (i = 0; i < WS_IEEE754_SINGLE_MANT_SIZE; i++) {
00151         value *= 2.0;
00152         mant <<= 1;
00153 
00154         if (value >= 1.0) {
00155             mant |= 1;
00156             value -= 1.0;
00157         }
00158     }
00159 
00160     /* Handle rounding.  Intel seems to round 0.5 down so to be
00161        compatible, our check is > instead of >=. */
00162     if (value * 2.0 > 1.0) {
00163         mant++;
00164         if (mant == 0x800000) {
00165             /* This we the really worst case.  The rounding rounds the
00166                mant up to 2.0.  So we must increase the exponent by one.
00167                This may then result an overflow in the exponent which
00168                converts our number to infinity. */
00169             mant = 0;
00170             exp++;
00171 
00172             if (exp > WS_IEEE754_SINGLE_EXP_MAX) {
00173                 /* Overflow => infinity. */
00174                 exp = 0xff;
00175                 goto done;
00176             }
00177         }
00178     }
00179 
00180     /* Handle biased exponent. */
00181     exp += WS_IEEE754_SINGLE_BIAS;
00182 
00183 done:
00184 
00185     /* Encode the value to the buffer. */
00186 
00187     mant |= exp << 23;
00188     mant |= sign << 31;
00189 
00190     buf[3] = (mant & 0x000000ff);
00191     buf[2] = (mant & 0x0000ff00) >> 8;
00192     buf[1] = (mant & 0x00ff0000) >> 16;
00193     buf[0] = (mant & 0xff000000) >> 24;
00194 
00195     return result;
00196 }

WsUInt32 ws_ieee754_single_get_exp unsigned char *  buf  ) 
 

Definition at line 262 of file wsieee754.c.

References WsUInt32.

Referenced by ws_ieee754_decode_single().

00263 {
00264     WsUInt32 value = buf[0] & 0x7f;
00265 
00266     value <<= 1;
00267     value |= (buf[1] & 0x80) >> 7;
00268 
00269     return value;
00270 }

WsUInt32 ws_ieee754_single_get_mant unsigned char *  buf  ) 
 

Definition at line 273 of file wsieee754.c.

References WsUInt32.

Referenced by ws_ieee754_decode_single().

00274 {
00275     WsUInt32 value = buf[1] & 0x7f;
00276 
00277     value <<= 8;
00278     value |= buf[2];
00279 
00280     value <<= 8;
00281     value |= buf[3];
00282 
00283     return value;
00284 }

WsUInt32 ws_ieee754_single_get_sign unsigned char *  buf  ) 
 

Definition at line 256 of file wsieee754.c.

References WsUInt32.

Referenced by ws_ieee754_decode_single().

00257 {
00258     return (buf[0] & 0x80) >> 7;
00259 }


Variable Documentation

unsigned char ws_ieee754_nan[4] = {0xff, 0xff, 0xff, 0xff}
 

Definition at line 86 of file wsieee754.c.

unsigned char ws_ieee754_negative_inf[4] = {0xff, 0x80, 0x00, 0x00}
 

Definition at line 90 of file wsieee754.c.

unsigned char ws_ieee754_positive_inf[4] = {0x7f, 0x80, 0x00, 0x00}
 

Definition at line 88 of file wsieee754.c.

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.