File: streflop_libm_bridge.h

package info (click to toggle)
spring 103.0%2Bdfsg2-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 43,720 kB
  • ctags: 63,685
  • sloc: cpp: 368,283; ansic: 33,988; python: 12,417; java: 12,203; awk: 5,879; sh: 1,846; xml: 655; perl: 405; php: 211; objc: 194; makefile: 77; sed: 2
file content (438 lines) | stat: -rw-r--r-- 14,521 bytes parent folder | download | duplicates (9)
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/*
    This file acts as a bridge between the libm files and streflop.
    It replaces the missing type definitions and macros that were defined
    by the external files that were included by the libm, so it is now
    standalone.

    In addition, this allows to wrap the basic types for compiling
    the libm, ex, with SoftFloat.

    This file is NOT included by the streflop main files, and thus NOT
    included by the user programs.
    It is included by the libm converted files to produce the streflop binary,
    that will be linked by the user program instead of the system libm.

    Nicolas Brodu, 2006
    Code released according to the GNU Lesser General Public License
*/

#ifndef STREFLOP_LIBM_BRIDGE
#define STREFLOP_LIBM_BRIDGE

// prevent inclusion of the main Math.h file
// => the function symbol are not defined when compiling libm
// => this adds a level of protection, a function inadvertantly using a wrong precision function is detected
#define STREFLOP_MATH_H

// First define our custom types
#include "../streflop.h"

// Export type definitions, etc.
using namespace streflop;

// for int32_t, etc. Assume WORDSIZE is defined by the Makefile.common
#include "../System.h"
#undef  __USE_ISOC99
#undef  __USE_POSIX
#undef  __USE_POSIX2
#undef  __USE_POSIX199309
#undef  __USE_POSIX199506
#undef  __USE_XOPEN
#undef  __USE_XOPEN_EXTENDED
#undef  __USE_UNIX98
#undef  __USE_XOPEN2K
#undef  __USE_LARGEFILE
#undef  __USE_LARGEFILE64
#undef  __USE_FILE_OFFSET64
#undef  __USE_BSD
#undef  __USE_SVID
#undef  __USE_MISC
#undef  __USE_GNU
#undef  __USE_REENTRANT
#undef  __USE_FORTIFY_LEVEL
#undef  __FAVOR_BSD
#undef  __KERNEL_STRICT_NAMES

#undef weak_alias
#undef strong_alias
#undef hidden_def
#undef libm_hidden_def
#undef INTDEF
#define weak_alias(x,y)
#define strong_alias(x,y)
#define hidden_def(x)
#define libm_hidden_def(x)
#define INTDEF(x)
#define __set_errno(x) do {} while (0)

#define _IEEE_LIBM 1

// u_int32_t is not C99 compliant
typedef streflop::uint32_t u_int32_t;

/////////////////////////////////////////////////////////////////////////////
// Common definitions
/////////////////////////////////////////////////////////////////////////////

// <float.h> is not included, define only these constants that are needed to compile libm
#define FLT_MIN_EXP (-128)
#define FLT_MAX_EXP 127
#define FLT_MANT_DIG 24
#define DBL_MIN_EXP (-1024)
#define DBL_MAX_EXP 1023
#define DBL_MANT_DIG 53
#define LDBL_MANT_DIG 64

#define HUGE_VALF SimplePositiveInfinity
#define HUGE_VAL DoublePositiveInfinity
#define HUGE_VALL ExtendedPositiveInfinity

#define INT_MAX ((-1)>>1)

// Stolen from bits/mathdef.h
#define FP_ILOGB0      (-2147483647)
#define FP_ILOGBNAN    2147483647

namespace streflop_libm {

// No template, only allow this for int types (could use traits, but it's simpler this way)
inline char abs(char x) {return x < 0 ? -x : x;}
inline short abs(short x) {return x < 0 ? -x : x;}
inline int abs(int x) {return x < 0 ? -x : x;}
inline long abs(long x) {return x < 0 ? -x : x;}
inline long long abs(long long x) {return x < 0 ? -x : x;}

inline char MIN(char x, char y) {return x<y ? x : y;}
inline short MIN(short x, short y) {return x<y ? x : y;}
inline int MIN(int x, int y) {return x<y ? x : y;}
inline long MIN(long x, long y) {return x<y ? x : y;}
inline long long MIN(long long x, long long y) {return x<y ? x : y;}


// Compensate lack of Math.h
enum
{
    FP_NAN = 0,
    FP_INFINITE = 1,
    FP_ZERO = 2,
    FP_SUBNORMAL = 3,
    FP_NORMAL = 4
};

#ifdef LIBM_COMPILING_FLT32
    extern int __fpclassifyf(Simple x);
    extern int __isnanf(Simple x);
    extern int __isinff(Simple x);
    inline int fpclassify(Simple x) {return streflop_libm::__fpclassifyf(x);}
    inline int isnan(Simple x) {return streflop_libm::__isnanf(x);}
    inline int isinf(Simple x) {return streflop_libm::__isinff(x);}
    inline int isfinite(Simple x) {return !(isnan(x) || isinf(x));}
    inline int isnormal(Simple x) {return fpclassify(x) == FP_NORMAL;}
    inline bool isunordered(Simple x, Simple y) {
        return (fpclassify(x) == FP_NAN) || (fpclassify (y) == FP_NAN);
    }
    inline bool isgreater(Simple x, Simple y) {
        return (!isunordered(x,y)) && (x > y);
    }
    inline bool isgreaterequal(Simple x, Simple y) {
        return (!isunordered(x,y)) && (x >= y);
    }
    inline bool isless(Simple x, Simple y) {
        return (!isunordered(x,y)) && (x < y);
    }
    inline bool islessequal(Simple x, Simple y) {
        return (!isunordered(x,y)) && (x <= y);
    }
    inline bool islessgreater(Simple x, Simple y) {
        return (!isunordered(x,y)) && ((x < y) || (x > y));
    }
    extern const Simple SimplePositiveInfinity;
    extern const Simple SimpleNegativeInfinity;
    extern const Simple SimpleNaN;
#endif

#ifdef LIBM_COMPILING_DBL64
    extern int __fpclassify(Double x);
    extern int __isnanl(Double x);
    extern int __isinf(Double x);
    inline int fpclassify(Double x) {return streflop_libm::__fpclassify(x);}
    inline int isnan(Double x) {return streflop_libm::__isnanl(x);}
    inline int isinf(Double x) {return streflop_libm::__isinf(x);}
    inline int isfinite(Double x) {return !(isnan(x) || isinf(x));}
    inline int isnormal(Double x) {return fpclassify(x) == FP_NORMAL;}
    inline bool isunordered(Double x, Double y) {
        return (fpclassify(x) == FP_NAN) || (fpclassify (y) == FP_NAN);
    }
    inline bool isgreater(Double x, Double y) {
        return (!isunordered(x,y)) && (x > y);
    }
    inline bool isgreaterequal(Double x, Double y) {
        return (!isunordered(x,y)) && (x >= y);
    }
    inline bool isless(Double x, Double y) {
        return (!isunordered(x,y)) && (x < y);
    }
    inline bool islessequal(Double x, Double y) {
        return (!isunordered(x,y)) && (x <= y);
    }
    inline bool islessgreater(Double x, Double y) {
        return (!isunordered(x,y)) && ((x < y) || (x > y));
    }
    extern const Double DoublePositiveInfinity;
    extern const Double DoubleNegativeInfinity;
    extern const Double DoubleNaN;
#endif

#ifdef LIBM_COMPILING_LDBL96
#ifdef Extended
    extern int __fpclassifyl(Extended x);
    extern int __isnanl(Extended x);
    extern int __isinfl(Extended x);
    inline int fpclassify(Extended x) {return streflop_libm::__fpclassifyl(x);}
    inline int isnan(Extended x) {return streflop_libm::__isnanl(x);}
    inline int isinf(Extended x) {return streflop_libm::__isinfl(x);}
    inline int isfinite(Extended x) {return !(isnan(x) || isinf(x));}
    inline int isnormal(Extended x) {return fpclassify(x) == FP_NORMAL;}
    inline bool isunordered(Extended x, Extended y) {
        return (fpclassify(x) == FP_NAN) || (fpclassify (y) == FP_NAN);
    }
    inline bool isgreater(Extended x, Extended y) {
        return (!isunordered(x,y)) && (x > y);
    }
    inline bool isgreaterequal(Extended x, Extended y) {
        return (!isunordered(x,y)) && (x >= y);
    }
    inline bool isless(Extended x, Extended y) {
        return (!isunordered(x,y)) && (x < y);
    }
    inline bool islessequal(Extended x, Extended y) {
        return (!isunordered(x,y)) && (x <= y);
    }
    inline bool islessgreater(Extended x, Extended y) {
        return (!isunordered(x,y)) && ((x < y) || (x > y));
    }
    extern const Extended ExtendedPositiveInfinity;
    extern const Extended ExtendedNegativeInfinity;
    extern const Extended ExtendedNaN;
#endif
#endif


}


// eval method is 0 for x87, sse, soft, that is float_t has size float and double_t has size double
#define FLT_EVAL_METHOD 0



// Endianity checking
#if __FLOAT_WORD_ORDER == 1234
#define LOW_WORD_IDX 0
#define HIGH_WORD_IDX 1
#elif __FLOAT_WORD_ORDER == 4321
#define LOW_WORD_IDX 1
#define HIGH_WORD_IDX 0
#else
#error unknown byte order
#endif


#ifdef Extended

// little endian
#if __FLOAT_WORD_ORDER == 1234

/// Little endian is fine, always the same offsets whatever the memory model
template<int N> struct ExtendedConverter {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(reinterpret_cast<char*>(e)+8);
    }
    // Mantissa
    static inline SizedUnsignedInteger<32>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<32>::Type*>(e);
    }
};

// Big endian
#elif __FLOAT_WORD_ORDER == 4321
/// Extended is softfloat
template<> struct ExtendedConverter<10> {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(e);
    }
    // Mantissa
    static inline SizedUnsignedInteger<32>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<32>::Type*>(reinterpret_cast<char*>(e)+2);
    }
};

/// Default gcc model for x87 - 32 bits (or with -m96bit-long-double)
template<> struct ExtendedConverter<12> {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(reinterpret_cast<char*>(e)+2);
    }
    // Mantissa
    static inline SizedUnsignedInteger<32>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<32>::Type*>(reinterpret_cast<char*>(e)+4);
    }
};

/// Default gcc model for x87 - 64 bits (or with -m128bit-long-double)
template<> struct ExtendedConverter<16> {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(reinterpret_cast<char*>(e)+6);
    }
    // Mantissa
    static inline SizedUnsignedInteger<32>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<32>::Type*>(reinterpret_cast<char*>(e)+8);
    }
};
#else
#error unknown byte order
#endif

#endif


// Simple
#ifdef LIBM_COMPILING_FLT32

// SSE is best case, always plain types
// X87 uses a wrapper for no denormals case
// First member of struct guaranted aligned at mem location => OK
// Idem for SoftFloat wrapper, though endianity has to be checked explicitly
#define SIMPLE_FROM_INT_PTR(x) *reinterpret_cast<Simple*>(x)
#define CONST_SIMPLE_FROM_INT_PTR(x) *reinterpret_cast<const Simple*>(x)


#define GET_FLOAT_WORD(i,d)                                     \
do {                                                            \
  Simple f = (d);                                               \
  (i) = *reinterpret_cast<streflop::uint32_t*>(&f);                            \
} while (0)


/* Set a float from a 32 bit int.  */
#define SET_FLOAT_WORD(d,i)                                     \
do {                                                            \
    int ii = (i);                                               \
    (d) = *reinterpret_cast<Simple*>(&ii);                      \
} while (0)

#endif

// Double

#ifdef LIBM_COMPILING_DBL64

#define DOUBLE_FROM_INT_PTR(x) *reinterpret_cast<Double*>(x)
#define CONST_DOUBLE_FROM_INT_PTR(x) *reinterpret_cast<const Double*>(x)

#define EXTRACT_WORDS(ix0,ix1,d)            \
do {                                        \
  Double f = (d);                           \
  (ix0) = reinterpret_cast<streflop::uint32_t*>(&f)[HIGH_WORD_IDX];  \
  (ix1) = reinterpret_cast<streflop::uint32_t*>(&f)[LOW_WORD_IDX];      \
} while (0)

#define GET_HIGH_WORD(i,d)          \
do {                                \
  Double f = (d);                           \
  (i) = reinterpret_cast<streflop::uint32_t*>(&f)[HIGH_WORD_IDX];  \
} while (0)

#define GET_LOW_WORD(i,d)           \
do {                                \
  Double f = (d);                           \
  (i) = reinterpret_cast<streflop::uint32_t*>(&f)[LOW_WORD_IDX];      \
} while (0)

#define INSERT_WORDS(d,ix0,ix1)     \
do {                                \
  Double f;                         \
  reinterpret_cast<streflop::uint32_t*>(&f)[HIGH_WORD_IDX] = (ix0);  \
  reinterpret_cast<streflop::uint32_t*>(&f)[LOW_WORD_IDX] = (ix1);      \
  (d) = f; \
} while (0)

#define SET_HIGH_WORD(d,v)          \
do {                                \
  Double f = (d);                   \
  reinterpret_cast<streflop::uint32_t*>(&f)[HIGH_WORD_IDX] = (v);  \
  (d) = f; \
} while (0)

#define SET_LOW_WORD(d,v)           \
do {                                \
  Double f = (d);                   \
  reinterpret_cast<streflop::uint32_t*>(&f)[LOW_WORD_IDX] = (v);  \
  (d) = f; \
} while (0)

#endif

// Extended
#ifdef LIBM_COMPILING_LDBL96

#define EXTENDED_FROM_INT_PTR(x) *reinterpret_cast<Extended*>(x)
#define CONST_EXTENDED_FROM_INT_PTR(x) *reinterpret_cast<const Extended*>(x)

#define GET_LDOUBLE_WORDS(exp,ix0,ix1,d)            \
do {                                \
  Extended f = (d);                           \
    (exp) = *ExtendedConverter<sizeof(Extended)>::sexpPtr(&f); \
    (ix0) = ExtendedConverter<sizeof(Extended)>::mPtr(&f)[HIGH_WORD_IDX]; \
    (ix1) = ExtendedConverter<sizeof(Extended)>::mPtr(&f)[LOW_WORD_IDX]; \
} while (0)

#define SET_LDOUBLE_WORDS(d,exp,ix0,ix1)            \
do {                                \
  Extended f;                         \
    *ExtendedConverter<sizeof(Extended)>::sexpPtr(&f) = (exp); \
    ExtendedConverter<sizeof(Extended)>::mPtr(&f)[HIGH_WORD_IDX] = (ix0); \
    ExtendedConverter<sizeof(Extended)>::mPtr(&f)[LOW_WORD_IDX] = (ix1); \
  (d) = f; \
} while (0)

#define GET_LDOUBLE_MSW(v,d)                    \
do {                                \
  Extended f = (d);                           \
  (v) = ExtendedConverter<sizeof(Extended)>::mPtr(&f)[HIGH_WORD_IDX]; \
} while (0)

#define SET_LDOUBLE_MSW(d,v)                    \
do {                                \
  Extended f = (d);                           \
  ExtendedConverter<sizeof(Extended)>::mPtr(&f)[HIGH_WORD_IDX] = (v); \
  (d) = f;                     \
} while (0)

#define GET_LDOUBLE_EXP(exp,d)                  \
do {                                \
  Extended f = (d);                           \
  (exp) = *ExtendedConverter<sizeof(Extended)>::sexpPtr(&f); \
} while (0)

#define SET_LDOUBLE_EXP(d,exp)                  \
do {                                \
  Extended f = (d);                           \
  *ExtendedConverter<sizeof(Extended)>::sexpPtr(&f) = (exp); \
  (d) = f;                     \
} while (0)

#endif


#ifdef _MSC_VER
// Even if MSVC != STDC, we still need to define it,
// otherwise MSVC chokes on the K&R style function headers.
# define __STDC__
#endif


#endif