home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Sound / LAME / Source / ieeefloat.c < prev    next >
C/C++ Source or Header  |  1999-04-30  |  28KB  |  972 lines

  1. /* Copyright (C) 1988-1991 Apple Computer, Inc.
  2.  * All Rights Reserved.
  3.  *
  4.  * Warranty Information
  5.  * Even though Apple has reviewed this software, Apple makes no warranty
  6.  * or representation, either express or implied, with respect to this
  7.  * software, its quality, accuracy, merchantability, or fitness for a 
  8.  * particular purpose.  As a result, this software is provided "as is,"
  9.  * and you, its user, are assuming the entire risk as to its quality
  10.  * and accuracy.
  11.  *
  12.  * This code may be used and freely distributed as long as it includes
  13.  * this copyright notice and the warranty information.
  14.  *
  15.  * Machine-independent I/O routines for IEEE floating-point numbers.
  16.  *
  17.  * NaN's and infinities are converted to HUGE_VAL or HUGE, which
  18.  * happens to be infinity on IEEE machines.  Unfortunately, it is
  19.  * impossible to preserve NaN's in a machine-independent way.
  20.  * Infinities are, however, preserved on IEEE machines.
  21.  *
  22.  * These routines have been tested on the following machines:
  23.  *    Apple Macintosh, MPW 3.1 C compiler
  24.  *    Apple Macintosh, THINK C compiler
  25.  *    Silicon Graphics IRIS, MIPS compiler
  26.  *    Cray X/MP and Y/MP
  27.  *    Digital Equipment VAX
  28.  *    Sequent Balance (Multiprocesor 386)
  29.  *    NeXT
  30.  *
  31.  *
  32.  * Implemented by Malcolm Slaney and Ken Turkowski.
  33.  *
  34.  * Malcolm Slaney contributions during 1988-1990 include big- and little-
  35.  * endian file I/O, conversion to and from Motorola's extended 80-bit
  36.  * floating-point format, and conversions to and from IEEE single-
  37.  * precision floating-point format.
  38.  *
  39.  * In 1991, Ken Turkowski implemented the conversions to and from
  40.  * IEEE double-precision format, added more precision to the extended
  41.  * conversions, and accommodated conversions involving +/- infinity,
  42.  * NaN's, and denormalized numbers.
  43.  *
  44.  * $Id: ieeefloat.c,v 1.1 1993/06/11 17:45:46 malcolm Exp $
  45.  *
  46.  * $Log: ieeefloat.c,v $
  47.  * Revision 1.1  1993/06/11  17:45:46  malcolm
  48.  * Initial revision
  49.  *
  50.  */
  51.  
  52. #include    <stdio.h>
  53. #include    <math.h>
  54. #include    "ieeefloat.h"
  55.  
  56.  
  57. /****************************************************************
  58.  * The following two routines make up for deficiencies in many
  59.  * compilers to convert properly between unsigned integers and
  60.  * floating-point.  Some compilers which have this bug are the
  61.  * THINK_C compiler for the Macintosh and the C compiler for the
  62.  * Silicon Graphics MIPS-based Iris.
  63.  ****************************************************************/
  64.  
  65. #ifdef applec    /* The Apple C compiler works */
  66. # define FloatToUnsigned(f)    ((unsigned long)(f))
  67. # define UnsignedToFloat(u)    ((defdouble)(u))
  68. #else /* applec */
  69. # define FloatToUnsigned(f)    ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1))
  70. # define UnsignedToFloat(u)    (((defdouble)((long)((u) - 2147483647L - 1))) + 2147483648.0)
  71. #endif /* applec */
  72.  
  73.  
  74. /****************************************************************
  75.  * Single precision IEEE floating-point conversion routines
  76.  ****************************************************************/
  77.  
  78. #define SEXP_MAX        255
  79. #define SEXP_OFFSET        127
  80. #define SEXP_SIZE        8
  81. #define SEXP_POSITION    (32-SEXP_SIZE-1)
  82.  
  83.  
  84. defdouble
  85. ConvertFromIeeeSingle(bytes)
  86. char* bytes;
  87. {
  88.     defdouble    f;
  89.     long    mantissa, expon;
  90.     long    bits;
  91.  
  92.     bits =    ((unsigned long)(bytes[0] & 0xFF) << 24)
  93.         |    ((unsigned long)(bytes[1] & 0xFF) << 16)
  94.         |    ((unsigned long)(bytes[2] & 0xFF) << 8)
  95.         |     (unsigned long)(bytes[3] & 0xFF);        /* Assemble bytes into a long */
  96.  
  97.     if ((bits & 0x7FFFFFFF) == 0) {
  98.         f = 0;
  99.     }
  100.  
  101.     else {
  102.         expon = (bits & 0x7F800000) >> SEXP_POSITION;
  103.         if (expon == SEXP_MAX) {        /* Infinity or NaN */
  104.             f = HUGE_VAL;        /* Map NaN's to infinity */
  105.         }
  106.         else {
  107.             if (expon == 0) {    /* Denormalized number */
  108.                 mantissa = (bits & 0x7fffff);
  109.                 f = ldexp((defdouble)mantissa, expon - SEXP_OFFSET - SEXP_POSITION + 1);
  110.             }
  111.             else {                /* Normalized number */
  112.                 mantissa = (bits & 0x7fffff) + 0x800000;    /* Insert hidden bit */
  113.                 f = ldexp((defdouble)mantissa, expon - SEXP_OFFSET - SEXP_POSITION);
  114.             }
  115.         }
  116.     }
  117.  
  118.     if (bits & 0x80000000)
  119.         return -f;
  120.     else
  121.         return f;
  122. }
  123.  
  124.  
  125. /****************************************************************/
  126.  
  127.  
  128. void
  129. ConvertToIeeeSingle(num, bytes)
  130. defdouble num;
  131. char* bytes;
  132. {
  133.     long    sign;
  134.     register long bits;
  135.  
  136.     if (num < 0) {    /* Can't distinguish a negative zero */
  137.         sign = 0x80000000;
  138.         num *= -1;
  139.     } else {
  140.         sign = 0;
  141.     }
  142.  
  143.     if (num == 0) {
  144.         bits = 0;
  145.     }
  146.  
  147.     else {
  148.         defdouble fMant;
  149.         int expon;
  150.  
  151.         fMant = frexp(num, &expon);
  152.  
  153.         if ((expon > (SEXP_MAX-SEXP_OFFSET+1)) || !(fMant < 1)) {
  154.             /* NaN's and infinities fail second test */
  155.             bits = sign | 0x7F800000;        /* +/- infinity */
  156.         }
  157.  
  158.         else {
  159.             long mantissa;
  160.  
  161.             if (expon < -(SEXP_OFFSET-2)) {    /* Smaller than normalized */
  162.                 int shift = (SEXP_POSITION+1) + (SEXP_OFFSET-2) + expon;
  163.                 if (shift < 0) {    /* Way too small: flush to zero */
  164.                     bits = sign;
  165.                 }
  166.                 else {            /* Nonzero denormalized number */
  167.                     mantissa = (long)(fMant * (1L << shift));
  168.                     bits = sign | mantissa;
  169.                 }
  170.             }
  171.  
  172.             else {                /* Normalized number */
  173.                 mantissa = (long)floor(fMant * (1L << (SEXP_POSITION+1)));
  174.                 mantissa -= (1L << SEXP_POSITION);            /* Hide MSB */
  175.                 bits = sign | ((long)((expon + SEXP_OFFSET - 1)) << SEXP_POSITION) | mantissa;
  176.             }
  177.         }
  178.     }
  179.  
  180.     bytes[0] = bits >> 24;    /* Copy to byte string */
  181.     bytes[1] = bits >> 16;
  182.     bytes[2] = bits >> 8;
  183.     bytes[3] = bits;
  184. }
  185.  
  186.  
  187. /****************************************************************
  188.  * Double precision IEEE floating-point conversion routines
  189.  ****************************************************************/
  190.  
  191. #define DEXP_MAX        2047
  192. #define DEXP_OFFSET        1023
  193. #define DEXP_SIZE        11
  194. #define DEXP_POSITION    (32-DEXP_SIZE-1)
  195.  
  196.  
  197. defdouble
  198. ConvertFromIeeeDouble(bytes)
  199. char* bytes;
  200. {
  201.     defdouble    f;
  202.     long    mantissa, expon;
  203.     unsigned long first, second;
  204.  
  205.     first = ((unsigned long)(bytes[0] & 0xFF) << 24)
  206.         |    ((unsigned long)(bytes[1] & 0xFF) << 16)
  207.         |    ((unsigned long)(bytes[2] & 0xFF) << 8)
  208.         |     (unsigned long)(bytes[3] & 0xFF);
  209.     second= ((unsigned long)(bytes[4] & 0xFF) << 24)
  210.         |    ((unsigned long)(bytes[5] & 0xFF) << 16)
  211.         |    ((unsigned long)(bytes[6] & 0xFF) << 8)
  212.         |     (unsigned long)(bytes[7] & 0xFF);
  213.     
  214.     if (first == 0 && second == 0) {
  215.         f = 0;
  216.     }
  217.  
  218.     else {
  219.         expon = (first & 0x7FF00000) >> DEXP_POSITION;
  220.         if (expon == DEXP_MAX) {        /* Infinity or NaN */
  221.             f = HUGE_VAL;        /* Map NaN's to infinity */
  222.         }
  223.         else {
  224.             if (expon == 0) {    /* Denormalized number */
  225.                 mantissa = (first & 0x000FFFFF);
  226.                 f = ldexp((defdouble)mantissa, expon - DEXP_OFFSET - DEXP_POSITION + 1);
  227.                 f += ldexp(UnsignedToFloat(second), expon - DEXP_OFFSET - DEXP_POSITION + 1 - 32);
  228.             }
  229.             else {                /* Normalized number */
  230.                 mantissa = (first & 0x000FFFFF) + 0x00100000;    /* Insert hidden bit */
  231.                 f = ldexp((defdouble)mantissa, expon - DEXP_OFFSET - DEXP_POSITION);
  232.                 f += ldexp(UnsignedToFloat(second), expon - DEXP_OFFSET - DEXP_POSITION - 32);
  233.             }
  234.         }
  235.     }
  236.  
  237.     if (first & 0x80000000)
  238.         return -f;
  239.     else
  240.         return f;
  241. }
  242.  
  243.  
  244. /****************************************************************/
  245.  
  246.  
  247. void
  248. ConvertToIeeeDouble(num, bytes)
  249. defdouble num;
  250. char *bytes;
  251. {
  252.     long    sign;
  253.     long    first, second;
  254.  
  255.     if (num < 0) {    /* Can't distinguish a negative zero */
  256.         sign = 0x80000000;
  257.         num *= -1;
  258.     } else {
  259.         sign = 0;
  260.     }
  261.  
  262.     if (num == 0) {
  263.         first = 0;
  264.         second = 0;
  265.     }
  266.  
  267.     else {
  268.         defdouble fMant, fsMant;
  269.         int expon;
  270.  
  271.         fMant = frexp(num, &expon);
  272.  
  273.         if ((expon > (DEXP_MAX-DEXP_OFFSET+1)) || !(fMant < 1)) {
  274.             /* NaN's and infinities fail second test */
  275.             first = sign | 0x7FF00000;        /* +/- infinity */
  276.             second = 0;
  277.         }
  278.  
  279.         else {
  280.             long mantissa;
  281.  
  282.             if (expon < -(DEXP_OFFSET-2)) {    /* Smaller than normalized */
  283.                 int shift = (DEXP_POSITION+1) + (DEXP_OFFSET-2) + expon;
  284.                 if (shift < 0) {    /* Too small for something in the MS word */
  285.                     first = sign;
  286.                     shift += 32;
  287.                     if (shift < 0) {    /* Way too small: flush to zero */
  288.                         second = 0;
  289.                     }
  290.                     else {            /* Pretty small demorn */
  291.                         second = FloatToUnsigned(floor(ldexp(fMant, shift)));
  292.                     }
  293.                 }
  294.                 else {            /* Nonzero denormalized number */
  295.                     fsMant = ldexp(fMant, shift);
  296.                     mantissa = (long)floor(fsMant);
  297.                     first = sign | mantissa;
  298.                     second = FloatToUnsigned(floor(ldexp(fsMant - mantissa, 32)));
  299.                 }
  300.             }
  301.  
  302.             else {                /* Normalized number */
  303.                 fsMant = ldexp(fMant, DEXP_POSITION+1);
  304.                 mantissa = (long)floor(fsMant);
  305.                 mantissa -= (1L << DEXP_POSITION);            /* Hide MSB */
  306.                 fsMant -= (1L << DEXP_POSITION);
  307.                 first = sign | ((long)((expon + DEXP_OFFSET - 1)) << DEXP_POSITION) | mantissa;
  308.                 second = FloatToUnsigned(floor(ldexp(fsMant - mantissa, 32)));
  309.             }
  310.         }
  311.     }
  312.     
  313.     bytes[0] = first >> 24;
  314.     bytes[1] = first >> 16;
  315.     bytes[2] = first >> 8;
  316.     bytes[3] = first;
  317.     bytes[4] = second >> 24;
  318.     bytes[5] = second >> 16;
  319.     bytes[6] = second >> 8;
  320.     bytes[7] = second;
  321. }
  322.  
  323.  
  324. /****************************************************************
  325.  * Extended precision IEEE floating-point conversion routines
  326.  ****************************************************************/
  327.  
  328. defdouble
  329. ConvertFromIeeeExtended(bytes)
  330. char* bytes;
  331. {
  332.     defdouble    f;
  333.     long    expon;
  334.     unsigned long hiMant, loMant;
  335.  
  336. #ifdef    TEST    
  337. printf("ConvertFromIEEEExtended(%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx\r",
  338.     (long)bytes[0], (long)bytes[1], (long)bytes[2], (long)bytes[3], 
  339.     (long)bytes[4], (long)bytes[5], (long)bytes[6], 
  340.     (long)bytes[7], (long)bytes[8], (long)bytes[9]);
  341. #endif
  342.     
  343.     expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
  344.     hiMant    =    ((unsigned long)(bytes[2] & 0xFF) << 24)
  345.             |    ((unsigned long)(bytes[3] & 0xFF) << 16)
  346.             |    ((unsigned long)(bytes[4] & 0xFF) << 8)
  347.             |    ((unsigned long)(bytes[5] & 0xFF));
  348.     loMant    =    ((unsigned long)(bytes[6] & 0xFF) << 24)
  349.             |    ((unsigned long)(bytes[7] & 0xFF) << 16)
  350.             |    ((unsigned long)(bytes[8] & 0xFF) << 8)
  351.             |    ((unsigned long)(bytes[9] & 0xFF));
  352.  
  353.     if (expon == 0 && hiMant == 0 && loMant == 0) {
  354.         f = 0;
  355.     }
  356.     else {
  357.         if (expon == 0x7FFF) {    /* Infinity or NaN */
  358.             f = HUGE_VAL;
  359.         }
  360.         else {
  361.             expon -= 16383;
  362.             f  = ldexp(UnsignedToFloat(hiMant), expon-=31);
  363.             f += ldexp(UnsignedToFloat(loMant), expon-=32);
  364.         }
  365.     }
  366.  
  367.     if (bytes[0] & 0x80)
  368.         return -f;
  369.     else
  370.         return f;
  371. }
  372.  
  373.  
  374. /****************************************************************/
  375.  
  376.  
  377. void
  378. ConvertToIeeeExtended(num, bytes)
  379. defdouble num;
  380. char *bytes;
  381. {
  382.     int    sign;
  383.     int expon;
  384.     defdouble fMant, fsMant;
  385.     unsigned long hiMant, loMant;
  386.  
  387.     if (num < 0) {
  388.         sign = 0x8000;
  389.         num *= -1;
  390.     } else {
  391.         sign = 0;
  392.     }
  393.  
  394.     if (num == 0) {
  395.         expon = 0; hiMant = 0; loMant = 0;
  396.     }
  397.     else {
  398.         fMant = frexp(num, &expon);
  399.         if ((expon > 16384) || !(fMant < 1)) {    /* Infinity or NaN */
  400.             expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */
  401.         }
  402.         else {    /* Finite */
  403.             expon += 16382;
  404.             if (expon < 0) {    /* denormalized */
  405.                 fMant = ldexp(fMant, expon);
  406.                 expon = 0;
  407.             }
  408.             expon |= sign;
  409.             fMant = ldexp(fMant, 32);          fsMant = floor(fMant); hiMant = FloatToUnsigned(fsMant);
  410.             fMant = ldexp(fMant - fsMant, 32); fsMant = floor(fMant); loMant = FloatToUnsigned(fsMant);
  411.         }
  412.     }
  413.     
  414.     bytes[0] = expon >> 8;
  415.     bytes[1] = expon;
  416.     bytes[2] = hiMant >> 24;
  417.     bytes[3] = hiMant >> 16;
  418.     bytes[4] = hiMant >> 8;
  419.     bytes[5] = hiMant;
  420.     bytes[6] = loMant >> 24;
  421.     bytes[7] = loMant >> 16;
  422.     bytes[8] = loMant >> 8;
  423.     bytes[9] = loMant;
  424. }
  425.  
  426. /****************************************************************
  427.  * Testing routines for the floating-point conversions.
  428.  ****************************************************************/
  429.  
  430. #ifdef METROWERKS
  431. #define IEEE
  432. #endif
  433. #ifdef applec
  434. # define IEEE
  435. #endif /* applec */
  436. #ifdef THINK_C
  437. # define IEEE
  438. #endif /* THINK_C */
  439. #ifdef sgi
  440. # define IEEE
  441. #endif /* sgi */
  442. #ifdef sequent
  443. # define IEEE
  444. # define LITTLE_ENDIAN
  445. #endif /* sequent */
  446. #ifdef sun
  447. # define IEEE
  448. #endif /* sun */
  449. #ifdef NeXT
  450. # define IEEE
  451. #endif /* NeXT */
  452.  
  453. #ifdef MAIN
  454.  
  455. union SParts {
  456.     Single s;
  457.     long i;
  458. };
  459. union DParts {
  460.     Double d;
  461.     long i[2];
  462. };
  463. union EParts {
  464.     defdouble e;
  465.     short i[6];
  466. };
  467.  
  468.  
  469. int
  470. GetHexValue(x)
  471. register int x;
  472. {
  473.     x &= 0x7F;
  474.     
  475.     if ('0' <= x && x <= '9')
  476.         x -= '0';
  477.     else if ('a' <= x && x <= 'f')
  478.         x = x - 'a' + 0xA;
  479.     else if ('A' <= x && x <= 'F')
  480.         x = x - 'A' + 0xA;
  481.     else
  482.         x = 0;
  483.     
  484.     return(x);
  485. }
  486.  
  487.  
  488. void
  489. Hex2Bytes(hex, bytes)
  490. register char *hex, *bytes;
  491. {
  492.     for ( ; *hex; hex += 2) {
  493.         *bytes++ = (GetHexValue(hex[0]) << 4) | GetHexValue(hex[1]);
  494.         if (hex[1] == 0)
  495.             break;    /* Guard against odd bytes */
  496.     }
  497. }
  498.  
  499.  
  500. int
  501. GetHexSymbol(x)
  502. register int x;
  503. {
  504.     x &= 0xF;
  505.     if (x <= 9)
  506.         x += '0';
  507.     else
  508.         x += 'A' - 0xA;
  509.     return(x);
  510. }
  511.  
  512.  
  513. void
  514. Bytes2Hex(bytes, hex, nBytes)
  515. register char *bytes, *hex;
  516. register int nBytes;
  517. {
  518.     for ( ; nBytes--; bytes++) {
  519.         *hex++ = GetHexSymbol(*bytes >> 4);
  520.         *hex++ = GetHexSymbol(*bytes);
  521.     }
  522.     *hex = 0;
  523. }
  524.  
  525.  
  526. void
  527. MaybeSwapBytes(bytes, nBytes)
  528. char* bytes;
  529. int nBytes;
  530. {
  531. #ifdef LITTLE_ENDIAN
  532.     register char *p, *q, t;
  533.     for (p = bytes, q = bytes+nBytes-1; p < q; p++, q--) {
  534.         t = *p;
  535.         *p = *q;
  536.         *q = t;
  537.     }
  538. #else
  539.     if (bytes, nBytes);        /* Just so it's used */
  540. #endif /* LITTLE_ENDIAN */
  541.     
  542. }
  543.  
  544.  
  545. float
  546. MachineIEEESingle(bytes)
  547. char* bytes;
  548. {
  549.     float t;
  550.     MaybeSwapBytes(bytes, 4);
  551.     t = *((float*)(bytes));
  552.     MaybeSwapBytes(bytes, 4);
  553.     return (t);
  554. }
  555.  
  556.  
  557. Double
  558. MachineIEEEDouble(bytes)
  559. char* bytes;
  560. {
  561.     Double t;
  562.     MaybeSwapBytes(bytes, 8);
  563.     t = *((Double*)(bytes));
  564.     MaybeSwapBytes(bytes, 8);
  565.     return (t);
  566. }
  567.  
  568.  
  569. void
  570. TestFromIeeeSingle(hex)
  571. char *hex;
  572. {
  573.     defdouble f;
  574.     union SParts p;
  575.     char bytes[4];
  576.  
  577.     Hex2Bytes(hex, bytes);
  578.     f = ConvertFromIeeeSingle(bytes);
  579.     p.s = f;
  580.  
  581. #ifdef IEEE
  582.     fprintf(stderr, "IEEE(%g) [%s] --> float(%g) [%08lX]\n",
  583.     MachineIEEESingle(bytes),
  584.     hex, f, p.i);
  585. #else /* IEEE */
  586.     fprintf(stderr, "IEEE[%s] --> float(%g) [%08lX]\n", hex, f, p.i);
  587. #endif /* IEEE */
  588. }
  589.  
  590.  
  591. void
  592. TestToIeeeSingle(f)
  593. defdouble f;
  594. {
  595.     union SParts p;
  596.     char bytes[4];
  597.     char hex[8+1];
  598.  
  599.     p.s = f;
  600.  
  601.     ConvertToIeeeSingle(f, bytes);
  602.     Bytes2Hex(bytes, hex, 4);
  603. #ifdef IEEE
  604.     fprintf(stderr, "float(%g) [%08lX] --> IEEE(%g) [%s]\n",
  605.         f, p.i,
  606.         MachineIEEESingle(bytes),
  607.         hex
  608.     );
  609. #else /* IEEE */
  610.     fprintf(stderr, "float(%g) [%08lX] --> IEEE[%s]\n", f, p.i, hex);
  611. #endif /* IEEE */
  612. }
  613.  
  614.  
  615. void
  616. TestFromIeeeDouble(hex)
  617. char *hex;
  618. {
  619.     defdouble f;
  620.     union DParts p;
  621.     char bytes[8];
  622.     
  623.     Hex2Bytes(hex, bytes);
  624.     f = ConvertFromIeeeDouble(bytes);
  625.     p.d = f;
  626.  
  627. #ifdef IEEE
  628.     fprintf(stderr, "IEEE(%g) [%.8s %.8s] --> double(%g) [%08lX %08lX]\n",
  629.     MachineIEEEDouble(bytes),
  630.     hex, hex+8, f, p.i[0], p.i[1]);
  631. #else /* IEEE */
  632.     fprintf(stderr, "IEEE[%.8s %.8s] --> double(%g) [%08lX %08lX]\n",
  633.         hex, hex+8, f, p.i[0], p.i[1]);
  634. #endif /* IEEE */
  635.  
  636. }
  637.  
  638. void
  639. TestToIeeeDouble(f)
  640. defdouble f;
  641. {
  642.     union DParts p;
  643.     char bytes[8];
  644.     char hex[16+1];
  645.  
  646.     p.d = f;
  647.  
  648.     ConvertToIeeeDouble(f, bytes);
  649.     Bytes2Hex(bytes, hex, 8);
  650. #ifdef IEEE
  651.     fprintf(stderr, "double(%g) [%08lX %08lX] --> IEEE(%g) [%.8s %.8s]\n",
  652.         f, p.i[0], p.i[1],
  653.         MachineIEEEDouble(bytes),
  654.         hex, hex+8
  655.     );
  656. #else /* IEEE */
  657.     fprintf(stderr, "double(%g) [%08lX %08lX] --> IEEE[%.8s %.8s]\n",
  658.         f, p.i[0], p.i[1], hex, hex+8
  659.     );
  660. #endif /* IEEE */
  661.  
  662. }
  663.  
  664.  
  665. void
  666. TestFromIeeeExtended(hex)
  667. char *hex;
  668. {
  669.     defdouble f;
  670.     union EParts p;
  671.     char bytes[12];
  672.  
  673.     Hex2Bytes(hex, bytes);
  674.     f = ConvertFromIeeeExtended(bytes);
  675.     p.e = f;
  676.  
  677.     bytes[11] = bytes[9];
  678.     bytes[10] = bytes[8];
  679.     bytes[9] = bytes[7];
  680.     bytes[8] = bytes[6];
  681.     bytes[7] = bytes[5];
  682.     bytes[6] = bytes[4];
  683.     bytes[5] = bytes[3];
  684.     bytes[4] = bytes[2];
  685.     bytes[3] = 0;
  686.     bytes[2] = 0;
  687.  
  688. #if defined(applec) || defined(THINK_C) || defined(METROWERKS)
  689.     fprintf(stderr, "IEEE(%g) [%.4s %.8s %.8s] --> extended(%g) [%04X %04X%04X %04X%04X]\n",
  690.         *((defdouble*)(bytes)),
  691.         hex, hex+4, hex+12, f,
  692.         p.i[0]&0xFFFF, p.i[2]&0xFFFF, p.i[3]&0xFFFF, p.i[4]&0xFFFF, p.i[5]&0xFFFF
  693.     );
  694. #else /* !Macintosh */
  695.     fprintf(stderr, "IEEE[%.4s %.8s %.8s] --> extended(%g) [%04X %04X%04X %04X%04X]\n",
  696.         hex, hex+4, hex+12, f,
  697.         p.i[0]&0xFFFF, p.i[2]&0xFFFF, p.i[3]&0xFFFF, p.i[4]&0xFFFF, p.i[5]&0xFFFF
  698.     );
  699. #endif /* Macintosh */
  700. }
  701.  
  702.  
  703. void
  704. TestToIeeeExtended(f)
  705. defdouble f;
  706. {
  707.     char bytes[12];
  708.     char hex[24+1];
  709.  
  710.     ConvertToIeeeExtended(f, bytes);
  711.     Bytes2Hex(bytes, hex, 10);
  712.  
  713.     bytes[11] = bytes[9];
  714.     bytes[10] = bytes[8];
  715.     bytes[9] = bytes[7];
  716.     bytes[8] = bytes[6];
  717.     bytes[7] = bytes[5];
  718.     bytes[6] = bytes[4];
  719.     bytes[5] = bytes[3];
  720.     bytes[4] = bytes[2];
  721.     bytes[3] = 0;
  722.     bytes[2] = 0;
  723.  
  724. #if defined(applec) || defined(THINK_C) || defined(METROWERKS)
  725.     fprintf(stderr, "extended(%g) --> IEEE(%g) [%.4s %.8s %.8s]\n",
  726.         f, *((defdouble*)(bytes)),
  727.         hex, hex+4, hex+12
  728.     );
  729. #else /* !Macintosh */
  730.     fprintf(stderr, "extended(%g) --> IEEE[%.4s %.8s %.8s]\n",
  731.         f,
  732.         hex, hex+4, hex+12
  733.     );
  734. #endif /* Macintosh */
  735. }
  736.  
  737. #include    <signal.h>
  738.  
  739. void SignalFPE(i, j)
  740. int    i;
  741. void (*j)();
  742. {
  743.     printf("[Floating Point Interrupt Caught.]\n", i, j);
  744.     signal(SIGFPE, SignalFPE);
  745. }
  746.     
  747. void
  748. main()
  749. {
  750.     long d[3];
  751.     char bytes[12];
  752.  
  753.     signal(SIGFPE, SignalFPE);
  754.  
  755.     TestFromIeeeSingle("00000000");
  756.     TestFromIeeeSingle("80000000");
  757.     TestFromIeeeSingle("3F800000");
  758.     TestFromIeeeSingle("BF800000");
  759.     TestFromIeeeSingle("40000000");
  760.     TestFromIeeeSingle("C0000000");
  761.     TestFromIeeeSingle("7F800000");
  762.     TestFromIeeeSingle("FF800000");
  763.     TestFromIeeeSingle("00800000");
  764.     TestFromIeeeSingle("00400000");
  765.     TestFromIeeeSingle("00000001");
  766.     TestFromIeeeSingle("80000001");
  767.     TestFromIeeeSingle("3F8FEDCB");
  768.     TestFromIeeeSingle("7FC00100");    /* Quiet NaN(1) */
  769.     TestFromIeeeSingle("7F800100");    /* Signalling NaN(1) */
  770.  
  771.     TestToIeeeSingle(0.0);
  772.     TestToIeeeSingle(-0.0);
  773.     TestToIeeeSingle(1.0);
  774.     TestToIeeeSingle(-1.0);
  775.     TestToIeeeSingle(2.0);
  776.     TestToIeeeSingle(-2.0);
  777.     TestToIeeeSingle(3.0);
  778.     TestToIeeeSingle(-3.0);
  779. #if !(defined(sgi) || defined(NeXT))
  780.     TestToIeeeSingle(HUGE_VAL);
  781.     TestToIeeeSingle(-HUGE_VAL);
  782. #endif
  783.  
  784. #ifdef IEEE
  785.     /* These only work on big-endian IEEE machines */
  786.     d[0] = 0x00800000L; MaybeSwapBytes(d,4); TestToIeeeSingle(*((float*)(&d[0])));        /* Smallest normalized */
  787.     d[0] = 0x00400000L; MaybeSwapBytes(d,4); TestToIeeeSingle(*((float*)(&d[0])));        /* Almost largest denormalized */
  788.     d[0] = 0x00000001L; MaybeSwapBytes(d,4); TestToIeeeSingle(*((float*)(&d[0])));        /* Smallest denormalized */
  789.     d[0] = 0x00000001L; MaybeSwapBytes(d,4); TestToIeeeSingle(*((float*)(&d[0])) * 0.5);    /* Smaller than smallest denorm */
  790.     d[0] = 0x3F8FEDCBL; MaybeSwapBytes(d,4); TestToIeeeSingle(*((float*)(&d[0])));
  791. #if !(defined(sgi) || defined(NeXT))
  792.     d[0] = 0x7FC00100L; MaybeSwapBytes(d,4); TestToIeeeSingle(*((float*)(&d[0])));        /* Quiet NaN(1) */
  793.     d[0] = 0x7F800100L; MaybeSwapBytes(d,4); TestToIeeeSingle(*((float*)(&d[0])));        /* Signalling NaN(1) */
  794. #endif /* sgi */
  795. #endif /* IEEE */
  796.  
  797.  
  798.  
  799.     TestFromIeeeDouble("0000000000000000");
  800.     TestFromIeeeDouble("8000000000000000");
  801.     TestFromIeeeDouble("3FF0000000000000");
  802.     TestFromIeeeDouble("BFF0000000000000");
  803.     TestFromIeeeDouble("4000000000000000");
  804.     TestFromIeeeDouble("C000000000000000");
  805.     TestFromIeeeDouble("7FF0000000000000");
  806.     TestFromIeeeDouble("FFF0000000000000");
  807.     TestFromIeeeDouble("0010000000000000");
  808.     TestFromIeeeDouble("0008000000000000");
  809.     TestFromIeeeDouble("0000000000000001");
  810.     TestFromIeeeDouble("8000000000000001");
  811.     TestFromIeeeDouble("3FFFEDCBA9876543");
  812.     TestFromIeeeDouble("7FF8002000000000");    /* Quiet NaN(1) */
  813.     TestFromIeeeDouble("7FF0002000000000");    /* Signalling NaN(1) */
  814.  
  815.     TestToIeeeDouble(0.0);
  816.     TestToIeeeDouble(-0.0);
  817.     TestToIeeeDouble(1.0);
  818.     TestToIeeeDouble(-1.0);
  819.     TestToIeeeDouble(2.0);
  820.     TestToIeeeDouble(-2.0);
  821.     TestToIeeeDouble(3.0);
  822.     TestToIeeeDouble(-3.0);
  823. #if !(defined(sgi) || defined(NeXT))
  824.     TestToIeeeDouble(HUGE_VAL);
  825.     TestToIeeeDouble(-HUGE_VAL);
  826. #endif
  827.  
  828. #ifdef IEEE
  829.     /* These only work on big-endian IEEE machines */
  830.     Hex2Bytes("0010000000000000", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* Smallest normalized */
  831.     Hex2Bytes("0010000080000000", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* Normalized, problem with unsigned */
  832.     Hex2Bytes("0008000000000000", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* Almost largest denormalized */
  833.     Hex2Bytes("0000000080000000", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* Denorm problem with unsigned */
  834.     Hex2Bytes("0000000000000001", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* Smallest denormalized */
  835.     Hex2Bytes("0000000000000001", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)) * 0.5);    /* Smaller than smallest denorm */
  836.     Hex2Bytes("3FFFEDCBA9876543", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* accuracy test */
  837. #if !(defined(sgi) || defined(NeXT))
  838.     Hex2Bytes("7FF8002000000000", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* Quiet NaN(1) */
  839.     Hex2Bytes("7FF0002000000000", bytes); MaybeSwapBytes(d,8); TestToIeeeDouble(*((Double*)(bytes)));    /* Signalling NaN(1) */
  840. #endif /* sgi */
  841. #endif /* IEEE */
  842.  
  843.     TestFromIeeeExtended("00000000000000000000");    /* +0 */
  844.     TestFromIeeeExtended("80000000000000000000");    /* -0 */
  845.     TestFromIeeeExtended("3FFF8000000000000000");    /* +1 */
  846.     TestFromIeeeExtended("BFFF8000000000000000");    /* -1 */
  847.     TestFromIeeeExtended("40008000000000000000");    /* +2 */
  848.     TestFromIeeeExtended("C0008000000000000000");    /* -2 */
  849.     TestFromIeeeExtended("7FFF0000000000000000");    /* +infinity */
  850.     TestFromIeeeExtended("FFFF0000000000000000");    /* -infinity */
  851.     TestFromIeeeExtended("7FFF8001000000000000");    /* Quiet NaN(1) */
  852.     TestFromIeeeExtended("7FFF0001000000000000");    /* Signalling NaN(1) */
  853.     TestFromIeeeExtended("3FFFFEDCBA9876543210");    /* accuracy test */
  854.  
  855.     TestToIeeeExtended(0.0);
  856.     TestToIeeeExtended(-0.0);
  857.     TestToIeeeExtended(1.0);
  858.     TestToIeeeExtended(-1.0);
  859.     TestToIeeeExtended(2.0);
  860.     TestToIeeeExtended(-2.0);
  861. #if !(defined(sgi) || defined(NeXT))
  862.     TestToIeeeExtended(HUGE_VAL);
  863.     TestToIeeeExtended(-HUGE_VAL);
  864. #endif /* sgi */
  865.  
  866. #if defined(applec) || defined(THINK_C) || defined(METROWERKS)
  867.     Hex2Bytes("7FFF00008001000000000000", bytes); TestToIeeeExtended(*((long double*)(bytes)));    /* Quiet NaN(1) */
  868.     Hex2Bytes("7FFF00000001000000000000", bytes); TestToIeeeExtended(*((long double*)(bytes)));    /* Signalling NaN(1) */
  869.     Hex2Bytes("7FFE00008000000000000000", bytes); TestToIeeeExtended(*((long double*)(bytes)));
  870.     Hex2Bytes("000000008000000000000000", bytes); TestToIeeeExtended(*((long double*)(bytes)));
  871.     Hex2Bytes("000000000000000000000001", bytes); TestToIeeeExtended(*((long double*)(bytes)));
  872.     Hex2Bytes("3FFF0000FEDCBA9876543210", bytes); TestToIeeeExtended(*((long double*)(bytes)));
  873. #endif
  874. }
  875.  
  876.  
  877. /* This is the output of the test program on an IEEE machine:
  878. IEEE(0) [00000000] --> float(0) [00000000]
  879. IEEE(-0) [80000000] --> float(-0) [80000000]
  880. IEEE(1) [3F800000] --> float(1) [3F800000]
  881. IEEE(-1) [BF800000] --> float(-1) [BF800000]
  882. IEEE(2) [40000000] --> float(2) [40000000]
  883. IEEE(-2) [C0000000] --> float(-2) [C0000000]
  884. IEEE(INF) [7F800000] --> float(INF) [7F800000]
  885. IEEE(-INF) [FF800000] --> float(-INF) [FF800000]
  886. IEEE(1.17549e-38) [00800000] --> float(1.17549e-38) [00800000]
  887. IEEE(5.87747e-39) [00400000] --> float(5.87747e-39) [00400000]
  888. IEEE(1.4013e-45) [00000001] --> float(1.4013e-45) [00000001]
  889. IEEE(-1.4013e-45) [80000001] --> float(-1.4013e-45) [80000001]
  890. IEEE(1.12444) [3F8FEDCB] --> float(1.12444) [3F8FEDCB]
  891. IEEE(NAN(001)) [7FC00100] --> float(INF) [7F800000]
  892. IEEE(NAN(001)) [7F800100] --> float(INF) [7F800000]
  893. float(0) [00000000] --> IEEE(0) [00000000]
  894. float(-0) [80000000] --> IEEE(0) [00000000]
  895. float(1) [3F800000] --> IEEE(1) [3F800000]
  896. float(-1) [BF800000] --> IEEE(-1) [BF800000]
  897. float(2) [40000000] --> IEEE(2) [40000000]
  898. float(-2) [C0000000] --> IEEE(-2) [C0000000]
  899. float(3) [40400000] --> IEEE(3) [40400000]
  900. float(-3) [C0400000] --> IEEE(-3) [C0400000]
  901. float(INF) [7F800000] --> IEEE(INF) [7F800000]
  902. float(-INF) [FF800000] --> IEEE(-INF) [FF800000]
  903. float(1.17549e-38) [00800000] --> IEEE(1.17549e-38) [00800000]
  904. float(5.87747e-39) [00400000] --> IEEE(5.87747e-39) [00400000]
  905. float(1.4013e-45) [00000001] --> IEEE(1.4013e-45) [00000001]
  906. float(7.00649e-46) [00000000] --> IEEE(0) [00000000]
  907. float(1.12444) [3F8FEDCB] --> IEEE(1.12444) [3F8FEDCB]
  908. float(NAN(001)) [7FC00100] --> IEEE(INF) [7F800000]
  909. float(NAN(001)) [7FC00100] --> IEEE(INF) [7F800000]
  910. IEEE(0) [00000000 00000000] --> double(0) [00000000 00000000]
  911. IEEE(-0) [80000000 00000000] --> double(-0) [80000000 00000000]
  912. IEEE(1) [3FF00000 00000000] --> double(1) [3FF00000 00000000]
  913. IEEE(-1) [BFF00000 00000000] --> double(-1) [BFF00000 00000000]
  914. IEEE(2) [40000000 00000000] --> double(2) [40000000 00000000]
  915. IEEE(-2) [C0000000 00000000] --> double(-2) [C0000000 00000000]
  916. IEEE(INF) [7FF00000 00000000] --> double(INF) [7FF00000 00000000]
  917. IEEE(-INF) [FFF00000 00000000] --> double(-INF) [FFF00000 00000000]
  918. IEEE(2.22507e-308) [00100000 00000000] --> double(2.22507e-308) [00100000 00000000]
  919. IEEE(1.11254e-308) [00080000 00000000] --> double(1.11254e-308) [00080000 00000000]
  920. IEEE(4.94066e-324) [00000000 00000001] --> double(4.94066e-324) [00000000 00000001]
  921. IEEE(-4.94066e-324) [80000000 00000001] --> double(-4.94066e-324) [80000000 00000001]
  922. IEEE(1.99556) [3FFFEDCB A9876543] --> double(1.99556) [3FFFEDCB A9876543]
  923. IEEE(NAN(001)) [7FF80020 00000000] --> double(INF) [7FF00000 00000000]
  924. IEEE(NAN(001)) [7FF00020 00000000] --> double(INF) [7FF00000 00000000]
  925. double(0) [00000000 00000000] --> IEEE(0) [00000000 00000000]
  926. double(-0) [80000000 00000000] --> IEEE(0) [00000000 00000000]
  927. double(1) [3FF00000 00000000] --> IEEE(1) [3FF00000 00000000]
  928. double(-1) [BFF00000 00000000] --> IEEE(-1) [BFF00000 00000000]
  929. double(2) [40000000 00000000] --> IEEE(2) [40000000 00000000]
  930. double(-2) [C0000000 00000000] --> IEEE(-2) [C0000000 00000000]
  931. double(3) [40080000 00000000] --> IEEE(3) [40080000 00000000]
  932. double(-3) [C0080000 00000000] --> IEEE(-3) [C0080000 00000000]
  933. double(INF) [7FF00000 00000000] --> IEEE(INF) [7FF00000 00000000]
  934. double(-INF) [FFF00000 00000000] --> IEEE(-INF) [FFF00000 00000000]
  935. double(2.22507e-308) [00100000 00000000] --> IEEE(2.22507e-308) [00100000 00000000]
  936. double(2.22507e-308) [00100000 80000000] --> IEEE(2.22507e-308) [00100000 80000000]
  937. double(1.11254e-308) [00080000 00000000] --> IEEE(1.11254e-308) [00080000 00000000]
  938. double(1.061e-314) [00000000 80000000] --> IEEE(1.061e-314) [00000000 80000000]
  939. double(4.94066e-324) [00000000 00000001] --> IEEE(4.94066e-324) [00000000 00000001]
  940. double(4.94066e-324) [00000000 00000001] --> IEEE(4.94066e-324) [00000000 00000001]
  941. double(1.99556) [3FFFEDCB A9876543] --> IEEE(1.99556) [3FFFEDCB A9876543]
  942. double(NAN(001)) [7FF80020 00000000] --> IEEE(INF) [7FF00000 00000000]
  943. double(NAN(001)) [7FF80020 00000000] --> IEEE(INF) [7FF00000 00000000]
  944. IEEE(0) [0000 00000000 00000000] --> extended(0) [0000 00000000 00000000]
  945. IEEE(-0) [8000 00000000 00000000] --> extended(-0) [8000 00000000 00000000]
  946. IEEE(1) [3FFF 80000000 00000000] --> extended(1) [3FFF 80000000 00000000]
  947. IEEE(-1) [BFFF 80000000 00000000] --> extended(-1) [BFFF 80000000 00000000]
  948. IEEE(2) [4000 80000000 00000000] --> extended(2) [4000 80000000 00000000]
  949. IEEE(-2) [C000 80000000 00000000] --> extended(-2) [C000 80000000 00000000]
  950. IEEE(INF) [7FFF 00000000 00000000] --> extended(INF) [7FFF 00000000 00000000]
  951. IEEE(-INF) [FFFF 00000000 00000000] --> extended(-INF) [FFFF 00000000 00000000]
  952. IEEE(NAN(001)) [7FFF 80010000 00000000] --> extended(INF) [7FFF 00000000 00000000]
  953. IEEE(NAN(001)) [7FFF 00010000 00000000] --> extended(INF) [7FFF 00000000 00000000]
  954. IEEE(1.99111) [3FFF FEDCBA98 76543210] --> extended(1.99111) [3FFF FEDCBA98 76543210]
  955. extended(0) --> IEEE(0) [0000 00000000 00000000]
  956. extended(-0) --> IEEE(0) [0000 00000000 00000000]
  957. extended(1) --> IEEE(1) [3FFF 80000000 00000000]
  958. extended(-1) --> IEEE(-1) [BFFF 80000000 00000000]
  959. extended(2) --> IEEE(2) [4000 80000000 00000000]
  960. extended(-2) --> IEEE(-2) [C000 80000000 00000000]
  961. extended(INF) --> IEEE(INF) [7FFF 00000000 00000000]
  962. extended(-INF) --> IEEE(-INF) [FFFF 00000000 00000000]
  963. extended(NAN(001)) --> IEEE(INF) [7FFF 00000000 00000000]
  964. extended(NAN(001)) --> IEEE(INF) [7FFF 00000000 00000000]
  965. extended(5.94866e+4931) --> IEEE(5.94866e+4931) [7FFE 80000000 00000000]
  966. extended(1e-4927) --> IEEE(1e-4927) [0000 80000000 00000000]
  967. extended(1e-4927) --> IEEE(1e-4927) [0000 00000000 00000001]
  968. extended(1.99111) --> IEEE(1.99111) [3FFF FEDCBA98 76543210]
  969. */
  970.  
  971. #endif /* TEST_FP */
  972.