home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / backup / star-1.3.1.tar.gz / star-1.3.1.tar / star-1.3.1 / lib / fconv.c < prev    next >
C/C++ Source or Header  |  2001-03-04  |  5KB  |  265 lines

  1. /* @(#)fconv.c    1.29 01/03/04 Copyright 1985 J. Schilling */
  2. /*
  3.  *    Convert floating point numbers to strings for format.c
  4.  *    Should rather use the MT-safe routines [efg]convert()
  5.  *
  6.  *    Copyright (c) 1985 J. Schilling
  7.  */
  8. /*
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2, or (at your option)
  12.  * any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. #include <mconfig.h>    /* <- may define NO_FLOATINGPOINT */
  25. #ifndef    NO_FLOATINGPOINT
  26.  
  27. #include <stdxlib.h>
  28. #include <standard.h>
  29. #include <strdefs.h>
  30. #include <schily.h>
  31.  
  32. #if    !defined(HAVE_STDLIB_H) || defined(HAVE_DTOA)
  33. extern    char    *ecvt __PR((double, int, int *, int *));
  34. extern    char    *fcvt __PR((double, int, int *, int *));
  35. #endif
  36.  
  37. #if    defined(HAVE_ISNAN) && defined(HAVE_ISINF)
  38. /*
  39.  * *BSD alike libc
  40.  */
  41. #define    FOUND_ISXX
  42. #endif
  43.  
  44. #include <math.h>
  45.  
  46. #if    defined(HAVE_FP_H)  && !defined(FOUND_ISXX)
  47. /*
  48.  * WAS:
  49.  * #if    defined(__osf__) || defined(_IBMR2) || defined(_AIX)
  50.  */
  51. /*
  52.  * Moved before HAVE_IEEEFP_H for True64 due to a hint
  53.  * from Bert De Knuydt <Bert.Deknuydt@esat.kuleuven.ac.be>
  54.  *
  55.  * True64 has both fp.h & ieeefp.h but the functions
  56.  * isnand() & finite() seem to be erreneously not implemented
  57.  * as a macro and the function lives in libm.
  58.  * Let's hope that we will not get problems with the new order.
  59.  */
  60. #include <fp.h> 
  61. #ifndef    isnan
  62. #define    isnan    IS_NAN
  63. #endif
  64. #ifndef    isinf
  65. #define    isinf    !FINITE
  66. /*#define    isinf    IS_INF*/
  67. #endif
  68. #define    FOUND_ISXX
  69. #endif 
  70.  
  71. #if    defined(HAVE_IEEEFP_H) && !defined(FOUND_ISXX)
  72. /*
  73.  * SVR4
  74.  */
  75. #include <ieeefp.h>
  76. #define    isnan    isnand
  77. #define    isinf    !finite
  78. #define    FOUND_ISXX
  79. #endif
  80.  
  81. /*
  82.  * WAS:
  83.  * #if    defined(__hpux) || defined(VMS) || defined(_SCO_DS) || defined(__QNX__)
  84.  */
  85. #if    defined(__hpux)
  86. #undef    isnan
  87. #undef    isinf
  88. #endif
  89.  
  90. #if    !defined(isnan) && !defined(HAVE_ISNAN)
  91. #define    isnan(val)    (0)
  92. #endif
  93. #if    !defined(isinf) && !defined(HAVE_ISINF)
  94. #define    isinf(val)    (0)
  95. #endif
  96.  
  97. #if !defined(HAVE_ECVT) || !defined(HAVE_FCVT) || !defined(HAVE_GCVT)
  98. #include "cvt.c"
  99. #endif
  100.  
  101. static    char    _nan[] = "(NaN)";
  102. static    char    _inf[] = "(Infinity)";
  103.  
  104. static    int    _ferr __PR((char *, double));
  105.  
  106. #ifdef    abs
  107. #    undef    abs
  108. #endif
  109. #define    abs(i)    ((i) < 0 ? -(i) : (i))
  110.  
  111. EXPORT int
  112. ftoes(s, val, fieldwidth, ndigits)
  113.     register    char     *s;
  114.             double    val;
  115.     register    int    fieldwidth;
  116.     register    int    ndigits;
  117. {
  118.     register    char    *b;
  119.     register    char    *rs;
  120.     register    int    len;
  121.     register    int    rdecpt;
  122.             int     decpt;
  123.             int    sign;
  124.  
  125.     if ((len = _ferr(s, val)) > 0)
  126.         return len;
  127.     rs = s;
  128. #ifdef    V7_FLOATSTYLE
  129.     b = ecvt(val, ndigits, &decpt, &sign);
  130.     rdecpt = decpt;
  131. #else
  132.     b = ecvt(val, ndigits+1, &decpt, &sign);
  133.     rdecpt = decpt-1;
  134. #endif
  135.     len = ndigits + 6;            /* Punkt e +/- nnn */
  136.     if (sign)
  137.         len++;
  138.     if (fieldwidth > len)
  139.         while (fieldwidth-- > len)
  140.             *rs++ = ' ';
  141.     if (sign)
  142.         *rs++ = '-';
  143. #ifndef    V7_FLOATSTYLE
  144.     if (*b)
  145.         *rs++ = *b++;
  146. #endif
  147.     *rs++ = '.';
  148.     while (*b && ndigits-- > 0)
  149.         *rs++ = *b++;
  150.     *rs++ = 'e';
  151.     *rs++ = rdecpt >= 0 ? '+' : '-';
  152.     rdecpt = abs(rdecpt);
  153. #ifndef    V7_FLOATSTYLE
  154.     if (rdecpt >= 100)
  155. #endif
  156.     {
  157.         *rs++ = rdecpt / 100 + '0';
  158.         rdecpt %= 100;
  159.     }
  160.     *rs++ = rdecpt / 10 + '0';
  161.     *rs++ = rdecpt % 10 + '0';
  162.     *rs = '\0';
  163.     return rs - s;
  164. }
  165.  
  166. /*
  167.  * fcvt() from Cygwin32 is buggy.
  168.  */
  169. #if    !defined(HAVE_FCVT) && defined(HAVE_ECVT)
  170. #define    USE_ECVT
  171. #endif
  172.  
  173. EXPORT int
  174. ftofs(s, val, fieldwidth, ndigits)
  175.     register    char     *s;
  176.             double    val;
  177.     register    int    fieldwidth;
  178.     register    int    ndigits;
  179. {
  180.     register    char    *b;
  181.     register    char    *rs;
  182.     register    int    len;
  183.     register    int    rdecpt;
  184.             int     decpt;
  185.             int    sign;
  186.  
  187.     if ((len = _ferr(s, val)) > 0)
  188.         return len;
  189.     rs = s;
  190. #ifdef    USE_ECVT
  191.     /*
  192.      * Needed on systems with broken fcvt() implementation
  193.      * (e.g. Cygwin32)
  194.      */
  195.     b = ecvt(val, ndigits, &decpt, &sign);
  196.     /*
  197.      * The next call is needed to force higher precision.
  198.      */
  199.     if (decpt > 0)
  200.         b = ecvt(val, ndigits+decpt, &decpt, &sign);
  201. #else
  202.     b = fcvt(val, ndigits, &decpt, &sign);
  203. #endif
  204.     rdecpt = decpt;
  205.     len = rdecpt + ndigits + 1;
  206.     if (rdecpt < 0)
  207.         len -= rdecpt;
  208.     if (sign)
  209.         len++;
  210.     if (fieldwidth > len)
  211.         while (fieldwidth-- > len)
  212.             *rs++ = ' ';
  213.     if (sign)
  214.         *rs++ = '-';
  215.     if (rdecpt > 0) {
  216.         len = rdecpt;
  217.         while (*b && len-- > 0)
  218.             *rs++ = *b++;
  219. #ifdef    USE_ECVT
  220.         while (len-- > 0)
  221.             *rs++ = '0';
  222. #endif
  223.     }
  224. #ifndef    V7_FLOATSTYLE
  225.     else {
  226.         *rs++ = '0';
  227.     }
  228. #endif
  229.     *rs++ = '.';
  230.     if (rdecpt < 0) {
  231.         len = rdecpt;
  232.         while (len++ < 0 && ndigits-- > 0)
  233.             *rs++ = '0';
  234.     }
  235.     while (*b && ndigits-- > 0)
  236.         *rs++ = *b++;
  237. #ifdef    USE_ECVT
  238.     while (ndigits-- > 0)
  239.         *rs++ = '0';
  240. #endif
  241.     *rs = '\0';
  242.     return rs - s;
  243. }
  244.  
  245. LOCAL int
  246. _ferr(s, val)
  247.     char    *s;
  248.     double    val;
  249. {
  250.     if (isnan(val)){
  251.         strcpy(s, _nan);
  252.         return (sizeof (_nan) - 1);
  253.     }
  254.  
  255.     /*
  256.      * Check first for NaN because finite() will return 1 on Nan too.
  257.      */
  258.     if (isinf(val)){
  259.         strcpy(s, _inf);
  260.         return (sizeof (_inf) - 1);
  261.     }
  262.     return 0;
  263. }
  264. #endif    /* NO_FLOATINGPOINT */
  265.