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