Home | History | Annotate | Download | only in gdtoa
      1 /*	$OpenBSD: ldtoa.c,v 1.1 2008/09/07 20:36:08 martynas Exp $	*/
      2 /*-
      3  * Copyright (c) 2003 David Schultz <das (at) FreeBSD.ORG>
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/types.h>
     29 #ifndef __vax__
     30 #include <machine/ieee.h>
     31 #endif /* !__vax__ */
     32 #include <float.h>
     33 #include <inttypes.h>
     34 #include <limits.h>
     35 #include <math.h>
     36 #include <stdlib.h>
     37 #include "gdtoaimp.h"
     38 
     39 #if (LDBL_MANT_DIG > DBL_MANT_DIG)
     40 
     41 /*
     42  * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(),
     43  * except that the floating point argument is passed by reference.
     44  * When dtoa() is passed a NaN or infinity, it sets expt to 9999.
     45  * However, a long double could have a valid exponent of 9999, so we
     46  * use INT_MAX in ldtoa() instead.
     47  */
     48 char *
     49 __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
     50     char **rve)
     51 {
     52 	FPI fpi = {
     53 		LDBL_MANT_DIG,			/* nbits */
     54 		LDBL_MIN_EXP - LDBL_MANT_DIG,	/* emin */
     55 		LDBL_MAX_EXP - LDBL_MANT_DIG,	/* emax */
     56 		FLT_ROUNDS,	       		/* rounding */
     57 #ifdef Sudden_Underflow	/* unused, but correct anyway */
     58 		1
     59 #else
     60 		0
     61 #endif
     62 	};
     63 	int be, kind;
     64 	char *ret;
     65 	struct ieee_ext *p = (struct ieee_ext *)ld;
     66 	uint32_t bits[(LDBL_MANT_DIG + 31) / 32];
     67 	void *vbits = bits;
     68 
     69 	/*
     70 	 * gdtoa doesn't know anything about the sign of the number, so
     71 	 * if the number is negative, we need to swap rounding modes of
     72 	 * 2 (upwards) and 3 (downwards).
     73 	 */
     74 	*sign = p->ext_sign;
     75 	fpi.rounding ^= (fpi.rounding >> 1) & p->ext_sign;
     76 
     77 	be = p->ext_exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1);
     78 	EXT_TO_ARRAY32(p, bits);
     79 
     80 	switch (fpclassify(*ld)) {
     81 	case FP_NORMAL:
     82 		kind = STRTOG_Normal;
     83 #ifdef EXT_IMPLICIT_NBIT
     84 		bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
     85 #endif /* EXT_IMPLICIT_NBIT */
     86 		break;
     87 	case FP_ZERO:
     88 		kind = STRTOG_Zero;
     89 		break;
     90 	case FP_SUBNORMAL:
     91 		kind = STRTOG_Denormal;
     92 		be++;
     93 		break;
     94 	case FP_INFINITE:
     95 		kind = STRTOG_Infinite;
     96 		break;
     97 	case FP_NAN:
     98 		kind = STRTOG_NaN;
     99 		break;
    100 	default:
    101 		abort();
    102 	}
    103 
    104 	ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve);
    105 	if (*decpt == -32768)
    106 		*decpt = INT_MAX;
    107 	return ret;
    108 }
    109 
    110 #else   /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
    111 
    112 char *
    113 __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
    114     char **rve)
    115 {
    116 	char *ret;
    117 
    118 	ret = dtoa((double)*ld, mode, ndigits, decpt, sign, rve);
    119 	if (*decpt == 9999)
    120 		*decpt = INT_MAX;
    121 	return ret;
    122 }
    123 
    124 #endif  /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
    125