Back to index

cell-binutils  2.17cvs20070401
Classes | Enumerations | Functions
floatformat.h File Reference
#include "ansidecl.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  floatformat

Enumerations

enum  floatformat_byteorders { floatformat_little, floatformat_big, floatformat_littlebyte_bigword, floatformat_vax }
enum  floatformat_intbit { floatformat_intbit_yes, floatformat_intbit_no }

Functions

void floatformat_to_double (const struct floatformat *, const void *, double *)
void floatformat_from_double (const struct floatformat *, const double *, void *)
int floatformat_is_valid (const struct floatformat *fmt, const void *from)

Class Documentation

struct floatformat

Definition at line 56 of file floatformat.h.


Enumeration Type Documentation

Enumerator:
floatformat_little 
floatformat_big 
floatformat_littlebyte_bigword 
floatformat_vax 

Definition at line 34 of file floatformat.h.

                            {
  /* Standard little endian byte order.
     EX: 1.2345678e10 => 00 00 80 c5 e0 fe 06 42 */
  floatformat_little,

  /* Standard big endian byte order.
     EX: 1.2345678e10 => 42 06 fe e0 c5 80 00 00 */
  floatformat_big,

  /* Little endian byte order but big endian word order.
     EX: 1.2345678e10 => e0 fe 06 42 00 00 80 c5 */
  floatformat_littlebyte_bigword,

  /* VAX byte order.  Little endian byte order with 16-bit words.  The
     following example is an illustration of the byte order only; VAX
     doesn't have a fully IEEE compliant floating-point format.
     EX: 1.2345678e10 => 80 c5 00 00 06 42 e0 fe */
  floatformat_vax
};
Enumerator:
floatformat_intbit_yes 
floatformat_intbit_no 

Definition at line 54 of file floatformat.h.


Function Documentation

void floatformat_from_double ( const struct floatformat ,
const double ,
void *   
)

Definition at line 464 of file floatformat.c.

{
  double dfrom;
  int exponent;
  double mant;
  unsigned int mant_bits, mant_off;
  int mant_bits_left;
  unsigned char *uto = (unsigned char *) to;

  dfrom = *from;
  memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);

  /* If negative, set the sign bit.  */
  if (dfrom < 0)
    {
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
      dfrom = -dfrom;
    }

  if (dfrom == 0)
    {
      /* 0.0.  */
      return;
    }

  if (dfrom != dfrom)
    {
      /* NaN.  */
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
               fmt->exp_len, fmt->exp_nan);
      /* Be sure it's not infinity, but NaN value is irrelevant.  */
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
               32, 1);
      return;
    }

  if (dfrom + dfrom == dfrom)
    {
      /* This can only happen for an infinite value (or zero, which we
        already handled above).  */
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
               fmt->exp_len, fmt->exp_nan);
      return;
    }

  mant = frexp (dfrom, &exponent);
  if (exponent + fmt->exp_bias - 1 > 0)
    put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
              fmt->exp_len, exponent + fmt->exp_bias - 1);
  else
    {
      /* Handle a denormalized number.  FIXME: What should we do for
        non-IEEE formats?  */
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
               fmt->exp_len, 0);
      mant = ldexp (mant, exponent + fmt->exp_bias - 1);
    }

  mant_bits_left = fmt->man_len;
  mant_off = fmt->man_start;
  while (mant_bits_left > 0)
    {
      unsigned long mant_long;
      mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;

      mant *= 4294967296.0;
      mant_long = (unsigned long)mant;
      mant -= mant_long;

      /* If the integer bit is implicit, and we are not creating a
        denormalized number, then we need to discard it.  */
      if ((unsigned int) mant_bits_left == fmt->man_len
         && fmt->intbit == floatformat_intbit_no
         && exponent + fmt->exp_bias - 1 > 0)
       {
         mant_long &= 0x7fffffff;
         mant_bits -= 1;
       }
      else if (mant_bits < 32)
       {
         /* The bits we want are in the most significant MANT_BITS bits of
            mant_long.  Move them to the least significant.  */
         mant_long >>= 32 - mant_bits;
       }

      put_field (uto, fmt->byteorder, fmt->totalsize,
               mant_off, mant_bits, mant_long);
      mant_off += mant_bits;
      mant_bits_left -= mant_bits;
    }
}

Here is the call graph for this function:

int floatformat_is_valid ( const struct floatformat fmt,
const void *  from 
)

Definition at line 560 of file floatformat.c.

{
  return fmt->is_valid (fmt, from);
}
void floatformat_to_double ( const struct floatformat ,
const void *  ,
double  
)

Definition at line 302 of file floatformat.c.

{
  const unsigned char *ufrom = (const unsigned char *) from;
  double dto;
  long exponent;
  unsigned long mant;
  unsigned int mant_bits, mant_off;
  int mant_bits_left;
  int special_exponent;            /* It's a NaN, denorm or zero */

  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
                     fmt->exp_start, fmt->exp_len);

  /* If the exponent indicates a NaN, we don't have information to
     decide what to do.  So we handle it like IEEE, except that we
     don't try to preserve the type of NaN.  FIXME.  */
  if ((unsigned long) exponent == fmt->exp_nan)
    {
      int nan;

      mant_off = fmt->man_start;
      mant_bits_left = fmt->man_len;
      nan = 0;
      while (mant_bits_left > 0)
       {
         mant_bits = min (mant_bits_left, 32);

         if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
                      mant_off, mant_bits) != 0)
           {
             /* This is a NaN.  */
             nan = 1;
             break;
           }

         mant_off += mant_bits;
         mant_bits_left -= mant_bits;
       }

      /* On certain systems (such as GNU/Linux), the use of the
        INFINITY macro below may generate a warning that can not be
        silenced due to a bug in GCC (PR preprocessor/11931).  The
        preprocessor fails to recognise the __extension__ keyword in
        conjunction with the GNU/C99 extension for hexadecimal
        floating point constants and will issue a warning when
        compiling with -pedantic.  */
      if (nan)
       dto = NAN;
      else
       dto = INFINITY;

      if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
       dto = -dto;

      *to = dto;

      return;
    }

  mant_bits_left = fmt->man_len;
  mant_off = fmt->man_start;
  dto = 0.0;

  special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;

  /* Don't bias zero's, denorms or NaNs.  */
  if (!special_exponent)
    exponent -= fmt->exp_bias;

  /* Build the result algebraically.  Might go infinite, underflow, etc;
     who cares. */

  /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
     increment the exponent by one to account for the integer bit.  */

  if (!special_exponent)
    {
      if (fmt->intbit == floatformat_intbit_no)
       dto = ldexp (1.0, exponent);
      else
       exponent++;
    }

  while (mant_bits_left > 0)
    {
      mant_bits = min (mant_bits_left, 32);

      mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
                      mant_off, mant_bits);

      /* Handle denormalized numbers.  FIXME: What should we do for
        non-IEEE formats?  */
      if (special_exponent && exponent == 0 && mant != 0)
       dto += ldexp ((double)mant,
                    (- fmt->exp_bias
                     - mant_bits
                     - (mant_off - fmt->man_start)
                     + 1));
      else
       dto += ldexp ((double)mant, exponent - mant_bits);
      if (exponent != 0)
       exponent -= mant_bits;
      mant_off += mant_bits;
      mant_bits_left -= mant_bits;
    }

  /* Negate it if negative.  */
  if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
    dto = -dto;
  *to = dto;
}

Here is the call graph for this function:

Here is the caller graph for this function: