xref: /aosp_15_r20/external/pytorch/test/cpp/tensorexpr/gtest_assert_float_eq.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1 #pragma once
2 
3 #include <cmath>
4 // Copyright 2005, Google Inc.
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // The Google C++ Testing and Mocking Framework (Google Test)
34 //
35 // This header file declares functions and macros used internally by
36 // Google Test.  They are subject to change without notice.
37 
38 using Bits = uint32_t;
39 
40 // this avoids the "dereferencing type-punned pointer
41 // will break strict-aliasing rules" error
42 union Float {
43   float float_;
44   Bits bits_;
45 };
46 
47 // # of bits in a number.
48 static const size_t kBitCount = 8 * sizeof(Bits);
49 // The mask for the sign bit.
50 static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
51 
52 // GOOGLETEST_CM0001 DO NOT DELETE
53 
54 // Converts an integer from the sign-and-magnitude representation to
55 // the biased representation.  More precisely, let N be 2 to the
56 // power of (kBitCount - 1), an integer x is represented by the
57 // unsigned number x + N.
58 //
59 // For instance,
60 //
61 //   -N + 1 (the most negative number representable using
62 //          sign-and-magnitude) is represented by 1;
63 //   0      is represented by N; and
64 //   N - 1  (the biggest number representable using
65 //          sign-and-magnitude) is represented by 2N - 1.
66 //
67 // Read http://en.wikipedia.org/wiki/Signed_number_representations
68 // for more details on signed number representations.
SignAndMagnitudeToBiased(const Bits & sam)69 static Bits SignAndMagnitudeToBiased(const Bits& sam) {
70   if (kSignBitMask & sam) {
71     // sam represents a negative number.
72     return ~sam + 1;
73   } else {
74     // sam represents a positive number.
75     return kSignBitMask | sam;
76   }
77 }
78 
79 // Given two numbers in the sign-and-magnitude representation,
80 // returns the distance between them as an unsigned number.
DistanceBetweenSignAndMagnitudeNumbers(const Bits & sam1,const Bits & sam2)81 static Bits DistanceBetweenSignAndMagnitudeNumbers(
82     const Bits& sam1,
83     const Bits& sam2) {
84   const Bits biased1 = SignAndMagnitudeToBiased(sam1);
85   const Bits biased2 = SignAndMagnitudeToBiased(sam2);
86   return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
87 }
88 
89 // How many ULP's (Units in the Last Place) we want to tolerate when
90 // comparing two numbers.  The larger the value, the more error we
91 // allow.  A 0 value means that two numbers must be exactly the same
92 // to be considered equal.
93 //
94 // The maximum error of a single floating-point operation is 0.5
95 // units in the last place.  On Intel CPU's, all floating-point
96 // calculations are done with 80-bit precision, while double has 64
97 // bits.  Therefore, 4 should be enough for ordinary use.
98 //
99 // See the following article for more details on ULP:
100 // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
101 static const size_t kMaxUlps = 4;
102 
103 // Returns true if and only if this number is at most kMaxUlps ULP's away
104 // from rhs.  In particular, this function:
105 //
106 //   - returns false if either number is (or both are) NAN.
107 //   - treats really large numbers as almost equal to infinity.
108 //   - thinks +0.0 and -0.0 are 0 DLP's apart.
AlmostEquals(float lhs,float rhs)109 inline bool AlmostEquals(float lhs, float rhs) {
110   // The IEEE standard says that any comparison operation involving
111   // a NAN must return false.
112   if (std::isnan(lhs) || std::isnan(rhs))
113     return false;
114 
115   Float l = {lhs};
116   Float r = {rhs};
117 
118   return DistanceBetweenSignAndMagnitudeNumbers(l.bits_, r.bits_) <= kMaxUlps;
119 }
120