00001 00007 /* 00008 * Copyright 2004-2006 Intel Corporation 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); 00011 * you may not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, 00018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 */ 00022 /*- 00023 * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> 00024 * All rights reserved. 00025 * 00026 * Redistribution and use in source and binary forms, with or without 00027 * modification, are permitted provided that the following conditions 00028 * are met: 00029 * 1. Redistributions of source code must retain the above copyright 00030 * notice, this list of conditions and the following disclaimer. 00031 * 2. Redistributions in binary form must reproduce the above copyright 00032 * notice, this list of conditions and the following disclaimer in the 00033 * documentation and/or other materials provided with the distribution. 00034 * 00035 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 00036 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00037 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00038 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 00039 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00040 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00041 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00042 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00043 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00044 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00045 * SUCH DAMAGE. 00046 */ 00047 00048 // demmer: we need _GNU_SOURCE for linux systems to pull in fpclassify 00049 #define _GNU_SOURCE 00050 #include "compat/fpclassify.h" 00051 00052 #include <sys/cdefs.h> 00053 #define __FBSDID(x) 00054 __FBSDID("$FreeBSD: src/lib/libc/gdtoa/_ldtoa.c,v 1.2 2004/01/18 07:53:49 das Exp $"); 00055 00056 #include <float.h> 00057 #include <inttypes.h> 00058 #include <limits.h> 00059 #include <math.h> 00060 #include <stdlib.h> 00061 #include "fpmath.h" 00062 #include "gdtoaimp.h" 00063 00064 /* 00065 * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), 00066 * except that the floating point argument is passed by reference. 00067 * When dtoa() is passed a NaN or infinity, it sets expt to 9999. 00068 * However, a long double could have a valid exponent of 9999, so we 00069 * use INT_MAX in ldtoa() instead. 00070 */ 00071 char * 00072 __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, 00073 char **rve) 00074 { 00075 static FPI fpi = { 00076 LDBL_MANT_DIG, /* nbits */ 00077 LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ 00078 LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ 00079 FPI_Round_near, /* rounding */ 00080 #ifdef Sudden_Underflow /* unused, but correct anyway */ 00081 1 00082 #else 00083 0 00084 #endif 00085 }; 00086 int be, kind; 00087 char *ret; 00088 union IEEEl2bits u; 00089 uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; 00090 00091 u.e = *ld; 00092 *sign = u.bits.sign; 00093 be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); 00094 LDBL_TO_ARRAY32(u, bits); 00095 00096 switch (fpclassify(u.e)) { 00097 case FP_NORMAL: 00098 kind = STRTOG_Normal; 00099 #ifdef LDBL_IMPLICIT_NBIT 00100 bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); 00101 #endif /* LDBL_IMPLICIT_NBIT */ 00102 break; 00103 case FP_ZERO: 00104 kind = STRTOG_Zero; 00105 break; 00106 case FP_SUBNORMAL: 00107 kind = STRTOG_Denormal; 00108 #ifdef LDBL_IMPLICIT_NBIT 00109 be++; 00110 #endif 00111 break; 00112 case FP_INFINITE: 00113 kind = STRTOG_Infinite; 00114 break; 00115 case FP_NAN: 00116 kind = STRTOG_NaN; 00117 break; 00118 default: 00119 abort(); 00120 } 00121 00122 ret = gdtoa(&fpi, be, (ULong *)bits, &kind, mode, ndigits, decpt, rve); 00123 if (*decpt == -32768) 00124 *decpt = INT_MAX; 00125 return ret; 00126 }