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 | 65 | return __fpclassify(x); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | + | |
| 68 | 69 | /* signbit */ |
| 69 | 70 | |
| 70 | 71 | __CRT_INLINE int __cdecl __signbit (double x) { |
| @@ -81,6 +82,118 @@ __CRT_INLINE int __cdecl __signbitl (long double x) { · 10 unmodified lines | ||
| 81 | 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 | 198 | End of code based on MUSL |
| 86 | 199 | *******************************************************************************/ |