1 /*
2  * Copyright (C) 2003-2006     Manuel Novoa III
3  *
4  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
5  */
6 /* Define a maximal floating point type, and the associated constants
7  * that are defined for the floating point types in float.h.
8  *
9  * This is to support archs that are missing long double, or even double.
10  */
11 
12 #ifndef _UCLIBC_FPMAX_H
13 #define _UCLIBC_FPMAX_H
14 
15 #include <features.h>
16 #include <float.h>
17 
18 #ifdef __UCLIBC_HAS_FLOATS__
19 
20 #if defined(LDBL_MANT_DIG)
21 
22 typedef long double __fpmax_t;
23 #define FPMAX_TYPE           3
24 
25 #define FPMAX_MANT_DIG       LDBL_MANT_DIG
26 #define FPMAX_DIG            LDBL_DIG
27 #define FPMAX_EPSILON        LDBL_EPSILON
28 #define FPMAX_MIN_EXP        LDBL_MIN_EXP
29 #define FPMAX_MIN            LDBL_MIN
30 #define FPMAX_MIN_10_EXP     LDBL_MIN_10_EXP
31 #define FPMAX_MAX_EXP        LDBL_MAX_EXP
32 #define FPMAX_MAX            LDBL_MAX
33 #define FPMAX_MAX_10_EXP     LDBL_MAX_10_EXP
34 
35 #elif defined(DBL_MANT_DIG)
36 
37 typedef double __fpmax_t;
38 #define FPMAX_TYPE           2
39 
40 #define FPMAX_MANT_DIG       DBL_MANT_DIG
41 #define FPMAX_DIG            DBL_DIG
42 #define FPMAX_EPSILON        DBL_EPSILON
43 #define FPMAX_MIN_EXP        DBL_MIN_EXP
44 #define FPMAX_MIN            DBL_MIN
45 #define FPMAX_MIN_10_EXP     DBL_MIN_10_EXP
46 #define FPMAX_MAX_EXP        DBL_MAX_EXP
47 #define FPMAX_MAX            DBL_MAX
48 #define FPMAX_MAX_10_EXP     DBL_MAX_10_EXP
49 
50 #elif defined(FLT_MANT_DIG)
51 
52 typedef float __fpmax_t;
53 #define FPMAX_TYPE           1
54 
55 #define FPMAX_MANT_DIG       FLT_MANT_DIG
56 #define FPMAX_DIG            FLT_DIG
57 #define FPMAX_EPSILON        FLT_EPSILON
58 #define FPMAX_MIN_EXP        FLT_MIN_EXP
59 #define FPMAX_MIN            FLT_MIN
60 #define FPMAX_MIN_10_EXP     FLT_MIN_10_EXP
61 #define FPMAX_MAX_EXP        FLT_MAX_EXP
62 #define FPMAX_MAX            FLT_MAX
63 #define FPMAX_MAX_10_EXP     FLT_MAX_10_EXP
64 
65 #else
66 #error unable to determine appropriate type for __fpmax_t!
67 #endif
68 
69 #ifndef DECIMAL_DIG
70 
71 #ifdef L___strtofpmax
72 /* Emit warning only once. */
73 #warning DECIMAL_DIG is not defined! If you are using gcc, it may not be defining __STDC_VERSION__ as it should.
74 #endif
75 #if !defined(FLT_RADIX) || (FLT_RADIX != 2)
76 #error unable to compensate for missing DECIMAL_DIG!
77 #endif
78 
79 /*  ceil (1 + #mantissa * log10 (FLT_RADIX)) */
80 #define DECIMAL_DIG   (1 + (((FPMAX_MANT_DIG * 100) + 331) / 332))
81 
82 #endif /* DECIMAL_DIG */
83 
84 #if defined _LIBC && defined IS_IN_libc
85 extern __fpmax_t __strtofpmax(const char *str, char **endptr, int exp_adjust) attribute_hidden;
86 
87 #ifdef __UCLIBC_HAS_XLOCALE__
88 extern __fpmax_t __strtofpmax_l(const char *str, char **endptr, int exp_adjust,
89 								__locale_t locale_arg) attribute_hidden;
90 #endif
91 
92 #ifdef __UCLIBC_HAS_WCHAR__
93 extern __fpmax_t __wcstofpmax(const wchar_t *wcs, wchar_t **endptr,
94 							  int exp_adjust) attribute_hidden;
95 
96 #ifdef __UCLIBC_HAS_XLOCALE__
97 extern __fpmax_t __wcstofpmax_l(const wchar_t *wcs, wchar_t **endptr,
98 								int exp_adjust, __locale_t locale_arg) attribute_hidden;
99 #endif
100 #endif /* __UCLIBC_HAS_WCHAR__ */
101 #endif /* _LIBC */
102 
103 /* The following checks in an __fpmax_t is either 0 or +/- infinity.
104  *
105  * WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!
106  *
107  * This only works if __fpmax_t is the actual maximal floating point type used
108  * in intermediate calculations.  Otherwise, excess precision in the
109  * intermediate values can cause the test to fail.
110  *
111  * WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!
112  */
113 
114 #define __FPMAX_ZERO_OR_INF_CHECK(x)  ((x) == ((x)/4) )
115 
116 #endif /* __UCLIBC_HAS_FLOATS__ */
117 
118 #endif /* _UCLIBC_FPMAX_H */
119