summaryrefslogtreecommitdiff
path: root/src/internal/longdbl.h
blob: 25ec8021b692e83ed222f2ce2f1dbd95bfa602ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#ifndef _LDHACK_H
#define _LDHACK_H

#include <float.h>
#include <stdint.h>

#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
union ldshape {
	long double value;
	struct {
		uint64_t m;
		uint16_t exp:15;
		uint16_t sign:1;
		uint16_t pad;
	} bits;
};
#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
union ldshape {
	long double value;
	struct {
		uint64_t mlo;
		uint64_t mhi:48;
		uint16_t exp:15;
		uint16_t sign:1;
	} bits;
};
#else
#error Unsupported long double representation
#endif


// FIXME: hacks to make freebsd+openbsd long double code happy

// union and macros for freebsd

#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384

union IEEEl2bits {
	long double e;
	struct {
		uint32_t manl:32;
		uint32_t manh:32;
		uint32_t exp:15;
		uint32_t sign:1;
		uint32_t pad:16;
	} bits;
	struct {
		uint64_t man:64;
		uint32_t expsign:16;
		uint32_t pad:16;
	} xbits;
};

#define LDBL_MANL_SIZE 32
#define LDBL_MANH_SIZE 32
#define LDBL_NBIT (1ull << LDBL_MANH_SIZE-1)
#undef LDBL_IMPLICIT_NBIT
#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)

#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
/*
// ld128 float.h
//#define LDBL_MAX 1.189731495357231765085759326628007016E+4932L
#define LDBL_MAX 0x1.ffffffffffffffffffffffffffffp+16383
#define LDBL_MAX_EXP 16384
#define LDBL_HAS_INFINITY 1
//#define LDBL_MIN 3.362103143112093506262677817321752603E-4932L
#define LDBL_MIN 0x1p-16382
#define LDBL_HAS_QUIET_NAN 1
#define LDBL_HAS_DENORM 1
//#define LDBL_EPSILON 1.925929944387235853055977942584927319E-34L
#define LDBL_EPSILON 0x1p-112
#define LDBL_MANT_DIG 113
#define LDBL_MIN_EXP (-16381)
#define LDBL_MAX_10_EXP 4932
#define LDBL_DENORM_MIN 0x0.0000000000000000000000000001p-16381
#define LDBL_MIN_10_EXP (-4931)
#define LDBL_DIG 33
*/

union IEEEl2bits {
	long double e;
	struct {
		uint64_t manl:64;
		uint64_t manh:48;
		uint32_t exp:15;
		uint32_t sign:1;
	} bits;
	struct {
		uint64_t unused0:64;
		uint64_t unused1:48;
		uint32_t expsign:16;
	} xbits;
};

#define LDBL_MANL_SIZE 64
#define LDBL_MANH_SIZE 48
#define LDBL_NBIT (1ull << LDBL_MANH_SIZE)
#define LDBL_IMPLICIT_NBIT 1
#define mask_nbit_l(u)

#endif


// macros for openbsd

#define GET_LDOUBLE_WORDS(se,mh,ml, f) do{ \
	union IEEEl2bits u; \
	u.e = (f); \
	(se) = u.xbits.expsign; \
	(mh) = u.bits.manh; \
	(ml) = u.bits.manl; \
}while(0)

#define SET_LDOUBLE_WORDS(f,  se,mh,ml) do{ \
	union IEEEl2bits u; \
	u.xbits.expsign = (se); \
	u.bits.manh = (mh); \
	u.bits.manl = (ml); \
	(f) = u.e; \
}while(0)

#define GET_LDOUBLE_EXP(se, f) do{ \
	union IEEEl2bits u; \
	u.e = (f); \
	(se) = u.xbits.expsign; \
}while(0)

#define SET_LDOUBLE_EXP(f, se) do{ \
	union IEEEl2bits u; \
	u.e = (f); \
	u.xbits.expsign = (se); \
	(f) = u.e; \
}while(0)

#endif