libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

convert_numeric.c (18939B)


      1 /* IEEE floating point support routines, for GDB, the GNU Debugger.
      2    Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006
      3    Free Software Foundation, Inc.
      4 
      5 This file is part of GDB.
      6 
      7 This program is free software; you can redistribute it and/or modify
      8 it under the terms of the GNU General Public License as published by
      9 the Free Software Foundation; either version 2 of the License, or
     10 (at your option) any later version.
     11 
     12 This program is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with this program; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
     20 
     21 /* This is needed to pick up the NAN macro on some systems.  */
     22 /* #define _GNU_SOURCE */
     23 
     24 #ifdef HAVE_CONFIG_H
     25 #include "config.h"
     26 #endif
     27 
     28 #include <math.h>
     29 
     30 #ifdef HAVE_STRING_H
     31 #include <string.h>
     32 #endif
     33 
     34 /* On some platforms, <float.h> provides DBL_QNAN.  */
     35 #ifdef STDC_HEADERS
     36 #include <float.h>
     37 #endif
     38 
     39 /*#include "ansidecl.h"*/
     40 /*#include "libiberty.h"*/
     41 #include "convert_numeric.h"
     42 
     43 #ifndef INFINITY
     44 #ifdef HUGE_VAL
     45 #define INFINITY HUGE_VAL
     46 #else
     47 #define INFINITY (1.0 / 0.0)
     48 #endif
     49 #endif
     50 
     51 #ifndef NAN
     52 #ifdef DBL_QNAN
     53 #define NAN DBL_QNAN
     54 #else
     55 #define NAN (0.0 / 0.0)
     56 #endif
     57 #endif
     58 
     59 static unsigned long get_field (const unsigned char *,
     60                                 enum EXTRACTOR_floatformat_byteorders,
     61                                 unsigned int,
     62                                 unsigned int,
     63                                 unsigned int);
     64 
     65 static int floatformat_always_valid (const struct EXTRACTOR_floatformat *fmt,
     66                                      const void *from);
     67 
     68 static int
     69 floatformat_always_valid (const struct
     70                           EXTRACTOR_floatformat *fmt /*ATTRIBUTE_UNUSED*/,
     71                           const void *from /*ATTRIBUTE_UNUSED*/)
     72 {
     73   return 1;
     74 }
     75 
     76 
     77 /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
     78    going to bother with trying to muck around with whether it is defined in
     79    a system header, what we do if not, etc.  */
     80 #define FLOATFORMAT_CHAR_BIT 8
     81 
     82 /* floatformats for IEEE single and double, big and little endian.  */
     83 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ieee_single_big = {
     84   floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
     85   floatformat_intbit_no,
     86   "floatformat_ieee_single_big",
     87   floatformat_always_valid
     88 };
     89 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ieee_single_little = {
     90   floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
     91   floatformat_intbit_no,
     92   "floatformat_ieee_single_little",
     93   floatformat_always_valid
     94 };
     95 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ieee_double_big = {
     96   floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
     97   floatformat_intbit_no,
     98   "floatformat_ieee_double_big",
     99   floatformat_always_valid
    100 };
    101 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ieee_double_little = {
    102   floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
    103   floatformat_intbit_no,
    104   "floatformat_ieee_double_little",
    105   floatformat_always_valid
    106 };
    107 
    108 /* floatformat for IEEE double, little endian byte order, with big endian word
    109    ordering, as on the ARM.  */
    110 
    111 const struct EXTRACTOR_floatformat
    112   EXTRACTOR_floatformat_ieee_double_littlebyte_bigword = {
    113   floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
    114   floatformat_intbit_no,
    115   "floatformat_ieee_double_littlebyte_bigword",
    116   floatformat_always_valid
    117 };
    118 
    119 /* floatformat for VAX.  Not quite IEEE, but close enough.  */
    120 
    121 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_vax_f = {
    122   floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
    123   floatformat_intbit_no,
    124   "floatformat_vax_f",
    125   floatformat_always_valid
    126 };
    127 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_vax_d = {
    128   floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
    129   floatformat_intbit_no,
    130   "floatformat_vax_d",
    131   floatformat_always_valid
    132 };
    133 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_vax_g = {
    134   floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
    135   floatformat_intbit_no,
    136   "floatformat_vax_g",
    137   floatformat_always_valid
    138 };
    139 
    140 static int floatformat_i387_ext_is_valid (const struct
    141                                           EXTRACTOR_floatformat *fmt,
    142                                           const void *from);
    143 
    144 static int
    145 floatformat_i387_ext_is_valid (const struct EXTRACTOR_floatformat *fmt, const
    146                                void *from)
    147 {
    148   /* In the i387 double-extended format, if the exponent is all ones,
    149      then the integer bit must be set.  If the exponent is neither 0
    150      nor ~0, the intbit must also be set.  Only if the exponent is
    151      zero can it be zero, and then it must be zero.  */
    152   unsigned long exponent, int_bit;
    153   const unsigned char *ufrom = (const unsigned char *) from;
    154 
    155   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    156                         fmt->exp_start, fmt->exp_len);
    157   int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    158                        fmt->man_start, 1);
    159 
    160   if ((exponent == 0) != (int_bit == 0))
    161     return 0;
    162   else
    163     return 1;
    164 }
    165 
    166 
    167 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_i387_ext = {
    168   floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
    169   floatformat_intbit_yes,
    170   "floatformat_i387_ext",
    171   floatformat_i387_ext_is_valid
    172 };
    173 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_m68881_ext = {
    174   /* Note that the bits from 16 to 31 are unused.  */
    175   floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
    176   floatformat_intbit_yes,
    177   "floatformat_m68881_ext",
    178   floatformat_always_valid
    179 };
    180 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_i960_ext = {
    181   /* Note that the bits from 0 to 15 are unused.  */
    182   floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
    183   floatformat_intbit_yes,
    184   "floatformat_i960_ext",
    185   floatformat_always_valid
    186 };
    187 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_m88110_ext = {
    188   floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
    189   floatformat_intbit_yes,
    190   "floatformat_m88110_ext",
    191   floatformat_always_valid
    192 };
    193 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_m88110_harris_ext = {
    194   /* Harris uses raw format 128 bytes long, but the number is just an ieee
    195      double, and the last 64 bits are wasted. */
    196   floatformat_big,128, 0, 1, 11,  0x3ff,  0x7ff, 12, 52,
    197   floatformat_intbit_no,
    198   "floatformat_m88110_ext_harris",
    199   floatformat_always_valid
    200 };
    201 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_arm_ext_big = {
    202   /* Bits 1 to 16 are unused.  */
    203   floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
    204   floatformat_intbit_yes,
    205   "floatformat_arm_ext_big",
    206   floatformat_always_valid
    207 };
    208 const struct EXTRACTOR_floatformat
    209   EXTRACTOR_floatformat_arm_ext_littlebyte_bigword = {
    210   /* Bits 1 to 16 are unused.  */
    211   floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
    212   floatformat_intbit_yes,
    213   "floatformat_arm_ext_littlebyte_bigword",
    214   floatformat_always_valid
    215 };
    216 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ia64_spill_big = {
    217   floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
    218   floatformat_intbit_yes,
    219   "floatformat_ia64_spill_big",
    220   floatformat_always_valid
    221 };
    222 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ia64_spill_little = {
    223   floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
    224   floatformat_intbit_yes,
    225   "floatformat_ia64_spill_little",
    226   floatformat_always_valid
    227 };
    228 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ia64_quad_big = {
    229   floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
    230   floatformat_intbit_no,
    231   "floatformat_ia64_quad_big",
    232   floatformat_always_valid
    233 };
    234 const struct EXTRACTOR_floatformat EXTRACTOR_floatformat_ia64_quad_little = {
    235   floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
    236   floatformat_intbit_no,
    237   "floatformat_ia64_quad_little",
    238   floatformat_always_valid
    239 };
    240 
    241 
    242 #ifndef min
    243 #define min(a, b) ((a) < (b) ? (a) : (b))
    244 #endif
    245 
    246 /* Extract a field which starts at START and is LEN bits long.  DATA and
    247    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
    248 static unsigned long
    249 get_field (const unsigned char *data, enum EXTRACTOR_floatformat_byteorders
    250            order,
    251            unsigned int total_len, unsigned int start, unsigned int len)
    252 {
    253   unsigned long result = 0;
    254   unsigned int cur_byte;
    255   int lo_bit, hi_bit, cur_bitshift = 0;
    256   int nextbyte = (order == floatformat_little) ? 1 : -1;
    257 
    258   /* Start is in big-endian bit order!  Fix that first.  */
    259   start = total_len - (start + len);
    260 
    261   /* Start at the least significant part of the field.  */
    262   if (order == floatformat_little)
    263     cur_byte = start / FLOATFORMAT_CHAR_BIT;
    264   else
    265     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
    266 
    267   lo_bit = start % FLOATFORMAT_CHAR_BIT;
    268   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
    269 
    270   do
    271   {
    272     unsigned int shifted = *(data + cur_byte) >> lo_bit;
    273     unsigned int bits = hi_bit - lo_bit;
    274     unsigned int mask = (1 << bits) - 1;
    275     result |= (shifted & mask) << cur_bitshift;
    276     len -= bits;
    277     cur_bitshift += bits;
    278     cur_byte += nextbyte;
    279     lo_bit = 0;
    280     hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
    281   }
    282   while (len != 0);
    283 
    284   return result;
    285 }
    286 
    287 
    288 /* Convert from FMT to a double.
    289    FROM is the address of the extended float.
    290    Store the double in *TO.  */
    291 
    292 void
    293 EXTRACTOR_common_floatformat_to_double (const struct EXTRACTOR_floatformat *fmt,
    294                                         const void *from, double *to)
    295 {
    296   const unsigned char *ufrom = (const unsigned char *) from;
    297   double dto;
    298   long exponent;
    299   unsigned long mant;
    300   unsigned int mant_bits, mant_off;
    301   int mant_bits_left;
    302   int special_exponent;   /* It's a NaN, denorm or zero */
    303 
    304   exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    305                         fmt->exp_start, fmt->exp_len);
    306 
    307   /* If the exponent indicates a NaN, we don't have information to
    308      decide what to do.  So we handle it like IEEE, except that we
    309      don't try to preserve the type of NaN.  FIXME.  */
    310   if ((unsigned long) exponent == fmt->exp_nan)
    311   {
    312     int nan;
    313 
    314     mant_off = fmt->man_start;
    315     mant_bits_left = fmt->man_len;
    316     nan = 0;
    317     while (mant_bits_left > 0)
    318     {
    319       mant_bits = min (mant_bits_left, 32);
    320 
    321       if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
    322                      mant_off, mant_bits) != 0)
    323       {
    324         /* This is a NaN.  */
    325         nan = 1;
    326         break;
    327       }
    328 
    329       mant_off += mant_bits;
    330       mant_bits_left -= mant_bits;
    331     }
    332 
    333     /* On certain systems (such as GNU/Linux), the use of the
    334  INFINITY macro below may generate a warning that can not be
    335  silenced due to a bug in GCC (PR preprocessor/11931).  The
    336  preprocessor fails to recognise the __extension__ keyword in
    337  conjunction with the GNU/C99 extension for hexadecimal
    338  floating point constants and will issue a warning when
    339  compiling with -pedantic.  */if (nan)
    340       dto = NAN;
    341     else
    342       dto = INFINITY;
    343 
    344     if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
    345       dto = -dto;
    346 
    347     *to = dto;
    348 
    349     return;
    350   }
    351 
    352   mant_bits_left = fmt->man_len;
    353   mant_off = fmt->man_start;
    354   dto = 0.0;
    355 
    356   special_exponent = (exponent == 0) || ((unsigned long) exponent ==
    357                                          fmt->exp_nan);
    358 
    359   /* Don't bias zero's, denorms or NaNs.  */
    360   if (! special_exponent)
    361     exponent -= fmt->exp_bias;
    362 
    363   /* Build the result algebraically.  Might go infinite, underflow, etc;
    364      who cares. */
    365 
    366   /* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
    367      increment the exponent by one to account for the integer bit.  */
    368 
    369   if (! special_exponent)
    370   {
    371     if (fmt->intbit == floatformat_intbit_no)
    372       dto = ldexp (1.0, exponent);
    373     else
    374       exponent++;
    375   }
    376 
    377   while (mant_bits_left > 0)
    378   {
    379     mant_bits = min (mant_bits_left, 32);
    380 
    381     mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
    382                       mant_off, mant_bits);
    383 
    384     /* Handle denormalized numbers.  FIXME: What should we do for
    385  non-IEEE formats?  */
    386     if (special_exponent && (exponent == 0) && (mant != 0) )
    387       dto += ldexp ((double) mant,
    388                     (-fmt->exp_bias
    389                      - mant_bits
    390                      - (mant_off - fmt->man_start)
    391                      + 1));
    392     else
    393       dto += ldexp ((double) mant, exponent - mant_bits);
    394     if (exponent != 0)
    395       exponent -= mant_bits;
    396     mant_off += mant_bits;
    397     mant_bits_left -= mant_bits;
    398   }
    399 
    400   /* Negate it if negative.  */
    401   if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
    402     dto = -dto;
    403   *to = dto;
    404 }
    405 
    406 
    407 static void put_field (unsigned char *, enum EXTRACTOR_floatformat_byteorders,
    408                        unsigned int,
    409                        unsigned int,
    410                        unsigned int,
    411                        unsigned long);
    412 
    413 /* Set a field which starts at START and is LEN bits long.  DATA and
    414    TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
    415 static void
    416 put_field (unsigned char *data, enum EXTRACTOR_floatformat_byteorders order,
    417            unsigned int total_len, unsigned int start, unsigned int len,
    418            unsigned long stuff_to_put)
    419 {
    420   unsigned int cur_byte;
    421   int lo_bit, hi_bit;
    422   int nextbyte = (order == floatformat_little) ? 1 : -1;
    423 
    424   /* Start is in big-endian bit order!  Fix that first.  */
    425   start = total_len - (start + len);
    426 
    427   /* Start at the least significant part of the field.  */
    428   if (order == floatformat_little)
    429     cur_byte = start / FLOATFORMAT_CHAR_BIT;
    430   else
    431     cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
    432 
    433   lo_bit = start % FLOATFORMAT_CHAR_BIT;
    434   hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
    435 
    436   do
    437   {
    438     unsigned char *byte_ptr = data + cur_byte;
    439     unsigned int bits = hi_bit - lo_bit;
    440     unsigned int mask = ((1 << bits) - 1) << lo_bit;
    441     *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
    442     stuff_to_put >>= bits;
    443     len -= bits;
    444     cur_byte += nextbyte;
    445     lo_bit = 0;
    446     hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
    447   }
    448   while (len != 0);
    449 }
    450 
    451 
    452 /* The converse: convert the double *FROM to an extended float
    453    and store where TO points.  Neither FROM nor TO have any alignment
    454    restrictions.  */
    455 
    456 void
    457 EXTRACTOR_common_floatformat_from_double (const struct
    458                                           EXTRACTOR_floatformat *fmt,
    459                                           const double *from, void *to)
    460 {
    461   double dfrom;
    462   int exponent;
    463   double mant;
    464   unsigned int mant_bits, mant_off;
    465   int mant_bits_left;
    466   unsigned char *uto = (unsigned char *) to;
    467 
    468   dfrom = *from;
    469   memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
    470 
    471   /* If negative, set the sign bit.  */
    472   if (dfrom < 0)
    473   {
    474     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
    475     dfrom = -dfrom;
    476   }
    477 
    478   if (dfrom == 0)
    479   {
    480     /* 0.0.  */
    481     return;
    482   }
    483 
    484   if (dfrom != dfrom)
    485   {
    486     /* NaN.  */
    487     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    488                fmt->exp_len, fmt->exp_nan);
    489     /* Be sure it's not infinity, but NaN value is irrelevant.  */
    490     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
    491                32, 1);
    492     return;
    493   }
    494 
    495   if (dfrom + dfrom == dfrom)
    496   {
    497     /* This can only happen for an infinite value (or zero, which we
    498  already handled above).  */
    499     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    500                fmt->exp_len, fmt->exp_nan);
    501     return;
    502   }
    503 
    504   mant = frexp (dfrom, &exponent);
    505   if (exponent + fmt->exp_bias - 1 > 0)
    506     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    507                fmt->exp_len, exponent + fmt->exp_bias - 1);
    508   else
    509   {
    510     /* Handle a denormalized number.  FIXME: What should we do for
    511  non-IEEE formats?  */
    512     put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
    513                fmt->exp_len, 0);
    514     mant = ldexp (mant, exponent + fmt->exp_bias - 1);
    515   }
    516 
    517   mant_bits_left = fmt->man_len;
    518   mant_off = fmt->man_start;
    519   while (mant_bits_left > 0)
    520   {
    521     unsigned long mant_long;
    522     mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
    523 
    524     mant *= 4294967296.0;
    525     mant_long = (unsigned long) mant;
    526     mant -= mant_long;
    527 
    528     /* If the integer bit is implicit, and we are not creating a
    529  denormalized number, then we need to discard it.  */
    530     if (( (unsigned int) mant_bits_left == fmt->man_len)
    531         && (fmt->intbit == floatformat_intbit_no)
    532         && (exponent + fmt->exp_bias - 1 > 0) )
    533     {
    534       mant_long &= 0x7fffffff;
    535       mant_bits -= 1;
    536     }
    537     else if (mant_bits < 32)
    538     {
    539       /* The bits we want are in the most significant MANT_BITS bits of
    540          mant_long.  Move them to the least significant.  */
    541       mant_long >>= 32 - mant_bits;
    542     }
    543 
    544     put_field (uto, fmt->byteorder, fmt->totalsize,
    545                mant_off, mant_bits, mant_long);
    546     mant_off += mant_bits;
    547     mant_bits_left -= mant_bits;
    548   }
    549 }
    550 
    551 
    552 /* Return non-zero iff the data at FROM is a valid number in format FMT.  */
    553 
    554 int
    555 EXTRACTOR_common_floatformat_is_valid (const struct EXTRACTOR_floatformat *fmt,
    556                                        const void *from)
    557 {
    558   return fmt->is_valid (fmt, from);
    559 }
    560 
    561 
    562 #ifdef IEEE_DEBUG
    563 
    564 #include <stdio.h>
    565 
    566 /* This is to be run on a host which uses IEEE floating point.  */
    567 
    568 void
    569 ieee_test (double n)
    570 {
    571   double result;
    572 
    573   floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
    574   if (((n != result) && (! isnan (n) || ! isnan (result)))
    575       || ((n < 0) && (result >= 0))
    576       || ((n >= 0) && (result < 0)))
    577     printf ("Differ(to): %.20g -> %.20g\n", n, result);
    578 
    579   floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
    580   if (((n != result) && (! isnan (n) || ! isnan (result)))
    581       || ((n < 0) && (result >= 0))
    582       || ((n >= 0) && (result < 0)))
    583     printf ("Differ(from): %.20g -> %.20g\n", n, result);
    584 
    585 #if 0
    586   {
    587     char exten[16];
    588 
    589     floatformat_from_double (&floatformat_m68881_ext, &n, exten);
    590     floatformat_to_double (&floatformat_m68881_ext, exten, &result);
    591     if (n != result)
    592       printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
    593   }
    594 #endif
    595 
    596 #if IEEE_DEBUG > 1
    597   /* This is to be run on a host which uses 68881 format.  */
    598   {
    599     long double ex = *(long double *) exten;
    600     if (ex != n)
    601       printf ("Differ(from vs. extended): %.20g\n", n);
    602   }
    603 #endif
    604 }
    605 
    606 
    607 int
    608 main (void)
    609 {
    610   ieee_test (0.0);
    611   ieee_test (0.5);
    612   ieee_test (256.0);
    613   ieee_test (0.12345);
    614   ieee_test (234235.78907234);
    615   ieee_test (-512.0);
    616   ieee_test (-0.004321);
    617   ieee_test (1.2E-70);
    618   ieee_test (1.2E-316);
    619   ieee_test (4.9406564584124654E-324);
    620   ieee_test (-4.9406564584124654E-324);
    621   ieee_test (-0.0);
    622   ieee_test (-INFINITY);
    623   ieee_test (-NAN);
    624   ieee_test (INFINITY);
    625   ieee_test (NAN);
    626   return 0;
    627 }
    628 
    629 
    630 #endif