Brian Silverman | 5da9803 | 2013-04-28 18:08:57 -0700 | [diff] [blame] | 1 | // Some of the Compiler-RT implementations we use want to use functions from |
| 2 | // libm. However, GCC provides builtins for them, so they don't need to show up |
| 3 | // in <math.h> Unfortunately, those GCC builtins seem to (sometimes, at least) |
| 4 | // just emit calls to the functions themselves, so we have our own |
| 5 | // implementations here. They might not be as fast as they could be, but they |
| 6 | // are correct as far as I can tell. |
| 7 | |
| 8 | #include <stdint.h> |
| 9 | |
| 10 | double fmax(double a, double b) { |
| 11 | if (__builtin_isnan(a)) return b; |
| 12 | if (__builtin_isnan(b)) return a; |
| 13 | if (a > b) return a; |
| 14 | return b; |
| 15 | } |
| 16 | float fmaxf(float a, float b) { |
| 17 | if (__builtin_isnan(a)) return b; |
| 18 | if (__builtin_isnan(b)) return a; |
| 19 | if (a > b) return a; |
| 20 | return b; |
| 21 | } |
| 22 | |
| 23 | double scalbn(double x, int exp) { |
| 24 | return x * (2 << exp); |
| 25 | } |
| 26 | float scalbnf(float x, int exp) { |
| 27 | return x * (2 << exp); |
| 28 | } |
| 29 | |
| 30 | float logbf(float x) { |
| 31 | union { |
| 32 | float f; |
| 33 | int32_t d; |
| 34 | } converter; |
| 35 | converter.f = x; |
| 36 | int32_t ix = converter.d & 0x7fffffff; |
| 37 | int32_t rix; |
| 38 | |
| 39 | if (ix == 0) { |
| 40 | return (float)-1.0 / __builtin_fabsf(x); |
| 41 | } else if (ix >= 0x7f800000) { |
| 42 | return x * x; |
| 43 | } else if (__builtin_expect((rix = ix >> 23) == 0, 0)) { |
| 44 | rix -= __builtin_clz(ix) - 9; |
| 45 | } |
| 46 | return (float)(rix - 127); |
| 47 | } |