1102227Smike/* $OpenBSD: ldtoa.c,v 1.4 2016/03/09 16:28:47 deraadt Exp $ */ 2102227Smike/*- 3102227Smike * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> 4102227Smike * All rights reserved. 5102227Smike * 6102227Smike * Redistribution and use in source and binary forms, with or without 7102227Smike * modification, are permitted provided that the following conditions 8102227Smike * are met: 9102227Smike * 1. Redistributions of source code must retain the above copyright 10102227Smike * notice, this list of conditions and the following disclaimer. 11102227Smike * 2. Redistributions in binary form must reproduce the above copyright 12102227Smike * notice, this list of conditions and the following disclaimer in the 13102227Smike * documentation and/or other materials provided with the distribution. 14102227Smike * 15102227Smike * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16102227Smike * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17102227Smike * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18102227Smike * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19102227Smike * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20102227Smike * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21102227Smike * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22102227Smike * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23102227Smike * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24102227Smike * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25102227Smike * SUCH DAMAGE. 26102227Smike */ 27102227Smike 28102227Smike#include <sys/types.h> 29102227Smike#include <machine/ieee.h> 30102227Smike#include <float.h> 31102227Smike#include <stdint.h> 32102227Smike#include <limits.h> 33102227Smike#include <math.h> 34102227Smike#include <stdlib.h> 35102227Smike#include "gdtoaimp.h" 36102227Smike 37102227Smike#if (LDBL_MANT_DIG > DBL_MANT_DIG) 38102227Smike 39102227Smike/* 40102227Smike * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), 41102227Smike * except that the floating point argument is passed by reference. 42143063Sjoerg * When dtoa() is passed a NaN or infinity, it sets expt to 9999. 43143063Sjoerg * However, a long double could have a valid exponent of 9999, so we 44143063Sjoerg * use INT_MAX in ldtoa() instead. 45143063Sjoerg */ 46147744Sthompsachar * 47147744Sthompsa__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, 48102227Smike char **rve) 49102227Smike{ 50102227Smike FPI fpi = { 51228469Sed LDBL_MANT_DIG, /* nbits */ 52102227Smike LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ 53102227Smike LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ 54102227Smike FLT_ROUNDS, /* rounding */ 55102227Smike#ifdef Sudden_Underflow /* unused, but correct anyway */ 56102227Smike 1 57235939Sobrien#else 58102227Smike 0 59102227Smike#endif 60232261Stijl }; 61232261Stijl int be, kind; 62232261Stijl char *ret; 63232261Stijl struct ieee_ext *p = (struct ieee_ext *)ld; 64232261Stijl uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; 65232261Stijl void *vbits = bits; 66232261Stijl 67232261Stijl /* 68232261Stijl * gdtoa doesn't know anything about the sign of the number, so 69232261Stijl * if the number is negative, we need to swap rounding modes of 70232261Stijl * 2 (upwards) and 3 (downwards). 71232261Stijl */ 72102227Smike *sign = p->ext_sign; 73102227Smike fpi.rounding ^= (fpi.rounding >> 1) & p->ext_sign; 74102227Smike 75102227Smike be = p->ext_exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); 76235939Sobrien EXT_TO_ARRAY32(p, bits); 77102227Smike 78102227Smike switch (fpclassify(*ld)) { 79114349Speter case FP_NORMAL: 80175398Sbde kind = STRTOG_Normal; 81102227Smike#ifdef EXT_IMPLICIT_NBIT 82232261Stijl bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); 83232261Stijl#endif /* EXT_IMPLICIT_NBIT */ 84232261Stijl break; 85232261Stijl case FP_ZERO: 86232261Stijl kind = STRTOG_Zero; 87232261Stijl break; 88232261Stijl case FP_SUBNORMAL: 89232261Stijl kind = STRTOG_Denormal; 90232261Stijl be++; 91102227Smike break; 92102227Smike case FP_INFINITE: 93102227Smike kind = STRTOG_Infinite; 94102227Smike break; 95102227Smike case FP_NAN: 96102227Smike kind = STRTOG_NaN; 97102227Smike break; 98102227Smike default: 99102227Smike abort(); 100235939Sobrien } 101102227Smike 102102227Smike ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); 103102227Smike if (*decpt == -32768) 104102227Smike *decpt = INT_MAX; 105102227Smike return ret; 106114349Speter} 107102227SmikeDEF_STRONG(__ldtoa); 108232261Stijl 109232261Stijl#else /* (LDBL_MANT_DIG == DBL_MANT_DIG) */ 110232261Stijl 111232261Stijlchar * 112232261Stijl__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, 113232261Stijl char **rve) 114232261Stijl{ 115232261Stijl char *ret; 116232261Stijl 117232261Stijl ret = dtoa((double)*ld, mode, ndigits, decpt, sign, rve); 118232261Stijl if (*decpt == 9999) 119102227Smike *decpt = INT_MAX; 120102227Smike return ret; 121102227Smike} 122102227SmikeDEF_STRONG(__ldtoa); 123102227Smike 124102227Smike#endif /* (LDBL_MANT_DIG == DBL_MANT_DIG) */ 125102227Smike