]> git.saurik.com Git - apple/libc.git/blobdiff - gdtoa/FreeBSD/gdtoaimp.h
Libc-1044.40.1.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoaimp.h
index dd398e46004f17b69e4f0d06abf34f898a724caa..b967e810848a8b922fbd7e46f268ddb382ad9db6 100644 (file)
@@ -26,8 +26,6 @@ THIS SOFTWARE.
 
 ****************************************************************/
 
-/* $FreeBSD: src/contrib/gdtoa/gdtoaimp.h,v 1.5 2003/04/09 06:04:35 das Exp $ */
-
 /* This is a variation on dtoa.c that converts arbitary binary
    floating-point formats to and from decimal notation.  It uses
    double-precision arithmetic internally, so there are still
@@ -35,13 +33,8 @@ THIS SOFTWARE.
    double-precision arithmetic (any of IEEE, VAX D_floating,
    or IBM mainframe arithmetic).
 
-   Please send bug reports to
-       David M. Gay
-       Bell Laboratories, Room 2C-463
-       600 Mountain Avenue
-       Murray Hill, NJ 07974-0636
-       U.S.A.
-       dmg@bell-labs.com
+   Please send bug reports to David M. Gay (dmg at acm dot org,
+   with " at " changed at "@" and " dot " changed to ".").
  */
 
 /* On a machine with IEEE extended-precision registers, it is
@@ -63,7 +56,7 @@ THIS SOFTWARE.
  * biased rounding (add half and chop).
  *
  * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 112-126].
  *
  * Modifications:
  *
@@ -120,7 +113,12 @@ THIS SOFTWARE.
  * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
  *     if memory is available and otherwise does something you deem
  *     appropriate.  If MALLOC is undefined, malloc will be invoked
- *     directly -- and assumed always to succeed.
+ *     directly -- and assumed always to succeed.  Similarly, if you
+ *     want something other than the system's free() to be called to
+ *     recycle memory acquired from MALLOC, #define FREE to be the
+ *     name of the alternate routine.  (FREE or free is only called in
+ *     pathological cases, e.g., in a gdtoa call after a gdtoa return in
+ *     mode 3 with thousands of digits requested.)
  * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
  *     memory allocations from a private pool of memory when possible.
  *     When used, the private pool is PRIVATE_MEM bytes long:  2304 bytes,
@@ -133,20 +131,22 @@ THIS SOFTWARE.
  *     conversions of IEEE doubles in single-threaded executions with
  *     8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
  *     4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- *     Infinity and NaN (case insensitively).  On some systems (e.g.,
- *     some HP systems), it may be necessary to #define NAN_WORD0
- *     appropriately -- to the most significant word of a quiet NaN.
- *     (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
+ *     #defined automatically on IEEE systems.  On such systems,
+ *     when INFNAN_CHECK is #defined, strtod checks
+ *     for Infinity and NaN (case insensitively).
  *     When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
  *     strtodg also accepts (case insensitively) strings of the form
- *     NaN(x), where x is a string of hexadecimal digits and spaces;
- *     if there is only one string of hexadecimal digits, it is taken
- *     for the fraction bits of the resulting NaN; if there are two or
- *     more strings of hexadecimal digits, each string is assigned
- *     to the next available sequence of 32-bit words of fractions
- *     bits (starting with the most significant), right-aligned in
- *     each sequence.
+ *     NaN(x), where x is a string of hexadecimal digits (optionally
+ *     preceded by 0x or 0X) and spaces; if there is only one string
+ *     of hexadecimal digits, it is taken for the fraction bits of the
+ *     resulting NaN; if there are two or more strings of hexadecimal
+ *     digits, each string is assigned to the next available sequence
+ *     of 32-bit words of fractions bits (starting with the most
+ *     significant), right-aligned in each sequence.
+ *     Unless GDTOA_NON_PEDANTIC_NANCHECK is #defined, input "NaN(...)"
+ *     is consumed even when ... has the wrong form (in which case the
+ *     "(...)" is consumed but ignored).
  * #define MULTIPLE_THREADS if the system offers preemptively scheduled
  *     multiple threads.  In this case, you must provide (or suitably
  *     #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
@@ -158,7 +158,7 @@ THIS SOFTWARE.
  *     dtoa.  You may do so whether or not MULTIPLE_THREADS is #defined.
  * #define IMPRECISE_INEXACT if you do not care about the setting of
  *     the STRTOG_Inexact bits in the special case of doing IEEE double
- *     precision conversions (which could also be done by the strtog in
+ *     precision conversions (which could also be done by the strtod in
  *     dtoa.c).
  * #define NO_HEX_FP to disable recognition of C9x's hexadecimal
  *     floating-point constants.
@@ -167,17 +167,101 @@ THIS SOFTWARE.
  * #define NO_STRING_H to use private versions of memcpy.
  *     On some K&R systems, it may also be necessary to
  *     #define DECLARE_SIZE_T in this case.
- * #define YES_ALIAS to permit aliasing certain double values with
- *     arrays of ULongs.  This leads to slightly better code with
- *     some compilers and was always used prior to 19990916, but it
- *     is not strictly legal and can cause trouble with aggressively
- *     optimizing compilers (e.g., gcc 2.95.1 under -O2).
  * #define USE_LOCALE to use the current locale's decimal_point value.
  */
 
 #ifndef GDTOAIMP_H_INCLUDED
 #define GDTOAIMP_H_INCLUDED
+/*
+ * Paranoia: Protect exported symbols, including ones in files we don't
+ * compile right now.  The standard strtof and strtod survive.
+ */
+#define        dtoa            __dtoa
+#define        gdtoa           __gdtoa
+#define        freedtoa        __freedtoa
+#define        strtodg         __strtodg
+#define        g_ddfmt         __g_ddfmt
+#define        g_dfmt          __g_dfmt
+#define        g_ffmt          __g_ffmt
+#define        g_Qfmt          __g_Qfmt
+#define        g_xfmt          __g_xfmt
+#define        g_xLfmt         __g_xLfmt
+#define        strtoId         __strtoId
+#define        strtoIdd        __strtoIdd
+#define        strtoIf         __strtoIf
+#define        strtoIQ         __strtoIQ
+#define        strtoIx         __strtoIx
+#define        strtoIxL        __strtoIxL
+#define        strtord         __strtord
+#define        strtordd        __strtordd
+#define        strtorf         __strtorf
+#define        strtorQ         __strtorQ
+#define        strtorx         __strtorx
+#define        strtorxL        __strtorxL
+#define        strtodI         __strtodI
+#define        strtopd         __strtopd
+#define        strtopdd        __strtopdd
+#define        strtopf         __strtopf
+#define        strtopQ         __strtopQ
+#define        strtopx         __strtopx
+#define        strtopxL        __strtopxL
+
+/* Protect gdtoa-internal symbols */
+#define        Balloc          __Balloc_D2A
+#define        Bfree           __Bfree_D2A
+#define        ULtoQ           __ULtoQ_D2A
+#define        ULtof           __ULtof_D2A
+#define        ULtod           __ULtod_D2A
+#define        ULtodd          __ULtodd_D2A
+#define        ULtox           __ULtox_D2A
+#define        ULtoxL          __ULtoxL_D2A
+#define        any_on          __any_on_D2A
+#define        b2d             __b2d_D2A
+#define        bigtens         __bigtens_D2A
+#define        cmp             __cmp_D2A
+#define        copybits        __copybits_D2A
+#define        d2b             __d2b_D2A
+#define        decrement       __decrement_D2A
+#define        diff            __diff_D2A
+#define        dtoa_result     __dtoa_result_D2A
+#define        g__fmt          __g__fmt_D2A
+#define        gethex          __gethex_D2A
+#define        hexdig          __hexdig_D2A
+#define        hexdig_init_D2A __hexdig_init_D2A
+#define        hexnan          __hexnan_D2A
+#define        hi0bits         __hi0bits_D2A
+#define        hi0bits_D2A     __hi0bits_D2A
+#define        i2b             __i2b_D2A
+#define        increment       __increment_D2A
+#define        lo0bits         __lo0bits_D2A
+#define        lshift          __lshift_D2A
+#define        match           __match_D2A
+#define        mult            __mult_D2A
+#define        multadd         __multadd_D2A
+#define        nrv_alloc       __nrv_alloc_D2A
+#define        pow5mult        __pow5mult_D2A
+#define        quorem          __quorem_D2A
+#define        ratio           __ratio_D2A
+#define        rshift          __rshift_D2A
+#define        rv_alloc        __rv_alloc_D2A
+#define        s2b             __s2b_D2A
+#define        set_ones        __set_ones_D2A
+#define        strcp           __strcp_D2A
+#define        strcp_D2A       __strcp_D2A
+#define        strtoIg         __strtoIg_D2A
+#define        sum             __sum_D2A
+#define        tens            __tens_D2A
+#define        tinytens        __tinytens_D2A
+#define        tinytens        __tinytens_D2A
+#define        trailz          __trailz_D2A
+#define        ulp             __ulp_D2A
+
+#include <xlocale.h>
 #include "gdtoa.h"
+#include "gd_qnan.h"
+#ifdef Honor_FLT_ROUNDS
+#include <fenv.h>
+#endif
 
 #ifdef DEBUG
 #include "stdio.h"
@@ -204,6 +288,7 @@ extern Char *MALLOC ANSI((size_t));
 
 #define INFNAN_CHECK
 #define USE_LOCALE
+#define NO_LOCALE_CACHE
 
 #undef IEEE_Arith
 #undef Avoid_Underflow
@@ -277,25 +362,14 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
 
 typedef union { double d; ULong L[2]; } U;
 
-#ifdef YES_ALIAS
-#define dval(x) x
 #ifdef IEEE_8087
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
 #else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
 #endif
-#else /* !YES_ALIAS */
-#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
-#endif
-#define dval(x) ((U*)&x)->d
-#endif /* YES_ALIAS */
+#define dval(x) (x)->d
 
 /* The following definition of Storeinc is appropriate for MIPS processors.
  * An alternative that might be better on some machines is
@@ -466,16 +540,14 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
 
 #define MULTIPLE_THREADS
 extern spinlock_t __gdtoa_locks[2];
-#define ACQUIRE_DTOA_LOCK(n)   do {            \
-       if (__isthreaded)                       \
-               _SPINLOCK(&__gdtoa_locks[n]);   \
+#define ACQUIRE_DTOA_LOCK(n)   do {                            \
+       if (__isthreaded) _SPINLOCK(&__gdtoa_locks[n]);         \
 } while(0)
-#define FREE_DTOA_LOCK(n)      do {            \
-       if (__isthreaded)                       \
-               _SPINUNLOCK(&__gdtoa_locks[n]); \
+#define FREE_DTOA_LOCK(n)      do {                            \
+       if (__isthreaded) _SPINUNLOCK(&__gdtoa_locks[n]);       \
 } while(0)
 
-#define Kmax 15
+#define Kmax 9
 
  struct
 Bigint {
@@ -496,92 +568,9 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
 #define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
 #endif /* NO_STRING_H */
 
-/*
- * Paranoia: Protect exported symbols, including ones in files we don't
- * compile right now.  The standard strtof and strtod survive.
- */
-#define        dtoa            __dtoa
-#define        gdtoa           __gdtoa
-#define        freedtoa        __freedtoa
-#define        strtodg         __strtodg
-#define        g_ddfmt         __g_ddfmt
-#define        g_dfmt          __g_dfmt
-#define        g_ffmt          __g_ffmt
-#define        g_Qfmt          __g_Qfmt
-#define        g_xfmt          __g_xfmt
-#define        g_xLfmt         __g_xLfmt
-#define        strtoId         __strtoId
-#define        strtoIdd        __strtoIdd
-#define        strtoIf         __strtoIf
-#define        strtoIQ         __strtoIQ
-#define        strtoIx         __strtoIx
-#define        strtoIxL        __strtoIxL
-#define        strtord         __strtord
-#define        strtordd        __strtordd
-#define        strtorf         __strtorf
-#define        strtorQ         __strtorQ
-#define        strtorx         __strtorx
-#define        strtorxL        __strtorxL
-#define        strtodI         __strtodI
-#define        strtopd         __strtopd
-#define        strtopdd        __strtopdd
-#define        strtopf         __strtopf
-#define        strtopQ         __strtopQ
-#define        strtopx         __strtopx
-#define        strtopxL        __strtopxL
-
-/* Protect gdtoa-internal symbols */
-#define        Balloc          __Balloc_D2A
-#define        Bfree           __Bfree_D2A
-#define        ULtoQ           __ULtoQ_D2A
-#define        ULtof           __ULtof_D2A
-#define        ULtod           __ULtod_D2A
-#define        ULtodd          __ULtodd_D2A
-#define        ULtox           __ULtox_D2A
-#define        ULtoxL          __ULtoxL_D2A
-#define        any_on          __any_on_D2A
-#define        b2d             __b2d_D2A
-#define        bigtens         __bigtens_D2A
-#define        cmp             __cmp_D2A
-#define        copybits        __copybits_D2A
-#define        d2b             __d2b_D2A
-#define        decrement       __decrement_D2A
-#define        diff            __diff_D2A
-#define        dtoa_result     __dtoa_result_D2A
-#define        g__fmt          __g__fmt_D2A
-#define        gethex          __gethex_D2A
-#define        hexdig          __hexdig_D2A
-#define        hexdig_init_D2A __hexdig_init_D2A
-#define        hexnan          __hexnan_D2A
-#define        hi0bits         __hi0bits_D2A
-#define        i2b             __i2b_D2A
-#define        increment       __increment_D2A
-#define        lo0bits         __lo0bits_D2A
-#define        lshift          __lshift_D2A
-#define        match           __match_D2A
-#define        mult            __mult_D2A
-#define        multadd         __multadd_D2A
-#define        nrv_alloc       __nrv_alloc_D2A
-#define        pow5mult        __pow5mult_D2A
-#define        quorem          __quorem_D2A
-#define        ratio           __ratio_D2A
-#define        rshift          __rshift_D2A
-#define        rv_alloc        __rv_alloc_D2A
-#define        s2b             __s2b_D2A
-#define        set_ones        __set_ones_D2A
-#define        strcp           __strcp_D2A
-#define        strcp_D2A       __strcp_D2A
-#define        strtoIg         __strtoIg_D2A
-#define        sum             __sum_D2A
-#define        tens            __tens_D2A
-#define        tinytens        __tinytens_D2A
-#define        tinytens        __tinytens_D2A
-#define        trailz          __trailz_D2A
-#define        ulp             __ulp_D2A
-
  extern char *dtoa_result;
  extern CONST double bigtens[], tens[], tinytens[];
- extern unsigned char hexdig[];
+ extern CONST unsigned char hexdig[];
 
  extern Bigint *Balloc ANSI((int));
  extern void Bfree ANSI((Bigint*));
@@ -596,18 +585,15 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
  extern int cmp ANSI((Bigint*, Bigint*));
  extern void copybits ANSI((ULong*, int, Bigint*));
  extern Bigint *d2b ANSI((double, int*, int*));
- extern int decrement ANSI((Bigint*));
+ extern void decrement ANSI((Bigint*));
  extern Bigint *diff ANSI((Bigint*, Bigint*));
  extern char *dtoa ANSI((double d, int mode, int ndigits,
                        int *decpt, int *sign, char **rve));
- extern void freedtoa ANSI((char*));
- extern char *gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp,
-                         int mode, int ndigits, int *decpt, char **rve));
- extern char *g__fmt ANSI((char*, char*, char*, int, ULong));
- extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
+ extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
+ extern int gethex ANSI((CONST char**, CONST FPI*, Long*, Bigint**, int, locale_t));
  extern void hexdig_init_D2A(Void);
- extern int hexnan ANSI((CONST char**, FPI*, ULong*));
- extern int hi0bits ANSI((ULong));
+ extern int hexnan ANSI((CONST char**, CONST FPI*, ULong*));
+ extern int hi0bits_D2A ANSI((ULong));
  extern Bigint *i2b ANSI((int));
  extern Bigint *increment ANSI((Bigint*));
  extern int lo0bits ANSI((ULong*));
@@ -621,62 +607,55 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
  extern double ratio ANSI((Bigint*, Bigint*));
  extern void rshift ANSI((Bigint*, int));
  extern char *rv_alloc ANSI((int));
- extern Bigint *s2b ANSI((CONST char*, int, int, ULong));
+ extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int));
  extern Bigint *set_ones ANSI((Bigint*, int));
  extern char *strcp ANSI((char*, const char*));
- extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
-
- extern int strtoId ANSI((CONST char *, char **, double *, double *));
- extern int strtoIdd ANSI((CONST char *, char **, double *, double *));
- extern int strtoIf ANSI((CONST char *, char **, float *, float *));
  extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
- extern int strtoIQ ANSI((CONST char *, char **, void *, void *));
- extern int strtoIx ANSI((CONST char *, char **, void *, void *));
- extern int strtoIxL ANSI((CONST char *, char **, void *, void *));
  extern double strtod ANSI((const char *s00, char **se));
- extern int strtopQ ANSI((CONST char *, char **, Void *));
- extern int strtopf ANSI((CONST char *, char **, float *));
- extern int strtopd ANSI((CONST char *, char **, double *));
- extern int strtopdd ANSI((CONST char *, char **, double *));
- extern int strtopx ANSI((CONST char *, char **, Void *));
- extern int strtopxL ANSI((CONST char *, char **, Void *));
- extern int strtord ANSI((CONST char *, char **, int, double *));
- extern int strtordd ANSI((CONST char *, char **, int, double *));
- extern int strtorf ANSI((CONST char *, char **, int, float *));
- extern int strtorQ ANSI((CONST char *, char **, int, void *));
- extern int strtorx ANSI((CONST char *, char **, int, void *));
- extern int strtorxL ANSI((CONST char *, char **, int, void *));
+ extern double strtod_l ANSI((const char *s00, char **se, locale_t));
  extern Bigint *sum ANSI((Bigint*, Bigint*));
  extern int trailz ANSI((Bigint*));
- extern double ulp ANSI((double));
+ extern double ulp ANSI((U*));
 
 #ifdef __cplusplus
 }
 #endif
-
-
+/*
+ * NAN_WORD0 and NAN_WORD1 are only referenced in strtod.c.  Prior to
+ * 20050115, they used to be hard-wired here (to 0x7ff80000 and 0,
+ * respectively), but now are determined by compiling and running
+ * qnan.c to generate gd_qnan.h, which specifies d_QNAN0 and d_QNAN1.
+ * Formerly gdtoaimp.h recommended supplying suitable -DNAN_WORD0=...
+ * and -DNAN_WORD1=...  values if necessary.  This should still work.
+ * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ */
 #ifdef IEEE_Arith
+#ifndef NO_INFNAN_CHECK
+#undef INFNAN_CHECK
+#define INFNAN_CHECK
+#endif
 #ifdef IEEE_MC68k
 #define _0 0
 #define _1 1
+#ifndef NAN_WORD0
+#define NAN_WORD0 d_QNAN0
+#endif
+#ifndef NAN_WORD1
+#define NAN_WORD1 d_QNAN1
+#endif
 #else
 #define _0 1
 #define _1 0
-#endif
-#else
-#undef INFNAN_CHECK
-#endif
-
-#ifdef INFNAN_CHECK
-
 #ifndef NAN_WORD0
-#define NAN_WORD0 0x7ff80000
+#define NAN_WORD0 d_QNAN1
 #endif
-
 #ifndef NAN_WORD1
-#define NAN_WORD1 0
+#define NAN_WORD1 d_QNAN0
+#endif
+#endif
+#else
+#undef INFNAN_CHECK
 #endif
-#endif /* INFNAN_CHECK */
 
 #undef SI
 #ifdef Sudden_Underflow
@@ -685,4 +664,78 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
 #define SI 0
 #endif
 
+/*
+ * For very large strings, strtod and family might exhaust memory in tight
+ * memory conditions (especially in 32-bits).  Such large strings could also
+ * tie up a CPU for minutes at a time.  Either can be considered a denial-of-
+ * service vunerability.
+ *
+ * To fix, we limit the string size to the maximum we need to calculate the
+ * rounding point correctly.  The longest string corresponding to the exact
+ * value of a floating point number occuring at 1.f...f p^-n, where n is
+ * the (absolute value of the) smallest exponent for a normalize number.
+ *
+ * To calculate this number of decimal digits, we use the formula:
+ *
+ * (n + m) - int(n * log10(2)) + 3
+ *
+ * where m is the number of bits in the f...f fraction.  This is the number
+ * of decimal digits for the least significant bit minus the number of leading
+ * zeros for the most significant bit (the '1'), plus a few to compensate for
+ * an extra digits due to the full 1.f...f value, an extra digit for the
+ * mid-way point for rounding and an extra guard digit.
+ *
+ * Using the approximation log10(2) ~ 1233 / (2^12), converting to the fpi.emin
+ * and fpi.nbits values, we get:
+ *
+ * -fpi.emin -((1233 * (-fpi.nbits - fpi.emin)) >> 12) + 3
+ *
+ * Finally, we add an extra digit, either '1' or '0', to represent whether
+ * to-be-truncated digits contain a non-zero digit, or are all zeros,
+ * respectively.
+ *
+ * The truncated string is allocated on the heap, so code using
+ * TRUNCATE_DIGITS() will need to free that space when no longer needed.
+ * Pass a char * as the second argument, initialized to NULL; if its value
+ * becomes non-NULL, memory was allocated.
+ */
+#define LOG2NUM 1233
+#define LOG2DENOMSHIFT 12
+#define TRUNCATEDIGITS(_nbits, _emin)  (-(_emin) - ((LOG2NUM * (-(_nbits) - (_emin))) >> LOG2DENOMSHIFT) + 3)
+
+#define TRUNCATE_DIGITS(_s0, _temp, _nd, _nd0, _nf, _nbits, _emin, _dplen) \
+{ \
+       int _maxdigits = TRUNCATEDIGITS((_nbits), (_emin)); \
+       if ((_nd) > _maxdigits && \
+         ((_temp) = MALLOC(_maxdigits + (_dplen) + 2)) != NULL) { \
+               char *_tp = (_temp) + _maxdigits; \
+               if ((_nd0) >= _maxdigits) { \
+                       memcpy((_temp), (_s0), _maxdigits); \
+                       if ((_nd) > (_nd0)) *_tp++ = '1'; \
+                       else { \
+                           const char *_q = (_s0) + _maxdigits; \
+                           int _n = (_nd0) - _maxdigits; \
+                           for(; _n > 0 && *_q == '0'; _n--, _q++) {} \
+                           *_tp++ = _n > 0 ? '1' : '0'; \
+                           } \
+                       (_nf) = -((_nd0) - (_maxdigits + 1)); \
+                       (_nd0) = _maxdigits + 1; \
+                       } \
+               else if ((_nd0) == 0) { \
+                       memcpy((_temp), (_s0), _maxdigits); \
+                       *_tp++ = '1'; \
+                       (_nf) -= ((_nd) - (_maxdigits + 1)); \
+                       } \
+               else { \
+                       memcpy((_temp), (_s0), _maxdigits + (_dplen)); \
+                       _tp += (_dplen); \
+                       *_tp++ = '1'; \
+                       (_nf) = (_maxdigits + 1) - (_nd0); \
+                       } \
+               *_tp = 0; \
+               (_nd) = _maxdigits + 1; \
+               (_s0) = (_temp); \
+               } \
+       }
+
 #endif /* GDTOAIMP_H_INCLUDED */