1/* Manipulation of the bit representation of 'long double' quantities.
2   Copyright (C) 1999-2019 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   <http://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   four 32 bit ints or two 64 bit ints.  */
27
28#if __FLOAT_WORD_ORDER == __BIG_ENDIAN
29
30typedef union
31{
32  long double value;
33  struct
34  {
35    uint64_t msw;
36    uint64_t lsw;
37  } parts64;
38  struct
39  {
40    uint32_t w0, w1, w2, w3;
41  } parts32;
42} ieee854_long_double_shape_type;
43
44#endif
45
46#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
47
48typedef union
49{
50  long double value;
51  struct
52  {
53    uint64_t lsw;
54    uint64_t msw;
55  } parts64;
56  struct
57  {
58    uint32_t w3, w2, w1, w0;
59  } parts32;
60} ieee854_long_double_shape_type;
61
62#endif
63
64/* Get two 64 bit ints from a long double.  */
65
66#define GET_LDOUBLE_WORDS64(ix0,ix1,d)				\
67do {								\
68  ieee854_long_double_shape_type qw_u;				\
69  qw_u.value = (d);						\
70  (ix0) = qw_u.parts64.msw;					\
71  (ix1) = qw_u.parts64.lsw;					\
72} while (0)
73
74/* Set a long double from two 64 bit ints.  */
75
76#define SET_LDOUBLE_WORDS64(d,ix0,ix1)				\
77do {								\
78  ieee854_long_double_shape_type qw_u;				\
79  qw_u.parts64.msw = (ix0);					\
80  qw_u.parts64.lsw = (ix1);					\
81  (d) = qw_u.value;						\
82} while (0)
83
84/* Get the more significant 64 bits of a long double mantissa.  */
85
86#define GET_LDOUBLE_MSW64(v,d)					\
87do {								\
88  ieee854_long_double_shape_type sh_u;				\
89  sh_u.value = (d);						\
90  (v) = sh_u.parts64.msw;					\
91} while (0)
92
93/* Set the more significant 64 bits of a long double mantissa from an int.  */
94
95#define SET_LDOUBLE_MSW64(d,v)					\
96do {								\
97  ieee854_long_double_shape_type sh_u;				\
98  sh_u.value = (d);						\
99  sh_u.parts64.msw = (v);					\
100  (d) = sh_u.value;						\
101} while (0)
102
103/* Get the least significant 64 bits of a long double mantissa.  */
104
105#define GET_LDOUBLE_LSW64(v,d)					\
106do {								\
107  ieee854_long_double_shape_type sh_u;				\
108  sh_u.value = (d);						\
109  (v) = sh_u.parts64.lsw;					\
110} while (0)
111
112/*
113   On a platform already supporting a binary128 long double,
114   _Float128 will alias to long double.  This transformation
115   makes aliasing *l functions to *f128 trivial.
116*/
117#define _Float128 long double
118#define L(x) x##L
119
120#endif /* math_ldbl.h */
121