1/* GCC Quad-Precision Math Library
2   Copyright (C) 2010, 2011 Free Software Foundation, Inc.
3   Written by Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
4
5This file is part of the libquadmath library.
6Libquadmath is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11Libquadmath is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
17License along with libquadmath; see the file COPYING.LIB.  If
18not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19Boston, MA 02110-1301, USA.  */
20
21#ifndef QUADMATH_IMP_H
22#define QUADMATH_IMP_H
23
24#include <stdint.h>
25#include <stdlib.h>
26#include "quadmath.h"
27#include "config.h"
28
29
30/* Under IEEE 754, an architecture may determine tininess of
31   floating-point results either "before rounding" or "after
32   rounding", but must do so in the same way for all operations
33   returning binary results.  Define TININESS_AFTER_ROUNDING to 1 for
34   "after rounding" architectures, 0 for "before rounding"
35   architectures.  */
36
37#define TININESS_AFTER_ROUNDING   1
38
39
40/* Prototypes for internal functions.  */
41extern int32_t __quadmath_rem_pio2q (__float128, __float128 *);
42extern void __quadmath_kernel_sincosq (__float128, __float128, __float128 *,
43				       __float128 *, int);
44extern __float128 __quadmath_kernel_sinq (__float128, __float128, int);
45extern __float128 __quadmath_kernel_cosq (__float128, __float128);
46extern __float128 __quadmath_x2y2m1q (__float128 x, __float128 y);
47extern int __quadmath_isinf_nsq (__float128 x);
48
49
50
51
52
53/* Frankly, if you have __float128, you have 64-bit integers, right?  */
54#ifndef UINT64_C
55# error "No way!"
56#endif
57
58
59/* Main union type we use to manipulate the floating-point type.  */
60typedef union
61{
62  __float128 value;
63
64  struct
65#ifdef __MINGW32__
66  /* On mingw targets the ms-bitfields option is active by default.
67     Therefore enforce gnu-bitfield style.  */
68  __attribute__ ((gcc_struct))
69#endif
70  {
71#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
72    unsigned negative:1;
73    unsigned exponent:15;
74    uint64_t mant_high:48;
75    uint64_t mant_low:64;
76#else
77    uint64_t mant_low:64;
78    uint64_t mant_high:48;
79    unsigned exponent:15;
80    unsigned negative:1;
81#endif
82  } ieee;
83
84  struct
85  {
86#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
87    uint64_t high;
88    uint64_t low;
89#else
90    uint64_t low;
91    uint64_t high;
92#endif
93  } words64;
94
95  struct
96  {
97#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
98    uint32_t w0;
99    uint32_t w1;
100    uint32_t w2;
101    uint32_t w3;
102#else
103    uint32_t w3;
104    uint32_t w2;
105    uint32_t w1;
106    uint32_t w0;
107#endif
108  } words32;
109
110  struct
111#ifdef __MINGW32__
112  /* Make sure we are using gnu-style bitfield handling.  */
113  __attribute__ ((gcc_struct))
114#endif
115  {
116#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
117    unsigned negative:1;
118    unsigned exponent:15;
119    unsigned quiet_nan:1;
120    uint64_t mant_high:47;
121    uint64_t mant_low:64;
122#else
123    uint64_t mant_low:64;
124    uint64_t mant_high:47;
125    unsigned quiet_nan:1;
126    unsigned exponent:15;
127    unsigned negative:1;
128#endif
129  } nan;
130
131} ieee854_float128;
132
133
134/* Get two 64 bit ints from a long double.  */
135#define GET_FLT128_WORDS64(ix0,ix1,d)  \
136do {                                   \
137  ieee854_float128 u;                  \
138  u.value = (d);                       \
139  (ix0) = u.words64.high;              \
140  (ix1) = u.words64.low;               \
141} while (0)
142
143/* Set a long double from two 64 bit ints.  */
144#define SET_FLT128_WORDS64(d,ix0,ix1)  \
145do {                                   \
146  ieee854_float128 u;                  \
147  u.words64.high = (ix0);              \
148  u.words64.low = (ix1);               \
149  (d) = u.value;                       \
150} while (0)
151
152/* Get the more significant 64 bits of a long double mantissa.  */
153#define GET_FLT128_MSW64(v,d)          \
154do {                                   \
155  ieee854_float128 u;                  \
156  u.value = (d);                       \
157  (v) = u.words64.high;                \
158} while (0)
159
160/* Set the more significant 64 bits of a long double mantissa from an int.  */
161#define SET_FLT128_MSW64(d,v)          \
162do {                                   \
163  ieee854_float128 u;                  \
164  u.value = (d);                       \
165  u.words64.high = (v);                \
166  (d) = u.value;                       \
167} while (0)
168
169/* Get the least significant 64 bits of a long double mantissa.  */
170#define GET_FLT128_LSW64(v,d)          \
171do {                                   \
172  ieee854_float128 u;                  \
173  u.value = (d);                       \
174  (v) = u.words64.low;                 \
175} while (0)
176
177
178#define IEEE854_FLOAT128_BIAS 0x3fff
179
180#define QUADFP_NAN		0
181#define QUADFP_INFINITE		1
182#define QUADFP_ZERO		2
183#define QUADFP_SUBNORMAL	3
184#define QUADFP_NORMAL		4
185#define fpclassifyq(x) \
186  __builtin_fpclassify (QUADFP_NAN, QUADFP_INFINITE, QUADFP_NORMAL, \
187			QUADFP_SUBNORMAL, QUADFP_ZERO, x)
188
189#endif
190