1 /* Manipulation of the bit representation of 'long double' quantities.
2    Copyright (C) 2000-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #ifndef _MATH_LDBL_H_
20 #define _MATH_LDBL_H_ 1
21 
22 #include <stdint.h>
23 #include <endian.h>
24 
25 /* A union which permits us to convert between a long double and
26    three 32 bit ints.  */
27 
28 #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
29 
30 typedef union
31 {
32   long double value;
33   struct
34   {
35     unsigned int empty0:32;
36     int sign_exponent:16;
37     unsigned int empty1:16;
38     uint32_t msw;
39     uint32_t lsw;
40   } parts;
41 } ieee_long_double_shape_type;
42 
43 #endif
44 
45 #if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
46 
47 typedef union
48 {
49   long double value;
50   struct
51   {
52     uint32_t lsw;
53     uint32_t msw;
54     int sign_exponent:16;
55     unsigned int empty1:16;
56     unsigned int empty0:32;
57   } parts;
58 } ieee_long_double_shape_type;
59 
60 #endif
61 
62 /* Get three 32 bit ints from a double.  */
63 
64 #define GET_LDOUBLE_WORDS(exp,ix0,ix1,d)			\
65 do {								\
66   ieee_long_double_shape_type ew_u;				\
67   ew_u.value = (d);						\
68   (exp) = ew_u.parts.sign_exponent;				\
69   (ix0) = ew_u.parts.msw;					\
70   (ix1) = ew_u.parts.lsw;					\
71 } while (0)
72 
73 /* Set a double from two 32 bit ints.  */
74 
75 #define SET_LDOUBLE_WORDS(d,exp,ix0,ix1)			\
76 do {								\
77   ieee_long_double_shape_type iw_u;				\
78   iw_u.parts.sign_exponent = (exp);				\
79   iw_u.parts.msw = (ix0);					\
80   iw_u.parts.lsw = (ix1);					\
81   (d) = iw_u.value;						\
82 } while (0)
83 
84 /* Get the more significant 32 bits of a long double mantissa.  */
85 
86 #define GET_LDOUBLE_MSW(v,d)					\
87 do {								\
88   ieee_long_double_shape_type sh_u;				\
89   sh_u.value = (d);						\
90   (v) = sh_u.parts.msw;						\
91 } while (0)
92 
93 /* Set the more significant 32 bits of a long double mantissa from an int.  */
94 
95 #define SET_LDOUBLE_MSW(d,v)					\
96 do {								\
97   ieee_long_double_shape_type sh_u;				\
98   sh_u.value = (d);						\
99   sh_u.parts.msw = (v);						\
100   (d) = sh_u.value;						\
101 } while (0)
102 
103 /* Get int from the exponent of a long double.  */
104 
105 #define GET_LDOUBLE_EXP(exp,d)					\
106 do {								\
107   ieee_long_double_shape_type ge_u;				\
108   ge_u.value = (d);						\
109   (exp) = ge_u.parts.sign_exponent;				\
110 } while (0)
111 
112 /* Set exponent of a long double from an int.  */
113 
114 #define SET_LDOUBLE_EXP(d,exp)					\
115 do {								\
116   ieee_long_double_shape_type se_u;				\
117   se_u.value = (d);						\
118   se_u.parts.sign_exponent = (exp);				\
119   (d) = se_u.value;						\
120 } while (0)
121 
122 #endif /* math_ldbl.h */
123