Use glReadnPixels only if KHR_robustness is supported am: d99ba132d9 am: 875d3c2990...
[platform/upstream/VK-GL-CTS.git] / framework / common / tcuInterval.hpp
1 #ifndef _TCUINTERVAL_HPP
2 #define _TCUINTERVAL_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program Tester Core
5  * ----------------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Interval arithmetic and floating point precisions.
24  *//*--------------------------------------------------------------------*/
25
26 #include "tcuDefs.hpp"
27
28 #include "deMath.h"
29
30 #include <iostream>
31 #include <limits>
32
33 #define TCU_INFINITY    (::std::numeric_limits<float>::infinity())
34 #define TCU_NAN                 (::std::numeric_limits<float>::quiet_NaN())
35
36 namespace tcu
37 {
38
39 // RAII context for temporarily changing the rounding mode
40 class ScopedRoundingMode
41 {
42 public:
43                                                         ScopedRoundingMode      (deRoundingMode mode)
44                                                                 : m_oldMode (deGetRoundingMode()) { deSetRoundingMode(mode); }
45
46                                                         ScopedRoundingMode      (void) : m_oldMode (deGetRoundingMode()) {}
47
48                                                         ~ScopedRoundingMode     (void)  { deSetRoundingMode(m_oldMode); }
49
50 private:
51                                                         ScopedRoundingMode      (const ScopedRoundingMode&);
52         ScopedRoundingMode&             operator=                       (const ScopedRoundingMode&);
53
54         const deRoundingMode    m_oldMode;
55 };
56
57 class Interval
58 {
59 public:
60                                 // Empty interval.
61                                 Interval                (void)
62                                         : m_hasNaN      (false)
63                                         , m_lo          (TCU_INFINITY)
64                                         , m_hi          (-TCU_INFINITY) {}
65
66                                 // Intentionally not explicit. Conversion from double to Interval is common
67                                 // and reasonable.
68                                 Interval                (double val)
69                                         : m_hasNaN      (!!deIsNaN(val))
70                                         , m_lo          (m_hasNaN ? TCU_INFINITY : val)
71                                         , m_hi          (m_hasNaN ? -TCU_INFINITY : val) {}
72
73                                 Interval                (bool hasNaN_, double lo_, double hi_)
74                                         : m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_) {}
75
76                                 Interval                (const Interval& a, const Interval& b)
77                                         : m_hasNaN      (a.m_hasNaN || b.m_hasNaN)
78                                         , m_lo          (de::min(a.lo(), b.lo()))
79                                         , m_hi          (de::max(a.hi(), b.hi())) {}
80
81         double          length                  (void) const { return m_hi - m_lo; }
82         double          lo                              (void) const { return m_lo; }
83         double          hi                              (void) const { return m_hi; }
84         bool            hasNaN                  (void) const { return m_hasNaN; }
85         Interval        nan                             (void) const { return m_hasNaN ? TCU_NAN : Interval(); }
86         bool            empty                   (void) const { return m_lo > m_hi; }
87         bool            isFinite                (void) const { return m_lo > -TCU_INFINITY && m_hi < TCU_INFINITY; }
88         bool            isOrdinary              (void) const { return !hasNaN() && !empty() && isFinite(); }
89
90
91         Interval        operator|               (const Interval& other) const
92         {
93                 return Interval(m_hasNaN || other.m_hasNaN,
94                                                 de::min(m_lo, other.m_lo),
95                                                 de::max(m_hi, other.m_hi));
96
97         }
98
99         Interval&       operator|=              (const Interval& other)
100         {
101                 return (*this = *this | other);
102         }
103
104         Interval        operator&               (const Interval& other) const
105         {
106                 return Interval(m_hasNaN && other.m_hasNaN,
107                                                 de::max(m_lo, other.m_lo),
108                                                 de::min(m_hi, other.m_hi));
109         }
110
111         Interval&       operator&=              (const Interval& other)
112         {
113                 return (*this = *this & other);
114         }
115
116         bool            contains                (const Interval& other) const
117         {
118                 return (other.lo() >= lo() && other.hi() <= hi() &&
119                                 (!other.hasNaN() || hasNaN()));
120         }
121
122         bool            intersects              (const Interval& other) const
123         {
124                 return ((other.hi() >= lo() && other.lo() <= hi()) ||
125                                 (other.hasNaN() && hasNaN()));
126         }
127
128         Interval        operator-               (void) const
129         {
130                 return Interval(hasNaN(), -hi(), -lo());
131         }
132
133         static Interval unbounded       (bool nan = false)
134         {
135                 return Interval(nan, -TCU_INFINITY, TCU_INFINITY);
136         }
137
138         double          midpoint                (void) const
139         {
140                 return 0.5 * (hi() + lo()); // returns NaN when not bounded
141         }
142
143         bool            operator==              (const Interval& other) const
144         {
145                 return ((m_hasNaN == other.m_hasNaN) &&
146                                 ((empty() && other.empty()) ||
147                                  (m_lo == other.m_lo && m_hi == other.m_hi)));
148         }
149
150 private:
151         bool            m_hasNaN;
152         double          m_lo;
153         double          m_hi;
154 } DE_WARN_UNUSED_TYPE;
155
156 inline Interval operator+       (const Interval& x) { return x; }
157 Interval                exp2            (const Interval& x);
158 Interval                exp                     (const Interval& x);
159 int                             sign            (const Interval& x);
160 Interval                abs                     (const Interval& x);
161 Interval                inverseSqrt     (const Interval& x);
162
163 Interval                operator+       (const Interval& x,             const Interval& y);
164 Interval                operator-       (const Interval& x,             const Interval& y);
165 Interval                operator*       (const Interval& x,             const Interval& y);
166 Interval                operator/       (const Interval& nom,   const Interval& den);
167
168 inline Interval& operator+=     (Interval& x,   const Interval& y) { return (x = x + y); }
169 inline Interval& operator-=     (Interval& x,   const Interval& y) { return (x = x - y); }
170 inline Interval& operator*=     (Interval& x,   const Interval& y) { return (x = x * y); }
171 inline Interval& operator/=     (Interval& x,   const Interval& y) { return (x = x / y); }
172
173 std::ostream&   operator<<      (std::ostream& os, const Interval& interval);
174
175 #define TCU_SET_INTERVAL_BOUNDS(DST, VAR, SETLOW, SETHIGH) do   \
176 {                                                                                                                               \
177         ::tcu::ScopedRoundingMode       VAR##_ctx_;                                             \
178         ::tcu::Interval&                        VAR##_dst_      = (DST);                        \
179         ::tcu::Interval                         VAR##_lo_;                                              \
180         ::tcu::Interval                         VAR##_hi_;                                              \
181                                                                                                                                 \
182         {                                                                                                                       \
183                 ::tcu::Interval&        (VAR) = VAR##_lo_;                                      \
184                 ::deSetRoundingMode(DE_ROUNDINGMODE_TO_NEGATIVE_INF);   \
185                 SETLOW;                                                                                                 \
186         }                                                                                                                       \
187         {                                                                                                                       \
188                 ::tcu::Interval&        (VAR) = VAR##_hi_;                                      \
189                 ::deSetRoundingMode(DE_ROUNDINGMODE_TO_POSITIVE_INF);   \
190                 SETHIGH;                                                                                                \
191         }                                                                                                                       \
192                                                                                                                                 \
193         VAR##_dst_ = VAR##_lo_ | VAR##_hi_;                                                     \
194 } while (::deGetFalse())
195
196 #define TCU_SET_INTERVAL(DST, VAR, BODY)                                                \
197         TCU_SET_INTERVAL_BOUNDS(DST, VAR, BODY, BODY)
198
199 //! Set the interval DST to the image of BODY on ARG, assuming that BODY on
200 //! ARG is a monotone function. In practice, BODY is evaluated on both the
201 //! upper and lower bound of ARG, and DST is set to the union of these
202 //! results. While evaluating BODY, PARAM is bound to the bound of ARG, and
203 //! the output of BODY should be stored in VAR.
204 #define TCU_INTERVAL_APPLY_MONOTONE1(DST, PARAM, ARG, VAR, BODY) do             \
205         {                                                                                                                                       \
206         const ::tcu::Interval&  VAR##_arg_              = (ARG);                                        \
207         ::tcu::Interval&                VAR##_dst_              = (DST);                                        \
208         ::tcu::Interval                 VAR##_lo_;                                                                      \
209         ::tcu::Interval                 VAR##_hi_;                                                                      \
210         if (VAR##_arg_.empty())                                                                                         \
211                 VAR##_dst_ = Interval();                                                                                \
212         else                                                                                                                            \
213         {                                                                                                                                       \
214                 {                                                                                                                               \
215                         const double            (PARAM) = VAR##_arg_.lo();                              \
216                         ::tcu::Interval&        (VAR)   = VAR##_lo_;                                    \
217                         BODY;                                                                                                           \
218                 }                                                                                                                               \
219                 {                                                                                                                               \
220                         const double            (PARAM) = VAR##_arg_.hi();                              \
221                         ::tcu::Interval&        (VAR)   = VAR##_hi_;                                    \
222                         BODY;                                                                                                           \
223                 }                                                                                                                               \
224                 VAR##_dst_ = VAR##_lo_ | VAR##_hi_;                                                             \
225         }                                                                                                                                       \
226         if (VAR##_arg_.hasNaN())                                                                                        \
227                 VAR##_dst_ |= TCU_NAN;                                                                                  \
228 } while (::deGetFalse())
229
230 #define TCU_INTERVAL_APPLY_MONOTONE2(DST, P0, A0, P1, A1, VAR, BODY)    \
231         TCU_INTERVAL_APPLY_MONOTONE1(                                                                           \
232                 DST, P0, A0, tmp2_,                                                                                             \
233                 TCU_INTERVAL_APPLY_MONOTONE1(tmp2_, P1, A1, VAR, BODY))
234
235 #define TCU_INTERVAL_APPLY_MONOTONE3(DST, P0, A0, P1, A1, P2, A2, VAR, BODY) \
236         TCU_INTERVAL_APPLY_MONOTONE1(                                                                           \
237                 DST, P0, A0, tmp3_,                                                                                             \
238                 TCU_INTERVAL_APPLY_MONOTONE2(tmp3_, P1, A1, P2, A2, VAR, BODY))
239
240 typedef double          DoubleFunc1                     (double);
241 typedef double          DoubleFunc2                     (double, double);
242 typedef double          DoubleFunc3                     (double, double, double);
243 typedef Interval        DoubleIntervalFunc1     (double);
244 typedef Interval        DoubleIntervalFunc2     (double, double);
245 typedef Interval        DoubleIntervalFunc3     (double, double, double);
246
247 Interval        applyMonotone   (DoubleFunc1&                   func,
248                                                          const Interval&                arg0);
249 Interval        applyMonotone   (DoubleFunc2&                   func,
250                                                          const Interval&                arg0,
251                                                          const Interval&                arg1);
252 Interval        applyMonotone   (DoubleIntervalFunc1&   func,
253                                                          const Interval&                arg0);
254 Interval        applyMonotone   (DoubleIntervalFunc2&   func,
255                                                          const Interval&                arg0,
256                                                          const Interval&                arg1);
257
258
259 } // tcu
260
261 #endif // _TCUINTERVAL_HPP