1174684Sdas/*- 2174684Sdas * Copyright (c) 2007 David Schultz 3174684Sdas * All rights reserved. 4174684Sdas * 5174684Sdas * Redistribution and use in source and binary forms, with or without 6174684Sdas * modification, are permitted provided that the following conditions 7174684Sdas * are met: 8174684Sdas * 1. Redistributions of source code must retain the above copyright 9174684Sdas * notice, this list of conditions and the following disclaimer. 10174684Sdas * 2. Redistributions in binary form must reproduce the above copyright 11174684Sdas * notice, this list of conditions and the following disclaimer in the 12174684Sdas * documentation and/or other materials provided with the distribution. 13174684Sdas * 14174684Sdas * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15174684Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16174684Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17174684Sdas * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18174684Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19174684Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20174684Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21174684Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22174684Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23174684Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24174684Sdas * SUCH DAMAGE. 25174684Sdas * 26174684Sdas * $FreeBSD$ 27174684Sdas */ 28174684Sdas 29174759Sdas#include <sys/endian.h> 30174759Sdas#include <ctype.h> 31174684Sdas#include <float.h> 32174684Sdas#include <math.h> 33174759Sdas#include <stdint.h> 34174759Sdas#include <strings.h> 35174684Sdas 36174684Sdas#include "math_private.h" 37174684Sdas 38174759Sdas/* 39174759Sdas * Scan a string of hexadecimal digits (the format nan(3) expects) and 40174759Sdas * make a bit array (using the local endianness). We stop when we 41174759Sdas * encounter an invalid character, NUL, etc. If we overflow, we do 42174759Sdas * the same as gcc's __builtin_nan(), namely, discard the high order bits. 43174759Sdas * 44174759Sdas * The format this routine accepts needs to be compatible with what is used 45174759Sdas * in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in 46174759Sdas * __builtin_nan(). In fact, we're only 100% compatible for strings we 47174759Sdas * consider valid, so we might be violating the C standard. But it's 48174759Sdas * impossible to use nan(3) portably anyway, so this seems good enough. 49174759Sdas */ 50174759Sdasvoid 51174759Sdas_scan_nan(uint32_t *words, int num_words, const char *s) 52174759Sdas{ 53174759Sdas int si; /* index into s */ 54174759Sdas int bitpos; /* index into words (in bits) */ 55174759Sdas 56174759Sdas bzero(words, num_words * sizeof(uint32_t)); 57174759Sdas 58174759Sdas /* Allow a leading '0x'. (It's expected, but redundant.) */ 59174759Sdas if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) 60174759Sdas s += 2; 61174759Sdas 62174759Sdas /* Scan forwards in the string, looking for the end of the sequence. */ 63174759Sdas for (si = 0; isxdigit(s[si]); si++) 64174759Sdas ; 65174759Sdas 66174759Sdas /* Scan backwards, filling in the bits in words[] as we go. */ 67174759Sdas#if _BYTE_ORDER == _LITTLE_ENDIAN 68174759Sdas for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) { 69174759Sdas#else 70174759Sdas for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) { 71174759Sdas#endif 72174759Sdas if (--si < 0) 73174759Sdas break; 74174759Sdas words[bitpos / 32] |= digittoint(s[si]) << (bitpos % 32); 75174759Sdas } 76174759Sdas} 77174759Sdas 78174684Sdasdouble 79174684Sdasnan(const char *s) 80174684Sdas{ 81174759Sdas union { 82174759Sdas double d; 83174759Sdas uint32_t bits[2]; 84174759Sdas } u; 85174684Sdas 86174759Sdas _scan_nan(u.bits, 2, s); 87174759Sdas#if _BYTE_ORDER == _LITTLE_ENDIAN 88174759Sdas u.bits[1] |= 0x7ff80000; 89174759Sdas#else 90174759Sdas u.bits[0] |= 0x7ff80000; 91174759Sdas#endif 92174759Sdas return (u.d); 93174684Sdas} 94174684Sdas 95174684Sdasfloat 96174684Sdasnanf(const char *s) 97174684Sdas{ 98174759Sdas union { 99174759Sdas float f; 100174759Sdas uint32_t bits[1]; 101174759Sdas } u; 102174684Sdas 103174759Sdas _scan_nan(u.bits, 1, s); 104174759Sdas u.bits[0] |= 0x7fc00000; 105174759Sdas return (u.f); 106174684Sdas} 107174684Sdas 108174684Sdas#if (LDBL_MANT_DIG == 53) 109174684Sdas__weak_reference(nan, nanl); 110174684Sdas#endif 111