fp_extend.h revision 303975
1292915Sdim//===-lib/fp_extend.h - low precision -> high precision conversion -*- C -*-===//
2292915Sdim//
3292915Sdim//                     The LLVM Compiler Infrastructure
4292915Sdim//
5292915Sdim// This file is dual licensed under the MIT and the University of Illinois Open
6292915Sdim// Source Licenses. See LICENSE.TXT for details.
7292915Sdim//
8292915Sdim//===----------------------------------------------------------------------===//
9292915Sdim//
10292915Sdim// Set source and destination setting
11292915Sdim//
12292915Sdim//===----------------------------------------------------------------------===//
13292915Sdim
14292915Sdim#ifndef FP_EXTEND_HEADER
15292915Sdim#define FP_EXTEND_HEADER
16292915Sdim
17292915Sdim#include "int_lib.h"
18292915Sdim
19292915Sdim#if defined SRC_SINGLE
20292915Sdimtypedef float src_t;
21292915Sdimtypedef uint32_t src_rep_t;
22292915Sdim#define SRC_REP_C UINT32_C
23292915Sdimstatic const int srcSigBits = 23;
24292915Sdim#define src_rep_t_clz __builtin_clz
25292915Sdim
26292915Sdim#elif defined SRC_DOUBLE
27292915Sdimtypedef double src_t;
28292915Sdimtypedef uint64_t src_rep_t;
29292915Sdim#define SRC_REP_C UINT64_C
30292915Sdimstatic const int srcSigBits = 52;
31292915Sdimstatic __inline int src_rep_t_clz(src_rep_t a) {
32292915Sdim#if defined __LP64__
33292915Sdim    return __builtin_clzl(a);
34292915Sdim#else
35292915Sdim    if (a & REP_C(0xffffffff00000000))
36292915Sdim        return __builtin_clz(a >> 32);
37292915Sdim    else
38292915Sdim        return 32 + __builtin_clz(a & REP_C(0xffffffff));
39292915Sdim#endif
40292915Sdim}
41292915Sdim
42292915Sdim#elif defined SRC_HALF
43292915Sdimtypedef uint16_t src_t;
44292915Sdimtypedef uint16_t src_rep_t;
45292915Sdim#define SRC_REP_C UINT16_C
46292915Sdimstatic const int srcSigBits = 10;
47292915Sdim#define src_rep_t_clz __builtin_clz
48292915Sdim
49292915Sdim#else
50292915Sdim#error Source should be half, single, or double precision!
51292915Sdim#endif //end source precision
52292915Sdim
53292915Sdim#if defined DST_SINGLE
54292915Sdimtypedef float dst_t;
55292915Sdimtypedef uint32_t dst_rep_t;
56292915Sdim#define DST_REP_C UINT32_C
57292915Sdimstatic const int dstSigBits = 23;
58292915Sdim
59292915Sdim#elif defined DST_DOUBLE
60292915Sdimtypedef double dst_t;
61292915Sdimtypedef uint64_t dst_rep_t;
62292915Sdim#define DST_REP_C UINT64_C
63292915Sdimstatic const int dstSigBits = 52;
64292915Sdim
65292915Sdim#elif defined DST_QUAD
66292915Sdimtypedef long double dst_t;
67292915Sdimtypedef __uint128_t dst_rep_t;
68292915Sdim#define DST_REP_C (__uint128_t)
69292915Sdimstatic const int dstSigBits = 112;
70292915Sdim
71292915Sdim#else
72292915Sdim#error Destination should be single, double, or quad precision!
73292915Sdim#endif //end destination precision
74292915Sdim
75292915Sdim// End of specialization parameters.  Two helper routines for conversion to and
76292915Sdim// from the representation of floating-point data as integer values follow.
77292915Sdim
78292915Sdimstatic __inline src_rep_t srcToRep(src_t x) {
79292915Sdim    const union { src_t f; src_rep_t i; } rep = {.f = x};
80292915Sdim    return rep.i;
81292915Sdim}
82292915Sdim
83292915Sdimstatic __inline dst_t dstFromRep(dst_rep_t x) {
84292915Sdim    const union { dst_t f; dst_rep_t i; } rep = {.i = x};
85292915Sdim    return rep.f;
86292915Sdim}
87292915Sdim// End helper routines.  Conversion implementation follows.
88292915Sdim
89292915Sdim#endif //FP_EXTEND_HEADER
90292915Sdim