extendsfdf2.c revision 37b97d1cf4501b94347e0b4e880f4b25825a289f
15c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon//===-- lib/extendsfdf2.c - single -> double conversion -----------*- C -*-===// 25c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// 35c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// The LLVM Compiler Infrastructure 45c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// 59ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant// This file is dual licensed under the MIT and the University of Illinois Open 69ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant// Source Licenses. See LICENSE.TXT for details. 75c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// 85c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon//===----------------------------------------------------------------------===// 95c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// 10e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// This file implements a fairly generic conversion from a narrower to a wider 115c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// IEEE-754 floating-point type. The constants and types defined following the 125c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// includes below parameterize the conversion. 13e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 14e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// This routine can be trivially adapted to support conversions from 15e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// half-precision or to quad-precision. It does not support types that don't 16e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// use the usual IEEE-754 interchange formats; specifically, some work would be 17e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// needed to adapt it to (for example) the Intel 80-bit format or PowerPC 18e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// double-double format. 19e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 20e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// Note please, however, that this implementation is only intended to support 21e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// *widening* operations; if you need to convert to a *narrower* floating-point 22e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// type (e.g. double -> float), then this routine will not do what you want it 23e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// to. 24e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 25e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// It also requires that integer types at least as large as both formats 26e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// are available on the target platform; this may pose a problem when trying 27e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// to add support for quad on some 32-bit systems, for example. You also may 28e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// run into trouble finding an appropriate CLZ function for wide source types; 29e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// you will likely need to roll your own on some platforms. 30e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 31e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// Finally, the following assumptions are made: 32e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 33e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 1. floating-point types and integer types have the same endianness on the 34e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// target platform 35e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 36e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// 2. quiet NaNs, if supported, are indicated by the leading bit of the 37e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// significand field being set 385c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon// 395c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon//===----------------------------------------------------------------------===// 40e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 415c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon#include <stdint.h> 425c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon#include <limits.h> 43e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 4437b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov#include "int_lib.h" 4537b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov 46e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canontypedef float src_t; 47e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canontypedef uint32_t src_rep_t; 48e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon#define SRC_REP_C UINT32_C 49e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canonstatic const int srcSigBits = 23; 50e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon#define src_rep_t_clz __builtin_clz 51e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 52e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canontypedef double dst_t; 53e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canontypedef uint64_t dst_rep_t; 54e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon#define DST_REP_C UINT64_C 55e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canonstatic const int dstSigBits = 52; 56e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 57e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// End of specialization parameters. Two helper routines for conversion to and 58e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// from the representation of floating-point data as integer values follow. 59e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 60e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canonstatic inline src_rep_t srcToRep(src_t x) { 61e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const union { src_t f; src_rep_t i; } rep = {.f = x}; 62e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon return rep.i; 63e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon} 64e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 65e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canonstatic inline dst_t dstFromRep(dst_rep_t x) { 66e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const union { dst_t f; dst_rep_t i; } rep = {.i = x}; 67e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon return rep.f; 68e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon} 69e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 70e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon// End helper routines. Conversion implementation follows. 71e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 7237b97d1cf4501b94347e0b4e880f4b25825a289fAnton KorobeynikovARM_EABI_FNALIAS(f2d, extendsfdf2); 7337b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov 745c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canondst_t __extendsfdf2(src_t a) { 75e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 76e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // Various constants whose values follow from the type parameters. 77e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // Any reasonable optimizer will fold and propagate all of these. 78e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int srcBits = sizeof(src_t)*CHAR_BIT; 79e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int srcExpBits = srcBits - srcSigBits - 1; 80e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int srcInfExp = (1 << srcExpBits) - 1; 81e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int srcExpBias = srcInfExp >> 1; 825c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon 83e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const src_rep_t srcMinNormal = SRC_REP_C(1) << srcSigBits; 84e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const src_rep_t srcInfinity = (src_rep_t)srcInfExp << srcSigBits; 85e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const src_rep_t srcSignMask = SRC_REP_C(1) << (srcSigBits + srcExpBits); 86e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const src_rep_t srcAbsMask = srcSignMask - 1; 87e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const src_rep_t srcQNaN = SRC_REP_C(1) << (srcSigBits - 1); 88e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const src_rep_t srcNaNCode = srcQNaN - 1; 895c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon 90e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int dstBits = sizeof(dst_t)*CHAR_BIT; 91e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int dstExpBits = dstBits - dstSigBits - 1; 92e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int dstInfExp = (1 << dstExpBits) - 1; 93e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int dstExpBias = dstInfExp >> 1; 945c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon 95e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const dst_rep_t dstMinNormal = DST_REP_C(1) << dstSigBits; 96e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 97e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // Break a into a sign and representation of the absolute value 985c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon const src_rep_t aRep = srcToRep(a); 995c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon const src_rep_t aAbs = aRep & srcAbsMask; 1005c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon const src_rep_t sign = aRep & srcSignMask; 101e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon dst_rep_t absResult; 102e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 103e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon if (aAbs - srcMinNormal < srcInfinity - srcMinNormal) { 104e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // a is a normal number. 105e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // Extend to the destination type by shifting the significand and 106e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // exponent into the proper position and rebiasing the exponent. 107e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult = (dst_rep_t)aAbs << (dstSigBits - srcSigBits); 108e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult += (dst_rep_t)(dstExpBias - srcExpBias) << dstSigBits; 109e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon } 110e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 111e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon else if (aAbs >= srcInfinity) { 112e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // a is NaN or infinity. 113e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // Conjure the result by beginning with infinity, then setting the qNaN 1145c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon // bit (if needed) and right-aligning the rest of the trailing NaN 1155c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon // payload field. 116e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult = (dst_rep_t)dstInfExp << dstSigBits; 117e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult |= (dst_rep_t)(aAbs & srcQNaN) << (dstSigBits - srcSigBits); 1185c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon absResult |= aAbs & srcNaNCode; 119e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon } 120e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 121e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon else if (aAbs) { 122e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // a is denormal. 123e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // renormalize the significand and clear the leading bit, then insert 124e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // the correct adjusted exponent in the destination type. 125e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int scale = src_rep_t_clz(aAbs) - src_rep_t_clz(srcMinNormal); 126e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult = (dst_rep_t)aAbs << (dstSigBits - srcSigBits + scale); 127e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult ^= dstMinNormal; 128e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon const int resultExponent = dstExpBias - srcExpBias - scale + 1; 129e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult |= (dst_rep_t)resultExponent << dstSigBits; 130e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon } 131e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 132e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon else { 133e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // a is zero. 134e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon absResult = 0; 135e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon } 136e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon 137e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon // Apply the signbit to (dst_t)abs(a). 1385c6d2ecb9c43d8b836b3203a243e24703d473765Stephen Canon const dst_rep_t result = absResult | (dst_rep_t)sign << (dstBits - srcBits); 139e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon return dstFromRep(result); 140e5086322295e5a345af02d09abfcf8ddca2d0897Stephen Canon} 141