1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/SkFloatUtils.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,173 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef SkFloatUtils_DEFINED 1.12 +#define SkFloatUtils_DEFINED 1.13 + 1.14 +#include "SkTypes.h" 1.15 +#include <limits.h> 1.16 +#include <float.h> 1.17 + 1.18 +template <size_t size> 1.19 +class SkTypeWithSize { 1.20 +public: 1.21 + // Prevents using SkTypeWithSize<N> with non-specialized N. 1.22 + typedef void UInt; 1.23 +}; 1.24 + 1.25 +template <> 1.26 +class SkTypeWithSize<32> { 1.27 +public: 1.28 + typedef uint32_t UInt; 1.29 +}; 1.30 + 1.31 +template <> 1.32 +class SkTypeWithSize<64> { 1.33 +public: 1.34 + typedef uint64_t UInt; 1.35 +}; 1.36 + 1.37 +template <typename RawType> 1.38 +struct SkNumericLimits { 1.39 + static const int digits = 0; 1.40 +}; 1.41 + 1.42 +template <> 1.43 +struct SkNumericLimits<double> { 1.44 + static const int digits = DBL_MANT_DIG; 1.45 +}; 1.46 + 1.47 +template <> 1.48 +struct SkNumericLimits<float> { 1.49 + static const int digits = FLT_MANT_DIG; 1.50 +}; 1.51 + 1.52 +//See 1.53 +//http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison/3423299#3423299 1.54 +//http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-internal.h 1.55 +//http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm 1.56 + 1.57 +template <typename RawType, unsigned int ULPs> 1.58 +class SkFloatingPoint { 1.59 +public: 1.60 + /** Bits is a unsigned integer the same size as the floating point number. */ 1.61 + typedef typename SkTypeWithSize<sizeof(RawType) * CHAR_BIT>::UInt Bits; 1.62 + 1.63 + /** # of bits in a number. */ 1.64 + static const size_t kBitCount = CHAR_BIT * sizeof(RawType); 1.65 + 1.66 + /** # of fraction bits in a number. */ 1.67 + static const size_t kFractionBitCount = SkNumericLimits<RawType>::digits - 1; 1.68 + 1.69 + /** # of exponent bits in a number. */ 1.70 + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; 1.71 + 1.72 + /** The mask for the sign bit. */ 1.73 + static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1); 1.74 + 1.75 + /** The mask for the fraction bits. */ 1.76 + static const Bits kFractionBitMask = 1.77 + ~static_cast<Bits>(0) >> (kExponentBitCount + 1); 1.78 + 1.79 + /** The mask for the exponent bits. */ 1.80 + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); 1.81 + 1.82 + /** How many ULP's (Units in the Last Place) to tolerate when comparing. */ 1.83 + static const size_t kMaxUlps = ULPs; 1.84 + 1.85 + /** 1.86 + * Constructs a FloatingPoint from a raw floating-point number. 1.87 + * 1.88 + * On an Intel CPU, passing a non-normalized NAN (Not a Number) 1.89 + * around may change its bits, although the new value is guaranteed 1.90 + * to be also a NAN. Therefore, don't expect this constructor to 1.91 + * preserve the bits in x when x is a NAN. 1.92 + */ 1.93 + explicit SkFloatingPoint(const RawType& x) { fU.value = x; } 1.94 + 1.95 + /** Returns the exponent bits of this number. */ 1.96 + Bits exponent_bits() const { return kExponentBitMask & fU.bits; } 1.97 + 1.98 + /** Returns the fraction bits of this number. */ 1.99 + Bits fraction_bits() const { return kFractionBitMask & fU.bits; } 1.100 + 1.101 + /** Returns true iff this is NAN (not a number). */ 1.102 + bool is_nan() const { 1.103 + // It's a NAN if both of the folloowing are true: 1.104 + // * the exponent bits are all ones 1.105 + // * the fraction bits are not all zero. 1.106 + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); 1.107 + } 1.108 + 1.109 + /** 1.110 + * Returns true iff this number is at most kMaxUlps ULP's away from ths. 1.111 + * In particular, this function: 1.112 + * - returns false if either number is (or both are) NAN. 1.113 + * - treats really large numbers as almost equal to infinity. 1.114 + * - thinks +0.0 and -0.0 are 0 DLP's apart. 1.115 + */ 1.116 + bool AlmostEquals(const SkFloatingPoint& rhs) const { 1.117 + // Any comparison operation involving a NAN must return false. 1.118 + if (is_nan() || rhs.is_nan()) return false; 1.119 + 1.120 + const Bits dist = DistanceBetweenSignAndMagnitudeNumbers(fU.bits, 1.121 + rhs.fU.bits); 1.122 + //SkDEBUGF(("(%f, %f, %d) ", u_.value_, rhs.u_.value_, dist)); 1.123 + return dist <= kMaxUlps; 1.124 + } 1.125 + 1.126 +private: 1.127 + /** The data type used to store the actual floating-point number. */ 1.128 + union FloatingPointUnion { 1.129 + /** The raw floating-point number. */ 1.130 + RawType value; 1.131 + /** The bits that represent the number. */ 1.132 + Bits bits; 1.133 + }; 1.134 + 1.135 + /** 1.136 + * Converts an integer from the sign-and-magnitude representation to 1.137 + * the biased representation. More precisely, let N be 2 to the 1.138 + * power of (kBitCount - 1), an integer x is represented by the 1.139 + * unsigned number x + N. 1.140 + * 1.141 + * For instance, 1.142 + * 1.143 + * -N + 1 (the most negative number representable using 1.144 + * sign-and-magnitude) is represented by 1; 1.145 + * 0 is represented by N; and 1.146 + * N - 1 (the biggest number representable using 1.147 + * sign-and-magnitude) is represented by 2N - 1. 1.148 + * 1.149 + * Read http://en.wikipedia.org/wiki/Signed_number_representations 1.150 + * for more details on signed number representations. 1.151 + */ 1.152 + static Bits SignAndMagnitudeToBiased(const Bits &sam) { 1.153 + if (kSignBitMask & sam) { 1.154 + // sam represents a negative number. 1.155 + return ~sam + 1; 1.156 + } else { 1.157 + // sam represents a positive number. 1.158 + return kSignBitMask | sam; 1.159 + } 1.160 + } 1.161 + 1.162 + /** 1.163 + * Given two numbers in the sign-and-magnitude representation, 1.164 + * returns the distance between them as an unsigned number. 1.165 + */ 1.166 + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, 1.167 + const Bits &sam2) { 1.168 + const Bits biased1 = SignAndMagnitudeToBiased(sam1); 1.169 + const Bits biased2 = SignAndMagnitudeToBiased(sam2); 1.170 + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); 1.171 + } 1.172 + 1.173 + FloatingPointUnion fU; 1.174 +}; 1.175 + 1.176 +#endif