gfx/skia/trunk/include/core/SkFloatingPoint.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/core/SkFloatingPoint.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,140 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2006 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#ifndef SkFloatingPoint_DEFINED
    1.14 +#define SkFloatingPoint_DEFINED
    1.15 +
    1.16 +#include "SkTypes.h"
    1.17 +
    1.18 +#include <math.h>
    1.19 +#include <float.h>
    1.20 +#include "SkFloatBits.h"
    1.21 +
    1.22 +// C++98 cmath std::pow seems to be the earliest portable way to get float pow.
    1.23 +// However, on Linux including cmath undefines isfinite.
    1.24 +// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14608
    1.25 +static inline float sk_float_pow(float base, float exp) {
    1.26 +    return powf(base, exp);
    1.27 +}
    1.28 +
    1.29 +static inline float sk_float_copysign(float x, float y) {
    1.30 +    int32_t xbits = SkFloat2Bits(x);
    1.31 +    int32_t ybits = SkFloat2Bits(y);
    1.32 +    return SkBits2Float((xbits & 0x7FFFFFFF) | (ybits & 0x80000000));
    1.33 +}
    1.34 +
    1.35 +#ifdef SK_BUILD_FOR_WINCE
    1.36 +    #define sk_float_sqrt(x)        (float)::sqrt(x)
    1.37 +    #define sk_float_sin(x)         (float)::sin(x)
    1.38 +    #define sk_float_cos(x)         (float)::cos(x)
    1.39 +    #define sk_float_tan(x)         (float)::tan(x)
    1.40 +    #define sk_float_acos(x)        (float)::acos(x)
    1.41 +    #define sk_float_asin(x)        (float)::asin(x)
    1.42 +    #define sk_float_atan2(y,x)     (float)::atan2(y,x)
    1.43 +    #define sk_float_abs(x)         (float)::fabs(x)
    1.44 +    #define sk_float_mod(x,y)       (float)::fmod(x,y)
    1.45 +    #define sk_float_exp(x)         (float)::exp(x)
    1.46 +    #define sk_float_log(x)         (float)::log(x)
    1.47 +    #define sk_float_floor(x)       (float)::floor(x)
    1.48 +    #define sk_float_ceil(x)        (float)::ceil(x)
    1.49 +#else
    1.50 +    #define sk_float_sqrt(x)        sqrtf(x)
    1.51 +    #define sk_float_sin(x)         sinf(x)
    1.52 +    #define sk_float_cos(x)         cosf(x)
    1.53 +    #define sk_float_tan(x)         tanf(x)
    1.54 +    #define sk_float_floor(x)       floorf(x)
    1.55 +    #define sk_float_ceil(x)        ceilf(x)
    1.56 +#ifdef SK_BUILD_FOR_MAC
    1.57 +    #define sk_float_acos(x)        static_cast<float>(acos(x))
    1.58 +    #define sk_float_asin(x)        static_cast<float>(asin(x))
    1.59 +#else
    1.60 +    #define sk_float_acos(x)        acosf(x)
    1.61 +    #define sk_float_asin(x)        asinf(x)
    1.62 +#endif
    1.63 +    #define sk_float_atan2(y,x)     atan2f(y,x)
    1.64 +    #define sk_float_abs(x)         fabsf(x)
    1.65 +    #define sk_float_mod(x,y)       fmodf(x,y)
    1.66 +    #define sk_float_exp(x)         expf(x)
    1.67 +    #define sk_float_log(x)         logf(x)
    1.68 +#endif
    1.69 +
    1.70 +#ifdef SK_BUILD_FOR_WIN
    1.71 +    #define sk_float_isfinite(x)    _finite(x)
    1.72 +    #define sk_float_isnan(x)       _isnan(x)
    1.73 +    static inline int sk_float_isinf(float x) {
    1.74 +        int32_t bits = SkFloat2Bits(x);
    1.75 +        return (bits << 1) == (0xFF << 24);
    1.76 +    }
    1.77 +#else
    1.78 +    #define sk_float_isfinite(x)    isfinite(x)
    1.79 +    #define sk_float_isnan(x)       isnan(x)
    1.80 +    #define sk_float_isinf(x)       isinf(x)
    1.81 +#endif
    1.82 +
    1.83 +#define sk_double_isnan(a)          sk_float_isnan(a)
    1.84 +
    1.85 +#ifdef SK_USE_FLOATBITS
    1.86 +    #define sk_float_floor2int(x)   SkFloatToIntFloor(x)
    1.87 +    #define sk_float_round2int(x)   SkFloatToIntRound(x)
    1.88 +    #define sk_float_ceil2int(x)    SkFloatToIntCeil(x)
    1.89 +#else
    1.90 +    #define sk_float_floor2int(x)   (int)sk_float_floor(x)
    1.91 +    #define sk_float_round2int(x)   (int)sk_float_floor((x) + 0.5f)
    1.92 +    #define sk_float_ceil2int(x)    (int)sk_float_ceil(x)
    1.93 +#endif
    1.94 +
    1.95 +extern const uint32_t gIEEENotANumber;
    1.96 +extern const uint32_t gIEEEInfinity;
    1.97 +extern const uint32_t gIEEENegativeInfinity;
    1.98 +
    1.99 +#define SK_FloatNaN                 (*SkTCast<const float*>(&gIEEENotANumber))
   1.100 +#define SK_FloatInfinity            (*SkTCast<const float*>(&gIEEEInfinity))
   1.101 +#define SK_FloatNegativeInfinity    (*SkTCast<const float*>(&gIEEENegativeInfinity))
   1.102 +
   1.103 +#if defined(__SSE__)
   1.104 +#include <xmmintrin.h>
   1.105 +#elif defined(__ARM_NEON__)
   1.106 +#include <arm_neon.h>
   1.107 +#endif
   1.108 +
   1.109 +// Fast, approximate inverse square root.
   1.110 +// Compare to name-brand "1.0f / sk_float_sqrt(x)".  Should be around 10x faster on SSE, 2x on NEON.
   1.111 +static inline float sk_float_rsqrt(const float x) {
   1.112 +// We want all this inlined, so we'll inline SIMD and just take the hit when we don't know we've got
   1.113 +// it at compile time.  This is going to be too fast to productively hide behind a function pointer.
   1.114 +//
   1.115 +// We do one step of Newton's method to refine the estimates in the NEON and null paths.  No
   1.116 +// refinement is faster, but very innacurate.  Two steps is more accurate, but slower than 1/sqrt.
   1.117 +#if defined(__SSE__)
   1.118 +    float result;
   1.119 +    _mm_store_ss(&result, _mm_rsqrt_ss(_mm_set_ss(x)));
   1.120 +    return result;
   1.121 +#elif defined(__ARM_NEON__)
   1.122 +    // Get initial estimate.
   1.123 +    const float32x2_t xx = vdup_n_f32(x);  // Clever readers will note we're doing everything 2x.
   1.124 +    float32x2_t estimate = vrsqrte_f32(xx);
   1.125 +
   1.126 +    // One step of Newton's method to refine.
   1.127 +    const float32x2_t estimate_sq = vmul_f32(estimate, estimate);
   1.128 +    estimate = vmul_f32(estimate, vrsqrts_f32(xx, estimate_sq));
   1.129 +    return vget_lane_f32(estimate, 0);  // 1 will work fine too; the answer's in both places.
   1.130 +#else
   1.131 +    // Get initial estimate.
   1.132 +    int i = *SkTCast<int*>(&x);
   1.133 +    i = 0x5f3759df - (i>>1);
   1.134 +    float estimate = *SkTCast<float*>(&i);
   1.135 +
   1.136 +    // One step of Newton's method to refine.
   1.137 +    const float estimate_sq = estimate*estimate;
   1.138 +    estimate *= (1.5f-0.5f*x*estimate_sq);
   1.139 +    return estimate;
   1.140 +#endif
   1.141 +}
   1.142 +
   1.143 +#endif

mercurial