Home | History | Annotate | Download | only in private
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkFloatingPoint_DEFINED
      9 #define SkFloatingPoint_DEFINED
     10 
     11 #include "../private/SkFloatBits.h"
     12 #include "SkTypes.h"
     13 #include "SkSafe_math.h"
     14 #include <float.h>
     15 #include <math.h>
     16 #include <cstring>
     17 #include <limits>
     18 
     19 
     20 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
     21     #include <xmmintrin.h>
     22 #elif defined(SK_ARM_HAS_NEON)
     23     #include <arm_neon.h>
     24 #endif
     25 
     26 // For _POSIX_VERSION
     27 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
     28 #include <unistd.h>
     29 #endif
     30 
     31 // C++98 cmath std::pow seems to be the earliest portable way to get float pow.
     32 // However, on Linux including cmath undefines isfinite.
     33 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14608
     34 static inline float sk_float_pow(float base, float exp) {
     35     return powf(base, exp);
     36 }
     37 
     38 #define sk_float_sqrt(x)        sqrtf(x)
     39 #define sk_float_sin(x)         sinf(x)
     40 #define sk_float_cos(x)         cosf(x)
     41 #define sk_float_tan(x)         tanf(x)
     42 #define sk_float_floor(x)       floorf(x)
     43 #define sk_float_ceil(x)        ceilf(x)
     44 #define sk_float_trunc(x)       truncf(x)
     45 #ifdef SK_BUILD_FOR_MAC
     46 #    define sk_float_acos(x)    static_cast<float>(acos(x))
     47 #    define sk_float_asin(x)    static_cast<float>(asin(x))
     48 #else
     49 #    define sk_float_acos(x)    acosf(x)
     50 #    define sk_float_asin(x)    asinf(x)
     51 #endif
     52 #define sk_float_atan2(y,x)     atan2f(y,x)
     53 #define sk_float_abs(x)         fabsf(x)
     54 #define sk_float_copysign(x, y) copysignf(x, y)
     55 #define sk_float_mod(x,y)       fmodf(x,y)
     56 #define sk_float_exp(x)         expf(x)
     57 #define sk_float_log(x)         logf(x)
     58 
     59 #define sk_float_round(x) sk_float_floor((x) + 0.5f)
     60 
     61 // can't find log2f on android, but maybe that just a tool bug?
     62 #ifdef SK_BUILD_FOR_ANDROID
     63     static inline float sk_float_log2(float x) {
     64         const double inv_ln_2 = 1.44269504088896;
     65         return (float)(log(x) * inv_ln_2);
     66     }
     67 #else
     68     #define sk_float_log2(x)        log2f(x)
     69 #endif
     70 
     71 static inline bool sk_float_isfinite(float x) {
     72     return SkFloatBits_IsFinite(SkFloat2Bits(x));
     73 }
     74 
     75 static inline bool sk_float_isinf(float x) {
     76     return SkFloatBits_IsInf(SkFloat2Bits(x));
     77 }
     78 
     79 static inline bool sk_float_isnan(float x) {
     80     return !(x == x);
     81 }
     82 
     83 #define sk_double_isnan(a)          sk_float_isnan(a)
     84 
     85 #define SK_MaxS32FitsInFloat    2147483520
     86 #define SK_MinS32FitsInFloat    -SK_MaxS32FitsInFloat
     87 
     88 #define SK_MaxS64FitsInFloat    (SK_MaxS64 >> (63-24) << (63-24))   // 0x7fffff8000000000
     89 #define SK_MinS64FitsInFloat    -SK_MaxS64FitsInFloat
     90 
     91 /**
     92  *  Return the closest int for the given float. Returns SK_MaxS32FitsInFloat for NaN.
     93  */
     94 static inline int sk_float_saturate2int(float x) {
     95     x = SkTMin<float>(x, SK_MaxS32FitsInFloat);
     96     x = SkTMax<float>(x, SK_MinS32FitsInFloat);
     97     return (int)x;
     98 }
     99 
    100 /**
    101  *  Return the closest int for the given double. Returns SK_MaxS32 for NaN.
    102  */
    103 static inline int sk_double_saturate2int(double x) {
    104     x = SkTMin<double>(x, SK_MaxS32);
    105     x = SkTMax<double>(x, SK_MinS32);
    106     return (int)x;
    107 }
    108 
    109 /**
    110  *  Return the closest int64_t for the given float. Returns SK_MaxS64FitsInFloat for NaN.
    111  */
    112 static inline int64_t sk_float_saturate2int64(float x) {
    113     x = SkTMin<float>(x, SK_MaxS64FitsInFloat);
    114     x = SkTMax<float>(x, SK_MinS64FitsInFloat);
    115     return (int64_t)x;
    116 }
    117 
    118 #define sk_float_floor2int(x)   sk_float_saturate2int(sk_float_floor(x))
    119 #define sk_float_round2int(x)   sk_float_saturate2int(sk_float_floor((x) + 0.5f))
    120 #define sk_float_ceil2int(x)    sk_float_saturate2int(sk_float_ceil(x))
    121 
    122 #define sk_float_floor2int_no_saturate(x)   (int)sk_float_floor(x)
    123 #define sk_float_round2int_no_saturate(x)   (int)sk_float_floor((x) + 0.5f)
    124 #define sk_float_ceil2int_no_saturate(x)    (int)sk_float_ceil(x)
    125 
    126 #define sk_double_floor(x)          floor(x)
    127 #define sk_double_round(x)          floor((x) + 0.5)
    128 #define sk_double_ceil(x)           ceil(x)
    129 #define sk_double_floor2int(x)      (int)floor(x)
    130 #define sk_double_round2int(x)      (int)floor((x) + 0.5)
    131 #define sk_double_ceil2int(x)       (int)ceil(x)
    132 
    133 // Cast double to float, ignoring any warning about too-large finite values being cast to float.
    134 // Clang thinks this is undefined, but it's actually implementation defined to return either
    135 // the largest float or infinity (one of the two bracketing representable floats).  Good enough!
    136 #if defined(__clang__) && (__clang_major__ * 1000 + __clang_minor__) >= 3007
    137 __attribute__((no_sanitize("float-cast-overflow")))
    138 #endif
    139 static inline float sk_double_to_float(double x) {
    140     return static_cast<float>(x);
    141 }
    142 
    143 #define SK_FloatNaN                 std::numeric_limits<float>::quiet_NaN()
    144 #define SK_FloatInfinity            (+std::numeric_limits<float>::infinity())
    145 #define SK_FloatNegativeInfinity    (-std::numeric_limits<float>::infinity())
    146 
    147 // Returns false if any of the floats are outside of [0...1]
    148 // Returns true if count is 0
    149 bool sk_floats_are_unit(const float array[], size_t count);
    150 
    151 static inline float sk_float_rsqrt_portable(float x) {
    152     // Get initial estimate.
    153     int i;
    154     memcpy(&i, &x, 4);
    155     i = 0x5F1FFFF9 - (i>>1);
    156     float estimate;
    157     memcpy(&estimate, &i, 4);
    158 
    159     // One step of Newton's method to refine.
    160     const float estimate_sq = estimate*estimate;
    161     estimate *= 0.703952253f*(2.38924456f-x*estimate_sq);
    162     return estimate;
    163 }
    164 
    165 // Fast, approximate inverse square root.
    166 // Compare to name-brand "1.0f / sk_float_sqrt(x)".  Should be around 10x faster on SSE, 2x on NEON.
    167 static inline float sk_float_rsqrt(float x) {
    168 // We want all this inlined, so we'll inline SIMD and just take the hit when we don't know we've got
    169 // it at compile time.  This is going to be too fast to productively hide behind a function pointer.
    170 //
    171 // We do one step of Newton's method to refine the estimates in the NEON and portable paths.  No
    172 // refinement is faster, but very innacurate.  Two steps is more accurate, but slower than 1/sqrt.
    173 //
    174 // Optimized constants in the portable path courtesy of http://rrrola.wz.cz/inv_sqrt.html
    175 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
    176     return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x)));
    177 #elif defined(SK_ARM_HAS_NEON)
    178     // Get initial estimate.
    179     const float32x2_t xx = vdup_n_f32(x);  // Clever readers will note we're doing everything 2x.
    180     float32x2_t estimate = vrsqrte_f32(xx);
    181 
    182     // One step of Newton's method to refine.
    183     const float32x2_t estimate_sq = vmul_f32(estimate, estimate);
    184     estimate = vmul_f32(estimate, vrsqrts_f32(xx, estimate_sq));
    185     return vget_lane_f32(estimate, 0);  // 1 will work fine too; the answer's in both places.
    186 #else
    187     return sk_float_rsqrt_portable(x);
    188 #endif
    189 }
    190 
    191 // This is the number of significant digits we can print in a string such that when we read that
    192 // string back we get the floating point number we expect.  The minimum value C requires is 6, but
    193 // most compilers support 9
    194 #ifdef FLT_DECIMAL_DIG
    195 #define SK_FLT_DECIMAL_DIG FLT_DECIMAL_DIG
    196 #else
    197 #define SK_FLT_DECIMAL_DIG 9
    198 #endif
    199 
    200 // IEEE defines how float divide behaves for non-finite values and zero-denoms, but C does not
    201 // so we have a helper that suppresses the possible undefined-behavior warnings.
    202 
    203 #ifdef __clang__
    204 __attribute__((no_sanitize("float-divide-by-zero")))
    205 #endif
    206 static inline float sk_ieee_float_divide(float numer, float denom) {
    207     return numer / denom;
    208 }
    209 
    210 #ifdef __clang__
    211 __attribute__((no_sanitize("float-divide-by-zero")))
    212 #endif
    213 static inline double sk_ieee_double_divide(double numer, double denom) {
    214     return numer / denom;
    215 }
    216 
    217 // While we clean up divide by zero, we'll replace places that do divide by zero with this TODO.
    218 static inline float sk_ieee_float_divide_TODO_IS_DIVIDE_BY_ZERO_SAFE_HERE(float n, float d) {
    219     return sk_ieee_float_divide(n,d);
    220 }
    221 static inline float sk_ieee_double_divide_TODO_IS_DIVIDE_BY_ZERO_SAFE_HERE(double n, double d) {
    222     return sk_ieee_double_divide(n,d);
    223 }
    224 
    225 #endif
    226