• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Native implementation of soft float functions */
2 #include <math.h>
3 
4 #if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
5 #include <ieeefp.h>
6 #define fabsf(f) ((float)fabs(f))
7 #else
8 #include <fenv.h>
9 #endif
10 
11 #ifdef __OpenBSD__
12 /* Get OpenBSD version number */
13 #include <sys/param.h>
14 #endif
15 
16 /*
17  * Define some C99-7.12.3 classification macros and
18  *        some C99-.12.4 for Solaris systems OS less than 10,
19  *        or Solaris 10 systems running GCC 3.x or less.
20  *   Solaris 10 with GCC4 does not need these macros as they
21  *   are defined in <iso/math_c99.h> with a compiler directive
22  */
23 #if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ((HOST_SOLARIS >= 10) \
24                                                         && (__GNUC__ <= 4))) \
25     || (defined(__OpenBSD__) && (OpenBSD < 200811))
26 /*
27  * C99 7.12.3 classification macros
28  * and
29  * C99 7.12.14 comparison macros
30  *
31  * ... do not work on Solaris 10 using GNU CC 3.4.x.
32  * Try to workaround the missing / broken C99 math macros.
33  */
34 #if defined(__OpenBSD__)
35 #define unordered(x, y) (isnan(x) || isnan(y))
36 #endif
37 
38 #define isnormal(x)             (fpclass(x) >= FP_NZERO)
39 #define isgreater(x, y)         ((!unordered(x, y)) && ((x) > (y)))
40 #define isgreaterequal(x, y)    ((!unordered(x, y)) && ((x) >= (y)))
41 #define isless(x, y)            ((!unordered(x, y)) && ((x) < (y)))
42 #define islessequal(x, y)       ((!unordered(x, y)) && ((x) <= (y)))
43 #define isunordered(x,y)        unordered(x, y)
44 #endif
45 
46 #if defined(__sun__) && !defined(NEED_LIBSUNMATH)
47 
48 #ifndef isnan
49 # define isnan(x) \
50     (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
51      : sizeof (x) == sizeof (double) ? isnan_d (x) \
52      : isnan_f (x))
isnan_f(float x)53 static inline int isnan_f  (float       x) { return x != x; }
isnan_d(double x)54 static inline int isnan_d  (double      x) { return x != x; }
isnan_ld(long double x)55 static inline int isnan_ld (long double x) { return x != x; }
56 #endif
57 
58 #ifndef isinf
59 # define isinf(x) \
60     (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
61      : sizeof (x) == sizeof (double) ? isinf_d (x) \
62      : isinf_f (x))
isinf_f(float x)63 static inline int isinf_f  (float       x) { return isnan (x - x); }
isinf_d(double x)64 static inline int isinf_d  (double      x) { return isnan (x - x); }
isinf_ld(long double x)65 static inline int isinf_ld (long double x) { return isnan (x - x); }
66 #endif
67 #endif
68 
69 typedef float float32;
70 typedef double float64;
71 #ifdef FLOATX80
72 typedef long double floatx80;
73 #endif
74 
75 typedef union {
76     float32 f;
77     uint32_t i;
78 } float32u;
79 typedef union {
80     float64 f;
81     uint64_t i;
82 } float64u;
83 #ifdef FLOATX80
84 typedef union {
85     floatx80 f;
86     struct {
87         uint64_t low;
88         uint16_t high;
89     } i;
90 } floatx80u;
91 #endif
92 
93 /*----------------------------------------------------------------------------
94 | Software IEC/IEEE floating-point rounding mode.
95 *----------------------------------------------------------------------------*/
96 #if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
97 #if defined(__OpenBSD__)
98 #define FE_RM FP_RM
99 #define FE_RP FP_RP
100 #define FE_RZ FP_RZ
101 #endif
102 enum {
103     float_round_nearest_even = FP_RN,
104     float_round_down         = FP_RM,
105     float_round_up           = FP_RP,
106     float_round_to_zero      = FP_RZ
107 };
108 #elif defined(__arm__)
109 enum {
110     float_round_nearest_even = 0,
111     float_round_down         = 1,
112     float_round_up           = 2,
113     float_round_to_zero      = 3
114 };
115 #else
116 enum {
117     float_round_nearest_even = FE_TONEAREST,
118     float_round_down         = FE_DOWNWARD,
119     float_round_up           = FE_UPWARD,
120     float_round_to_zero      = FE_TOWARDZERO
121 };
122 #endif
123 
124 typedef struct float_status {
125     signed char float_rounding_mode;
126 #ifdef FLOATX80
127     signed char floatx80_rounding_precision;
128 #endif
129 } float_status;
130 
131 void set_float_rounding_mode(int val STATUS_PARAM);
132 #ifdef FLOATX80
133 void set_floatx80_rounding_precision(int val STATUS_PARAM);
134 #endif
135 
136 /*----------------------------------------------------------------------------
137 | Software IEC/IEEE integer-to-floating-point conversion routines.
138 *----------------------------------------------------------------------------*/
139 float32 int32_to_float32( int STATUS_PARAM);
140 float32 uint32_to_float32( unsigned int STATUS_PARAM);
141 float64 int32_to_float64( int STATUS_PARAM);
142 float64 uint32_to_float64( unsigned int STATUS_PARAM);
143 #ifdef FLOATX80
144 floatx80 int32_to_floatx80( int STATUS_PARAM);
145 #endif
146 #ifdef FLOAT128
147 float128 int32_to_float128( int STATUS_PARAM);
148 #endif
149 float32 int64_to_float32( int64_t STATUS_PARAM);
150 float32 uint64_to_float32( uint64_t STATUS_PARAM);
151 float64 int64_to_float64( int64_t STATUS_PARAM);
152 float64 uint64_to_float64( uint64_t v STATUS_PARAM);
153 #ifdef FLOATX80
154 floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
155 #endif
156 #ifdef FLOAT128
157 float128 int64_to_float128( int64_t STATUS_PARAM);
158 #endif
159 
160 /*----------------------------------------------------------------------------
161 | Software IEC/IEEE single-precision conversion routines.
162 *----------------------------------------------------------------------------*/
163 int float32_to_int32( float32  STATUS_PARAM);
164 int float32_to_int32_round_to_zero( float32  STATUS_PARAM);
165 unsigned int float32_to_uint32( float32 a STATUS_PARAM);
166 unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM);
167 int64_t float32_to_int64( float32  STATUS_PARAM);
168 int64_t float32_to_int64_round_to_zero( float32  STATUS_PARAM);
169 float64 float32_to_float64( float32  STATUS_PARAM);
170 #ifdef FLOATX80
171 floatx80 float32_to_floatx80( float32  STATUS_PARAM);
172 #endif
173 #ifdef FLOAT128
174 float128 float32_to_float128( float32  STATUS_PARAM);
175 #endif
176 
177 /*----------------------------------------------------------------------------
178 | Software IEC/IEEE single-precision operations.
179 *----------------------------------------------------------------------------*/
180 float32 float32_round_to_int( float32  STATUS_PARAM);
float32_add(float32 a,float32 b STATUS_PARAM)181 INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM)
182 {
183     return a + b;
184 }
float32_sub(float32 a,float32 b STATUS_PARAM)185 INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM)
186 {
187     return a - b;
188 }
float32_mul(float32 a,float32 b STATUS_PARAM)189 INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM)
190 {
191     return a * b;
192 }
float32_div(float32 a,float32 b STATUS_PARAM)193 INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
194 {
195     return a / b;
196 }
197 float32 float32_rem( float32, float32  STATUS_PARAM);
198 float32 float32_sqrt( float32  STATUS_PARAM);
float32_eq(float32 a,float32 b STATUS_PARAM)199 INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
200 {
201     return a == b;
202 }
float32_le(float32 a,float32 b STATUS_PARAM)203 INLINE int float32_le( float32 a, float32 b STATUS_PARAM)
204 {
205     return a <= b;
206 }
float32_lt(float32 a,float32 b STATUS_PARAM)207 INLINE int float32_lt( float32 a, float32 b STATUS_PARAM)
208 {
209     return a < b;
210 }
float32_eq_signaling(float32 a,float32 b STATUS_PARAM)211 INLINE int float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
212 {
213     return a <= b && a >= b;
214 }
float32_le_quiet(float32 a,float32 b STATUS_PARAM)215 INLINE int float32_le_quiet( float32 a, float32 b STATUS_PARAM)
216 {
217     return islessequal(a, b);
218 }
float32_lt_quiet(float32 a,float32 b STATUS_PARAM)219 INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
220 {
221     return isless(a, b);
222 }
float32_unordered(float32 a,float32 b STATUS_PARAM)223 INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
224 {
225     return isunordered(a, b);
226 
227 }
228 int float32_compare( float32, float32 STATUS_PARAM );
229 int float32_compare_quiet( float32, float32 STATUS_PARAM );
230 int float32_is_signaling_nan( float32 );
231 
float32_abs(float32 a)232 INLINE float32 float32_abs(float32 a)
233 {
234     return fabsf(a);
235 }
236 
float32_chs(float32 a)237 INLINE float32 float32_chs(float32 a)
238 {
239     return -a;
240 }
241 
float32_scalbn(float32 a,int n)242 INLINE float32 float32_scalbn(float32 a, int n)
243 {
244     return scalbnf(a, n);
245 }
246 
247 /*----------------------------------------------------------------------------
248 | Software IEC/IEEE double-precision conversion routines.
249 *----------------------------------------------------------------------------*/
250 int float64_to_int32( float64 STATUS_PARAM );
251 int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
252 unsigned int float64_to_uint32( float64 STATUS_PARAM );
253 unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
254 int64_t float64_to_int64( float64 STATUS_PARAM );
255 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
256 uint64_t float64_to_uint64( float64 STATUS_PARAM );
257 uint64_t float64_to_uint64_round_to_zero( float64 STATUS_PARAM );
258 float32 float64_to_float32( float64 STATUS_PARAM );
259 #ifdef FLOATX80
260 floatx80 float64_to_floatx80( float64 STATUS_PARAM );
261 #endif
262 #ifdef FLOAT128
263 float128 float64_to_float128( float64 STATUS_PARAM );
264 #endif
265 
266 /*----------------------------------------------------------------------------
267 | Software IEC/IEEE double-precision operations.
268 *----------------------------------------------------------------------------*/
269 float64 float64_round_to_int( float64 STATUS_PARAM );
270 float64 float64_trunc_to_int( float64 STATUS_PARAM );
float64_add(float64 a,float64 b STATUS_PARAM)271 INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
272 {
273     return a + b;
274 }
float64_sub(float64 a,float64 b STATUS_PARAM)275 INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM)
276 {
277     return a - b;
278 }
float64_mul(float64 a,float64 b STATUS_PARAM)279 INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM)
280 {
281     return a * b;
282 }
float64_div(float64 a,float64 b STATUS_PARAM)283 INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
284 {
285     return a / b;
286 }
287 float64 float64_rem( float64, float64 STATUS_PARAM );
288 float64 float64_sqrt( float64 STATUS_PARAM );
float64_eq(float64 a,float64 b STATUS_PARAM)289 INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
290 {
291     return a == b;
292 }
float64_le(float64 a,float64 b STATUS_PARAM)293 INLINE int float64_le( float64 a, float64 b STATUS_PARAM)
294 {
295     return a <= b;
296 }
float64_lt(float64 a,float64 b STATUS_PARAM)297 INLINE int float64_lt( float64 a, float64 b STATUS_PARAM)
298 {
299     return a < b;
300 }
float64_eq_signaling(float64 a,float64 b STATUS_PARAM)301 INLINE int float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
302 {
303     return a <= b && a >= b;
304 }
float64_le_quiet(float64 a,float64 b STATUS_PARAM)305 INLINE int float64_le_quiet( float64 a, float64 b STATUS_PARAM)
306 {
307     return islessequal(a, b);
308 }
float64_lt_quiet(float64 a,float64 b STATUS_PARAM)309 INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
310 {
311     return isless(a, b);
312 
313 }
float64_unordered(float64 a,float64 b STATUS_PARAM)314 INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
315 {
316     return isunordered(a, b);
317 
318 }
319 int float64_compare( float64, float64 STATUS_PARAM );
320 int float64_compare_quiet( float64, float64 STATUS_PARAM );
321 int float64_is_signaling_nan( float64 );
322 int float64_is_nan( float64 );
323 
float64_abs(float64 a)324 INLINE float64 float64_abs(float64 a)
325 {
326     return fabs(a);
327 }
328 
float64_chs(float64 a)329 INLINE float64 float64_chs(float64 a)
330 {
331     return -a;
332 }
333 
float64_scalbn(float64 a,int n)334 INLINE float64 float64_scalbn(float64 a, int n)
335 {
336     return scalbn(a, n);
337 }
338 
339 #ifdef FLOATX80
340 
341 /*----------------------------------------------------------------------------
342 | Software IEC/IEEE extended double-precision conversion routines.
343 *----------------------------------------------------------------------------*/
344 int floatx80_to_int32( floatx80 STATUS_PARAM );
345 int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
346 int64_t floatx80_to_int64( floatx80 STATUS_PARAM);
347 int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM);
348 float32 floatx80_to_float32( floatx80 STATUS_PARAM );
349 float64 floatx80_to_float64( floatx80 STATUS_PARAM );
350 #ifdef FLOAT128
351 float128 floatx80_to_float128( floatx80 STATUS_PARAM );
352 #endif
353 
354 /*----------------------------------------------------------------------------
355 | Software IEC/IEEE extended double-precision operations.
356 *----------------------------------------------------------------------------*/
357 floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
floatx80_add(floatx80 a,floatx80 b STATUS_PARAM)358 INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM)
359 {
360     return a + b;
361 }
floatx80_sub(floatx80 a,floatx80 b STATUS_PARAM)362 INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM)
363 {
364     return a - b;
365 }
floatx80_mul(floatx80 a,floatx80 b STATUS_PARAM)366 INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM)
367 {
368     return a * b;
369 }
floatx80_div(floatx80 a,floatx80 b STATUS_PARAM)370 INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
371 {
372     return a / b;
373 }
374 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
375 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
floatx80_eq(floatx80 a,floatx80 b STATUS_PARAM)376 INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
377 {
378     return a == b;
379 }
floatx80_le(floatx80 a,floatx80 b STATUS_PARAM)380 INLINE int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
381 {
382     return a <= b;
383 }
floatx80_lt(floatx80 a,floatx80 b STATUS_PARAM)384 INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
385 {
386     return a < b;
387 }
floatx80_eq_signaling(floatx80 a,floatx80 b STATUS_PARAM)388 INLINE int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
389 {
390     return a <= b && a >= b;
391 }
floatx80_le_quiet(floatx80 a,floatx80 b STATUS_PARAM)392 INLINE int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
393 {
394     return islessequal(a, b);
395 }
floatx80_lt_quiet(floatx80 a,floatx80 b STATUS_PARAM)396 INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
397 {
398     return isless(a, b);
399 
400 }
floatx80_unordered(floatx80 a,floatx80 b STATUS_PARAM)401 INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
402 {
403     return isunordered(a, b);
404 
405 }
406 int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
407 int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
408 int floatx80_is_signaling_nan( floatx80 );
409 
floatx80_abs(floatx80 a)410 INLINE floatx80 floatx80_abs(floatx80 a)
411 {
412     return fabsl(a);
413 }
414 
floatx80_chs(floatx80 a)415 INLINE floatx80 floatx80_chs(floatx80 a)
416 {
417     return -a;
418 }
419 
floatx80_scalbn(floatx80 a,int n)420 INLINE floatx80 floatx80_scalbn(floatx80 a, int n)
421 {
422     return scalbnl(a, n);
423 }
424 
425 #endif
426