xref: /aosp_15_r20/external/skia/src/utils/SkFloatUtils.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkFloatUtils_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkFloatUtils_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include <limits.h>
13*c8dee2aaSAndroid Build Coastguard Worker #include <float.h>
14*c8dee2aaSAndroid Build Coastguard Worker 
15*c8dee2aaSAndroid Build Coastguard Worker template <size_t size>
16*c8dee2aaSAndroid Build Coastguard Worker class SkTypeWithSize {
17*c8dee2aaSAndroid Build Coastguard Worker public:
18*c8dee2aaSAndroid Build Coastguard Worker     // Prevents using SkTypeWithSize<N> with non-specialized N.
19*c8dee2aaSAndroid Build Coastguard Worker     typedef void UInt;
20*c8dee2aaSAndroid Build Coastguard Worker };
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker template <>
23*c8dee2aaSAndroid Build Coastguard Worker class SkTypeWithSize<32> {
24*c8dee2aaSAndroid Build Coastguard Worker public:
25*c8dee2aaSAndroid Build Coastguard Worker     typedef uint32_t UInt;
26*c8dee2aaSAndroid Build Coastguard Worker };
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker template <>
29*c8dee2aaSAndroid Build Coastguard Worker class SkTypeWithSize<64> {
30*c8dee2aaSAndroid Build Coastguard Worker public:
31*c8dee2aaSAndroid Build Coastguard Worker     typedef uint64_t UInt;
32*c8dee2aaSAndroid Build Coastguard Worker };
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker template <typename RawType>
35*c8dee2aaSAndroid Build Coastguard Worker struct SkNumericLimits {
36*c8dee2aaSAndroid Build Coastguard Worker     static const int digits = 0;
37*c8dee2aaSAndroid Build Coastguard Worker };
38*c8dee2aaSAndroid Build Coastguard Worker 
39*c8dee2aaSAndroid Build Coastguard Worker template <>
40*c8dee2aaSAndroid Build Coastguard Worker struct SkNumericLimits<double> {
41*c8dee2aaSAndroid Build Coastguard Worker     static const int digits = DBL_MANT_DIG;
42*c8dee2aaSAndroid Build Coastguard Worker };
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker template <>
45*c8dee2aaSAndroid Build Coastguard Worker struct SkNumericLimits<float> {
46*c8dee2aaSAndroid Build Coastguard Worker     static const int digits = FLT_MANT_DIG;
47*c8dee2aaSAndroid Build Coastguard Worker };
48*c8dee2aaSAndroid Build Coastguard Worker 
49*c8dee2aaSAndroid Build Coastguard Worker //See
50*c8dee2aaSAndroid Build Coastguard Worker //http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison/3423299#3423299
51*c8dee2aaSAndroid Build Coastguard Worker //http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-internal.h
52*c8dee2aaSAndroid Build Coastguard Worker //http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker template <typename RawType, unsigned int ULPs>
55*c8dee2aaSAndroid Build Coastguard Worker class SkFloatingPoint {
56*c8dee2aaSAndroid Build Coastguard Worker public:
57*c8dee2aaSAndroid Build Coastguard Worker     /** Bits is a unsigned integer the same size as the floating point number. */
58*c8dee2aaSAndroid Build Coastguard Worker     typedef typename SkTypeWithSize<sizeof(RawType) * CHAR_BIT>::UInt Bits;
59*c8dee2aaSAndroid Build Coastguard Worker 
60*c8dee2aaSAndroid Build Coastguard Worker     /** # of bits in a number. */
61*c8dee2aaSAndroid Build Coastguard Worker     static const size_t kBitCount = CHAR_BIT * sizeof(RawType);
62*c8dee2aaSAndroid Build Coastguard Worker 
63*c8dee2aaSAndroid Build Coastguard Worker     /** # of fraction bits in a number. */
64*c8dee2aaSAndroid Build Coastguard Worker     static const size_t kFractionBitCount = SkNumericLimits<RawType>::digits - 1;
65*c8dee2aaSAndroid Build Coastguard Worker 
66*c8dee2aaSAndroid Build Coastguard Worker     /** # of exponent bits in a number. */
67*c8dee2aaSAndroid Build Coastguard Worker     static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
68*c8dee2aaSAndroid Build Coastguard Worker 
69*c8dee2aaSAndroid Build Coastguard Worker     /** The mask for the sign bit. */
70*c8dee2aaSAndroid Build Coastguard Worker     static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker     /** The mask for the fraction bits. */
73*c8dee2aaSAndroid Build Coastguard Worker     static const Bits kFractionBitMask =
74*c8dee2aaSAndroid Build Coastguard Worker         ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker     /** The mask for the exponent bits. */
77*c8dee2aaSAndroid Build Coastguard Worker     static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker     /** How many ULP's (Units in the Last Place) to tolerate when comparing. */
80*c8dee2aaSAndroid Build Coastguard Worker     static const size_t kMaxUlps = ULPs;
81*c8dee2aaSAndroid Build Coastguard Worker 
82*c8dee2aaSAndroid Build Coastguard Worker     /**
83*c8dee2aaSAndroid Build Coastguard Worker      *  Constructs a FloatingPoint from a raw floating-point number.
84*c8dee2aaSAndroid Build Coastguard Worker      *
85*c8dee2aaSAndroid Build Coastguard Worker      *  On an Intel CPU, passing a non-normalized NAN (Not a Number)
86*c8dee2aaSAndroid Build Coastguard Worker      *  around may change its bits, although the new value is guaranteed
87*c8dee2aaSAndroid Build Coastguard Worker      *  to be also a NAN.  Therefore, don't expect this constructor to
88*c8dee2aaSAndroid Build Coastguard Worker      *  preserve the bits in x when x is a NAN.
89*c8dee2aaSAndroid Build Coastguard Worker      */
90*c8dee2aaSAndroid Build Coastguard Worker     explicit SkFloatingPoint(const RawType& x) { fU.value = x; }
91*c8dee2aaSAndroid Build Coastguard Worker 
92*c8dee2aaSAndroid Build Coastguard Worker     /** Returns the exponent bits of this number. */
93*c8dee2aaSAndroid Build Coastguard Worker     Bits exponent_bits() const { return kExponentBitMask & fU.bits; }
94*c8dee2aaSAndroid Build Coastguard Worker 
95*c8dee2aaSAndroid Build Coastguard Worker     /** Returns the fraction bits of this number. */
96*c8dee2aaSAndroid Build Coastguard Worker     Bits fraction_bits() const { return kFractionBitMask & fU.bits; }
97*c8dee2aaSAndroid Build Coastguard Worker 
98*c8dee2aaSAndroid Build Coastguard Worker     /** Returns true iff this is NAN (not a number). */
99*c8dee2aaSAndroid Build Coastguard Worker     bool is_nan() const {
100*c8dee2aaSAndroid Build Coastguard Worker         // It's a NAN if both of the folloowing are true:
101*c8dee2aaSAndroid Build Coastguard Worker         // * the exponent bits are all ones
102*c8dee2aaSAndroid Build Coastguard Worker         // * the fraction bits are not all zero.
103*c8dee2aaSAndroid Build Coastguard Worker         return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
104*c8dee2aaSAndroid Build Coastguard Worker     }
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker     /**
107*c8dee2aaSAndroid Build Coastguard Worker      *  Returns true iff this number is at most kMaxUlps ULP's away from ths.
108*c8dee2aaSAndroid Build Coastguard Worker      *  In particular, this function:
109*c8dee2aaSAndroid Build Coastguard Worker      *   - returns false if either number is (or both are) NAN.
110*c8dee2aaSAndroid Build Coastguard Worker      *   - treats really large numbers as almost equal to infinity.
111*c8dee2aaSAndroid Build Coastguard Worker      *   - thinks +0.0 and -0.0 are 0 DLP's apart.
112*c8dee2aaSAndroid Build Coastguard Worker      */
113*c8dee2aaSAndroid Build Coastguard Worker     bool AlmostEquals(const SkFloatingPoint& rhs) const {
114*c8dee2aaSAndroid Build Coastguard Worker         // Any comparison operation involving a NAN must return false.
115*c8dee2aaSAndroid Build Coastguard Worker         if (is_nan() || rhs.is_nan()) return false;
116*c8dee2aaSAndroid Build Coastguard Worker 
117*c8dee2aaSAndroid Build Coastguard Worker         const Bits dist = DistanceBetweenSignAndMagnitudeNumbers(fU.bits,
118*c8dee2aaSAndroid Build Coastguard Worker                                                                  rhs.fU.bits);
119*c8dee2aaSAndroid Build Coastguard Worker         //SkDEBUGF("(%f, %f, %d) ", u_.value_, rhs.u_.value_, dist);
120*c8dee2aaSAndroid Build Coastguard Worker         return dist <= kMaxUlps;
121*c8dee2aaSAndroid Build Coastguard Worker     }
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker private:
124*c8dee2aaSAndroid Build Coastguard Worker     /** The data type used to store the actual floating-point number. */
125*c8dee2aaSAndroid Build Coastguard Worker     union FloatingPointUnion {
126*c8dee2aaSAndroid Build Coastguard Worker         /** The raw floating-point number. */
127*c8dee2aaSAndroid Build Coastguard Worker         RawType value;
128*c8dee2aaSAndroid Build Coastguard Worker         /** The bits that represent the number. */
129*c8dee2aaSAndroid Build Coastguard Worker         Bits bits;
130*c8dee2aaSAndroid Build Coastguard Worker     };
131*c8dee2aaSAndroid Build Coastguard Worker 
132*c8dee2aaSAndroid Build Coastguard Worker     /**
133*c8dee2aaSAndroid Build Coastguard Worker      *  Converts an integer from the sign-and-magnitude representation to
134*c8dee2aaSAndroid Build Coastguard Worker      *  the biased representation. More precisely, let N be 2 to the
135*c8dee2aaSAndroid Build Coastguard Worker      *  power of (kBitCount - 1), an integer x is represented by the
136*c8dee2aaSAndroid Build Coastguard Worker      *  unsigned number x + N.
137*c8dee2aaSAndroid Build Coastguard Worker      *
138*c8dee2aaSAndroid Build Coastguard Worker      *  For instance,
139*c8dee2aaSAndroid Build Coastguard Worker      *
140*c8dee2aaSAndroid Build Coastguard Worker      *    -N + 1 (the most negative number representable using
141*c8dee2aaSAndroid Build Coastguard Worker      *           sign-and-magnitude) is represented by 1;
142*c8dee2aaSAndroid Build Coastguard Worker      *    0      is represented by N; and
143*c8dee2aaSAndroid Build Coastguard Worker      *    N - 1  (the biggest number representable using
144*c8dee2aaSAndroid Build Coastguard Worker      *           sign-and-magnitude) is represented by 2N - 1.
145*c8dee2aaSAndroid Build Coastguard Worker      *
146*c8dee2aaSAndroid Build Coastguard Worker      *  Read http://en.wikipedia.org/wiki/Signed_number_representations
147*c8dee2aaSAndroid Build Coastguard Worker      *  for more details on signed number representations.
148*c8dee2aaSAndroid Build Coastguard Worker      */
149*c8dee2aaSAndroid Build Coastguard Worker     static Bits SignAndMagnitudeToBiased(const Bits &sam) {
150*c8dee2aaSAndroid Build Coastguard Worker         if (kSignBitMask & sam) {
151*c8dee2aaSAndroid Build Coastguard Worker             // sam represents a negative number.
152*c8dee2aaSAndroid Build Coastguard Worker             return ~sam + 1;
153*c8dee2aaSAndroid Build Coastguard Worker         } else {
154*c8dee2aaSAndroid Build Coastguard Worker             // sam represents a positive number.
155*c8dee2aaSAndroid Build Coastguard Worker             return kSignBitMask | sam;
156*c8dee2aaSAndroid Build Coastguard Worker         }
157*c8dee2aaSAndroid Build Coastguard Worker     }
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker     /**
160*c8dee2aaSAndroid Build Coastguard Worker      *  Given two numbers in the sign-and-magnitude representation,
161*c8dee2aaSAndroid Build Coastguard Worker      *  returns the distance between them as an unsigned number.
162*c8dee2aaSAndroid Build Coastguard Worker      */
163*c8dee2aaSAndroid Build Coastguard Worker     static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
164*c8dee2aaSAndroid Build Coastguard Worker                                                        const Bits &sam2) {
165*c8dee2aaSAndroid Build Coastguard Worker         const Bits biased1 = SignAndMagnitudeToBiased(sam1);
166*c8dee2aaSAndroid Build Coastguard Worker         const Bits biased2 = SignAndMagnitudeToBiased(sam2);
167*c8dee2aaSAndroid Build Coastguard Worker         return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
168*c8dee2aaSAndroid Build Coastguard Worker     }
169*c8dee2aaSAndroid Build Coastguard Worker 
170*c8dee2aaSAndroid Build Coastguard Worker     FloatingPointUnion fU;
171*c8dee2aaSAndroid Build Coastguard Worker };
172*c8dee2aaSAndroid Build Coastguard Worker 
173*c8dee2aaSAndroid Build Coastguard Worker #endif
174