round and fmin/fmax are relatively commonly used functions but were not implemented anywhere in the tcc Windows distribution package. Newer mingw(64) math.h stil doesn't include these implementations. Add C implementations for these functions and place it as inline functions at win32/include/tcc/tcc_libm.h - which is already included from math.h . The code is mostly taken from musl-libc rs-1.0 (MIT) [*], musl-libc: http://git.musl-libc.org/cgit/musl/tree/src/math?h=rs-1.0 license: http://git.musl-libc.org/cgit/musl/tree/COPYRIGHT?h=rs-1.0 Potential enhancements: - Check how many useful libm implementations are still missing and consider adding them (some of them already work via the MS runtime). - Consider putting libm implementations in an actual libm.a file, or add a dummy one such that build processes which try to link with libm will not fail.
Unified · Split
| @@ -65,6 +65,7 @@ __CRT_INLINE int __cdecl __fpclassifyl (long double x) { · 64 unmodified lines | |||
| 65 | return __fpclassify(x); | 65 | return __fpclassify(x); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | |||
| 68 | /* signbit */ | 69 | /* signbit */ |
| 69 | 70 | ||
| 70 | __CRT_INLINE int __cdecl __signbit (double x) { | 71 | __CRT_INLINE int __cdecl __signbit (double x) { |
| @@ -81,6 +82,118 @@ __CRT_INLINE int __cdecl __signbitl (long double x) { · 10 unmodified lines | |||
| 81 | return __signbit(x); | 82 | return __signbit(x); |
| 82 | } | 83 | } |
| 83 | 84 | ||
| 85 | |||
| 86 | /* fmin*, fmax* */ | ||
| 87 | |||
| 88 | #define TCCFP_FMIN_EVAL (isnan(x) ? y : \ | ||
| 89 | isnan(y) ? x : \ | ||
| 90 | (signbit(x) != signbit(y)) ? (signbit(x) ? x : y) : \ | ||
| 91 | x < y ? x : y) | ||
| 92 | |||
| 93 | __CRT_INLINE double __cdecl fmin (double x, double y) { | ||
| 94 | return TCCFP_FMIN_EVAL; | ||
| 95 | } | ||
| 96 | |||
| 97 | __CRT_INLINE float __cdecl fminf (float x, float y) { | ||
| 98 | return TCCFP_FMIN_EVAL; | ||
| 99 | } | ||
| 100 | |||
| 101 | __CRT_INLINE long double __cdecl fminl (long double x, long double y) { | ||
| 102 | return TCCFP_FMIN_EVAL; | ||
| 103 | } | ||
| 104 | |||
| 105 | #define TCCFP_FMAX_EVAL (isnan(x) ? y : \ | ||
| 106 | isnan(y) ? x : \ | ||
| 107 | (signbit(x) != signbit(y)) ? (signbit(x) ? y : x) : \ | ||
| 108 | x < y ? y : x) | ||
| 109 | |||
| 110 | __CRT_INLINE double __cdecl fmax (double x, double y) { | ||
| 111 | return TCCFP_FMAX_EVAL; | ||
| 112 | } | ||
| 113 | |||
| 114 | __CRT_INLINE float __cdecl fmaxf (float x, float y) { | ||
| 115 | return TCCFP_FMAX_EVAL; | ||
| 116 | } | ||
| 117 | |||
| 118 | __CRT_INLINE long double __cdecl fmaxl (long double x, long double y) { | ||
| 119 | return TCCFP_FMAX_EVAL; | ||
| 120 | } | ||
| 121 | |||
| 122 | |||
| 123 | /* *round* */ | ||
| 124 | |||
| 125 | #define TCCFP_FORCE_EVAL(x) do { \ | ||
| 126 | if (sizeof(x) == sizeof(float)) { \ | ||
| 127 | volatile float __x; \ | ||
| 128 | __x = (x); \ | ||
| 129 | } else if (sizeof(x) == sizeof(double)) { \ | ||
| 130 | volatile double __x; \ | ||
| 131 | __x = (x); \ | ||
| 132 | } else { \ | ||
| 133 | volatile long double __x; \ | ||
| 134 | __x = (x); \ | ||
| 135 | } \ | ||
| 136 | } while(0) | ||
| 137 | |||
| 138 | __CRT_INLINE double __cdecl round (double x) { | ||
| 139 | union {double f; uint64_t i;} u = {x}; | ||
| 140 | int e = u.i >> 52 & 0x7ff; | ||
| 141 | double y; | ||
| 142 | |||
| 143 | if (e >= 0x3ff+52) | ||
| 144 | return x; | ||
| 145 | if (u.i >> 63) | ||
| 146 | x = -x; | ||
| 147 | if (e < 0x3ff-1) { | ||
| 148 | /* raise inexact if x!=0 */ | ||
| 149 | TCCFP_FORCE_EVAL(x + 0x1p52); | ||
| 150 | return 0*u.f; | ||
| 151 | } | ||
| 152 | y = (double)(x + 0x1p52) - 0x1p52 - x; | ||
| 153 | if (y > 0.5) | ||
| 154 | y = y + x - 1; | ||
| 155 | else if (y <= -0.5) | ||
| 156 | y = y + x + 1; | ||
| 157 | else | ||
| 158 | y = y + x; | ||
| 159 | if (u.i >> 63) | ||
| 160 | y = -y; | ||
| 161 | return y; | ||
| 162 | } | ||
| 163 | |||
| 164 | __CRT_INLINE long __cdecl lround (double x) { | ||
| 165 | return round(x); | ||
| 166 | } | ||
| 167 | |||
| 168 | __CRT_INLINE long long __cdecl llround (double x) { | ||
| 169 | return round(x); | ||
| 170 | } | ||
| 171 | |||
| 172 | __CRT_INLINE float __cdecl roundf (float x) { | ||
| 173 | return round(x); | ||
| 174 | } | ||
| 175 | |||
| 176 | __CRT_INLINE long __cdecl lroundf (float x) { | ||
| 177 | return round(x); | ||
| 178 | } | ||
| 179 | |||
| 180 | __CRT_INLINE long long __cdecl llroundf (float x) { | ||
| 181 | return round(x); | ||
| 182 | } | ||
| 183 | |||
| 184 | __CRT_INLINE long double __cdecl roundl (long double x) { | ||
| 185 | return round(x); | ||
| 186 | } | ||
| 187 | |||
| 188 | __CRT_INLINE long __cdecl lroundl (long double x) { | ||
| 189 | return round(x); | ||
| 190 | } | ||
| 191 | |||
| 192 | __CRT_INLINE long long __cdecl llroundl (long double x) { | ||
| 193 | return round(x); | ||
| 194 | } | ||
| 195 | |||
| 196 | |||
| 84 | /******************************************************************************* | 197 | /******************************************************************************* |
| 85 | End of code based on MUSL | 198 | End of code based on MUSL |
| 86 | *******************************************************************************/ | 199 | *******************************************************************************/ |