xref: /aosp_15_r20/external/deqp/framework/common/tcuInterval.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker #ifndef _TCUINTERVAL_HPP
2*35238bceSAndroid Build Coastguard Worker #define _TCUINTERVAL_HPP
3*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Tester Core
5*35238bceSAndroid Build Coastguard Worker  * ----------------------------------------
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
8*35238bceSAndroid Build Coastguard Worker  *
9*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
10*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
11*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
14*35238bceSAndroid Build Coastguard Worker  *
15*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
16*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
17*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
19*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
20*35238bceSAndroid Build Coastguard Worker  *
21*35238bceSAndroid Build Coastguard Worker  *//*!
22*35238bceSAndroid Build Coastguard Worker  * \file
23*35238bceSAndroid Build Coastguard Worker  * \brief Interval arithmetic and floating point precisions.
24*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "tcuDefs.hpp"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
29*35238bceSAndroid Build Coastguard Worker 
30*35238bceSAndroid Build Coastguard Worker #include <iostream>
31*35238bceSAndroid Build Coastguard Worker #include <limits>
32*35238bceSAndroid Build Coastguard Worker #include <cmath>
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker #define TCU_INFINITY (::std::numeric_limits<float>::infinity())
35*35238bceSAndroid Build Coastguard Worker #define TCU_NAN (::std::numeric_limits<float>::quiet_NaN())
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker namespace tcu
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker 
40*35238bceSAndroid Build Coastguard Worker // RAII context for temporarily changing the rounding mode
41*35238bceSAndroid Build Coastguard Worker class ScopedRoundingMode
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker public:
ScopedRoundingMode(deRoundingMode mode)44*35238bceSAndroid Build Coastguard Worker     ScopedRoundingMode(deRoundingMode mode) : m_oldMode(deGetRoundingMode())
45*35238bceSAndroid Build Coastguard Worker     {
46*35238bceSAndroid Build Coastguard Worker         deSetRoundingMode(mode);
47*35238bceSAndroid Build Coastguard Worker     }
48*35238bceSAndroid Build Coastguard Worker 
ScopedRoundingMode(void)49*35238bceSAndroid Build Coastguard Worker     ScopedRoundingMode(void) : m_oldMode(deGetRoundingMode())
50*35238bceSAndroid Build Coastguard Worker     {
51*35238bceSAndroid Build Coastguard Worker     }
52*35238bceSAndroid Build Coastguard Worker 
~ScopedRoundingMode(void)53*35238bceSAndroid Build Coastguard Worker     ~ScopedRoundingMode(void)
54*35238bceSAndroid Build Coastguard Worker     {
55*35238bceSAndroid Build Coastguard Worker         deSetRoundingMode(m_oldMode);
56*35238bceSAndroid Build Coastguard Worker     }
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker private:
59*35238bceSAndroid Build Coastguard Worker     ScopedRoundingMode(const ScopedRoundingMode &);
60*35238bceSAndroid Build Coastguard Worker     ScopedRoundingMode &operator=(const ScopedRoundingMode &);
61*35238bceSAndroid Build Coastguard Worker 
62*35238bceSAndroid Build Coastguard Worker     const deRoundingMode m_oldMode;
63*35238bceSAndroid Build Coastguard Worker };
64*35238bceSAndroid Build Coastguard Worker 
65*35238bceSAndroid Build Coastguard Worker class Interval
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker public:
68*35238bceSAndroid Build Coastguard Worker     // Empty interval.
Interval(void)69*35238bceSAndroid Build Coastguard Worker     Interval(void)
70*35238bceSAndroid Build Coastguard Worker         : m_hasNaN(false)
71*35238bceSAndroid Build Coastguard Worker         , m_lo(TCU_INFINITY)
72*35238bceSAndroid Build Coastguard Worker         , m_hi(-TCU_INFINITY)
73*35238bceSAndroid Build Coastguard Worker         , m_warningLo(-TCU_INFINITY)
74*35238bceSAndroid Build Coastguard Worker         , m_warningHi(TCU_INFINITY)
75*35238bceSAndroid Build Coastguard Worker     {
76*35238bceSAndroid Build Coastguard Worker     }
77*35238bceSAndroid Build Coastguard Worker 
78*35238bceSAndroid Build Coastguard Worker     // Intentionally not explicit. Conversion from double to Interval is common
79*35238bceSAndroid Build Coastguard Worker     // and reasonable.
Interval(double val)80*35238bceSAndroid Build Coastguard Worker     Interval(double val)
81*35238bceSAndroid Build Coastguard Worker         : m_hasNaN(!!deIsNaN(val))
82*35238bceSAndroid Build Coastguard Worker         , m_lo(m_hasNaN ? TCU_INFINITY : val)
83*35238bceSAndroid Build Coastguard Worker         , m_hi(m_hasNaN ? -TCU_INFINITY : val)
84*35238bceSAndroid Build Coastguard Worker         , m_warningLo(-TCU_INFINITY)
85*35238bceSAndroid Build Coastguard Worker         , m_warningHi(TCU_INFINITY)
86*35238bceSAndroid Build Coastguard Worker     {
87*35238bceSAndroid Build Coastguard Worker     }
88*35238bceSAndroid Build Coastguard Worker 
Interval(bool hasNaN_,double lo_,double hi_)89*35238bceSAndroid Build Coastguard Worker     Interval(bool hasNaN_, double lo_, double hi_)
90*35238bceSAndroid Build Coastguard Worker         : m_hasNaN(hasNaN_)
91*35238bceSAndroid Build Coastguard Worker         , m_lo(lo_)
92*35238bceSAndroid Build Coastguard Worker         , m_hi(hi_)
93*35238bceSAndroid Build Coastguard Worker         , m_warningLo(-TCU_INFINITY)
94*35238bceSAndroid Build Coastguard Worker         , m_warningHi(TCU_INFINITY)
95*35238bceSAndroid Build Coastguard Worker     {
96*35238bceSAndroid Build Coastguard Worker     }
97*35238bceSAndroid Build Coastguard Worker 
Interval(bool hasNaN_,double lo_,double hi_,double wlo_,double whi_)98*35238bceSAndroid Build Coastguard Worker     Interval(bool hasNaN_, double lo_, double hi_, double wlo_, double whi_)
99*35238bceSAndroid Build Coastguard Worker         : m_hasNaN(hasNaN_)
100*35238bceSAndroid Build Coastguard Worker         , m_lo(lo_)
101*35238bceSAndroid Build Coastguard Worker         , m_hi(hi_)
102*35238bceSAndroid Build Coastguard Worker         , m_warningLo(wlo_)
103*35238bceSAndroid Build Coastguard Worker         , m_warningHi(whi_)
104*35238bceSAndroid Build Coastguard Worker     {
105*35238bceSAndroid Build Coastguard Worker     }
106*35238bceSAndroid Build Coastguard Worker 
Interval(const Interval & a,const Interval & b)107*35238bceSAndroid Build Coastguard Worker     Interval(const Interval &a, const Interval &b)
108*35238bceSAndroid Build Coastguard Worker         : m_hasNaN(a.m_hasNaN || b.m_hasNaN)
109*35238bceSAndroid Build Coastguard Worker         , m_lo(de::min(a.lo(), b.lo()))
110*35238bceSAndroid Build Coastguard Worker         , m_hi(de::max(a.hi(), b.hi()))
111*35238bceSAndroid Build Coastguard Worker         , m_warningLo(de::min(a.warningLo(), b.warningLo()))
112*35238bceSAndroid Build Coastguard Worker         , m_warningHi(de::max(a.warningHi(), b.warningHi()))
113*35238bceSAndroid Build Coastguard Worker     {
114*35238bceSAndroid Build Coastguard Worker     }
115*35238bceSAndroid Build Coastguard Worker 
length(void) const116*35238bceSAndroid Build Coastguard Worker     double length(void) const
117*35238bceSAndroid Build Coastguard Worker     {
118*35238bceSAndroid Build Coastguard Worker         return m_hi - m_lo;
119*35238bceSAndroid Build Coastguard Worker     }
lo(void) const120*35238bceSAndroid Build Coastguard Worker     double lo(void) const
121*35238bceSAndroid Build Coastguard Worker     {
122*35238bceSAndroid Build Coastguard Worker         return m_lo;
123*35238bceSAndroid Build Coastguard Worker     }
hi(void) const124*35238bceSAndroid Build Coastguard Worker     double hi(void) const
125*35238bceSAndroid Build Coastguard Worker     {
126*35238bceSAndroid Build Coastguard Worker         return m_hi;
127*35238bceSAndroid Build Coastguard Worker     }
warningLo(void) const128*35238bceSAndroid Build Coastguard Worker     double warningLo(void) const
129*35238bceSAndroid Build Coastguard Worker     {
130*35238bceSAndroid Build Coastguard Worker         return m_warningLo;
131*35238bceSAndroid Build Coastguard Worker     }
warningHi(void) const132*35238bceSAndroid Build Coastguard Worker     double warningHi(void) const
133*35238bceSAndroid Build Coastguard Worker     {
134*35238bceSAndroid Build Coastguard Worker         return m_warningHi;
135*35238bceSAndroid Build Coastguard Worker     }
hasNaN(void) const136*35238bceSAndroid Build Coastguard Worker     bool hasNaN(void) const
137*35238bceSAndroid Build Coastguard Worker     {
138*35238bceSAndroid Build Coastguard Worker         return m_hasNaN;
139*35238bceSAndroid Build Coastguard Worker     }
nan(void) const140*35238bceSAndroid Build Coastguard Worker     Interval nan(void) const
141*35238bceSAndroid Build Coastguard Worker     {
142*35238bceSAndroid Build Coastguard Worker         return m_hasNaN ? TCU_NAN : Interval();
143*35238bceSAndroid Build Coastguard Worker     }
empty(void) const144*35238bceSAndroid Build Coastguard Worker     bool empty(void) const
145*35238bceSAndroid Build Coastguard Worker     {
146*35238bceSAndroid Build Coastguard Worker         return m_lo > m_hi;
147*35238bceSAndroid Build Coastguard Worker     }
148*35238bceSAndroid Build Coastguard Worker 
149*35238bceSAndroid Build Coastguard Worker     // The interval is represented in double, it can extend outside the range of smaller floating-point formats
150*35238bceSAndroid Build Coastguard Worker     // and get rounded to infinity.
isFinite(double maxValue) const151*35238bceSAndroid Build Coastguard Worker     bool isFinite(double maxValue) const
152*35238bceSAndroid Build Coastguard Worker     {
153*35238bceSAndroid Build Coastguard Worker         return m_lo > -maxValue && m_hi < maxValue;
154*35238bceSAndroid Build Coastguard Worker     }
isOrdinary(double maxValue) const155*35238bceSAndroid Build Coastguard Worker     bool isOrdinary(double maxValue) const
156*35238bceSAndroid Build Coastguard Worker     {
157*35238bceSAndroid Build Coastguard Worker         return !hasNaN() && !empty() && isFinite(maxValue);
158*35238bceSAndroid Build Coastguard Worker     }
159*35238bceSAndroid Build Coastguard Worker 
warning(double lo_,double hi_)160*35238bceSAndroid Build Coastguard Worker     void warning(double lo_, double hi_)
161*35238bceSAndroid Build Coastguard Worker     {
162*35238bceSAndroid Build Coastguard Worker         m_warningLo = lo_;
163*35238bceSAndroid Build Coastguard Worker         m_warningHi = hi_;
164*35238bceSAndroid Build Coastguard Worker     }
165*35238bceSAndroid Build Coastguard Worker 
operator |(const Interval & other) const166*35238bceSAndroid Build Coastguard Worker     Interval operator|(const Interval &other) const
167*35238bceSAndroid Build Coastguard Worker     {
168*35238bceSAndroid Build Coastguard Worker         return Interval(m_hasNaN || other.m_hasNaN, de::min(m_lo, other.m_lo), de::max(m_hi, other.m_hi),
169*35238bceSAndroid Build Coastguard Worker                         de::min(m_warningLo, other.m_warningLo), de::max(m_warningHi, other.m_warningHi));
170*35238bceSAndroid Build Coastguard Worker     }
171*35238bceSAndroid Build Coastguard Worker 
operator |=(const Interval & other)172*35238bceSAndroid Build Coastguard Worker     Interval &operator|=(const Interval &other)
173*35238bceSAndroid Build Coastguard Worker     {
174*35238bceSAndroid Build Coastguard Worker         return (*this = *this | other);
175*35238bceSAndroid Build Coastguard Worker     }
176*35238bceSAndroid Build Coastguard Worker 
operator &(const Interval & other) const177*35238bceSAndroid Build Coastguard Worker     Interval operator&(const Interval &other) const
178*35238bceSAndroid Build Coastguard Worker     {
179*35238bceSAndroid Build Coastguard Worker         return Interval(m_hasNaN && other.m_hasNaN, de::max(m_lo, other.m_lo), de::min(m_hi, other.m_hi),
180*35238bceSAndroid Build Coastguard Worker                         de::max(m_warningLo, other.m_warningLo), de::min(m_warningHi, other.m_warningHi));
181*35238bceSAndroid Build Coastguard Worker     }
182*35238bceSAndroid Build Coastguard Worker 
operator &=(const Interval & other)183*35238bceSAndroid Build Coastguard Worker     Interval &operator&=(const Interval &other)
184*35238bceSAndroid Build Coastguard Worker     {
185*35238bceSAndroid Build Coastguard Worker         return (*this = *this & other);
186*35238bceSAndroid Build Coastguard Worker     }
187*35238bceSAndroid Build Coastguard Worker 
contains(const Interval & other) const188*35238bceSAndroid Build Coastguard Worker     bool contains(const Interval &other) const
189*35238bceSAndroid Build Coastguard Worker     {
190*35238bceSAndroid Build Coastguard Worker         return (other.lo() >= lo() && other.hi() <= hi() && (!other.hasNaN() || hasNaN()));
191*35238bceSAndroid Build Coastguard Worker     }
192*35238bceSAndroid Build Coastguard Worker 
containsWarning(const Interval & other) const193*35238bceSAndroid Build Coastguard Worker     bool containsWarning(const Interval &other) const
194*35238bceSAndroid Build Coastguard Worker     {
195*35238bceSAndroid Build Coastguard Worker         return (other.lo() >= warningLo() && other.hi() <= warningHi() && (!other.hasNaN() || hasNaN()));
196*35238bceSAndroid Build Coastguard Worker     }
197*35238bceSAndroid Build Coastguard Worker 
intersects(const Interval & other) const198*35238bceSAndroid Build Coastguard Worker     bool intersects(const Interval &other) const
199*35238bceSAndroid Build Coastguard Worker     {
200*35238bceSAndroid Build Coastguard Worker         return ((other.hi() >= lo() && other.lo() <= hi()) || (other.hasNaN() && hasNaN()));
201*35238bceSAndroid Build Coastguard Worker     }
202*35238bceSAndroid Build Coastguard Worker 
operator -(void) const203*35238bceSAndroid Build Coastguard Worker     Interval operator-(void) const
204*35238bceSAndroid Build Coastguard Worker     {
205*35238bceSAndroid Build Coastguard Worker         return Interval(hasNaN(), -hi(), -lo(), -warningHi(), -warningLo());
206*35238bceSAndroid Build Coastguard Worker     }
207*35238bceSAndroid Build Coastguard Worker 
unbounded(bool nan=false)208*35238bceSAndroid Build Coastguard Worker     static Interval unbounded(bool nan = false)
209*35238bceSAndroid Build Coastguard Worker     {
210*35238bceSAndroid Build Coastguard Worker         return Interval(nan, -TCU_INFINITY, TCU_INFINITY);
211*35238bceSAndroid Build Coastguard Worker     }
212*35238bceSAndroid Build Coastguard Worker 
midpoint(void) const213*35238bceSAndroid Build Coastguard Worker     double midpoint(void) const
214*35238bceSAndroid Build Coastguard Worker     {
215*35238bceSAndroid Build Coastguard Worker         const double h = hi();
216*35238bceSAndroid Build Coastguard Worker         const double l = lo();
217*35238bceSAndroid Build Coastguard Worker 
218*35238bceSAndroid Build Coastguard Worker         if (h == -l)
219*35238bceSAndroid Build Coastguard Worker             return 0.0;
220*35238bceSAndroid Build Coastguard Worker         if (l == -TCU_INFINITY)
221*35238bceSAndroid Build Coastguard Worker             return -TCU_INFINITY;
222*35238bceSAndroid Build Coastguard Worker         if (h == TCU_INFINITY)
223*35238bceSAndroid Build Coastguard Worker             return TCU_INFINITY;
224*35238bceSAndroid Build Coastguard Worker 
225*35238bceSAndroid Build Coastguard Worker         const bool negativeH = ::std::signbit(h);
226*35238bceSAndroid Build Coastguard Worker         const bool negativeL = ::std::signbit(l);
227*35238bceSAndroid Build Coastguard Worker         double ret;
228*35238bceSAndroid Build Coastguard Worker 
229*35238bceSAndroid Build Coastguard Worker         if (negativeH != negativeL)
230*35238bceSAndroid Build Coastguard Worker         {
231*35238bceSAndroid Build Coastguard Worker             // Different signs. Adding both values should be safe.
232*35238bceSAndroid Build Coastguard Worker             ret = (h + l) * 0.5;
233*35238bceSAndroid Build Coastguard Worker         }
234*35238bceSAndroid Build Coastguard Worker         else
235*35238bceSAndroid Build Coastguard Worker         {
236*35238bceSAndroid Build Coastguard Worker             // Same sign. Substracting low from high should be safe.
237*35238bceSAndroid Build Coastguard Worker             ret = l + (h - l) * 0.5;
238*35238bceSAndroid Build Coastguard Worker         }
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker         return ret;
241*35238bceSAndroid Build Coastguard Worker     }
242*35238bceSAndroid Build Coastguard Worker 
operator ==(const Interval & other) const243*35238bceSAndroid Build Coastguard Worker     bool operator==(const Interval &other) const
244*35238bceSAndroid Build Coastguard Worker     {
245*35238bceSAndroid Build Coastguard Worker         return ((m_hasNaN == other.m_hasNaN) &&
246*35238bceSAndroid Build Coastguard Worker                 ((empty() && other.empty()) || (m_lo == other.m_lo && m_hi == other.m_hi)));
247*35238bceSAndroid Build Coastguard Worker     }
248*35238bceSAndroid Build Coastguard Worker 
249*35238bceSAndroid Build Coastguard Worker private:
250*35238bceSAndroid Build Coastguard Worker     bool m_hasNaN;
251*35238bceSAndroid Build Coastguard Worker     double m_lo;
252*35238bceSAndroid Build Coastguard Worker     double m_hi;
253*35238bceSAndroid Build Coastguard Worker     double m_warningLo;
254*35238bceSAndroid Build Coastguard Worker     double m_warningHi;
255*35238bceSAndroid Build Coastguard Worker } DE_WARN_UNUSED_TYPE;
256*35238bceSAndroid Build Coastguard Worker 
operator +(const Interval & x)257*35238bceSAndroid Build Coastguard Worker inline Interval operator+(const Interval &x)
258*35238bceSAndroid Build Coastguard Worker {
259*35238bceSAndroid Build Coastguard Worker     return x;
260*35238bceSAndroid Build Coastguard Worker }
261*35238bceSAndroid Build Coastguard Worker Interval exp2(const Interval &x);
262*35238bceSAndroid Build Coastguard Worker Interval exp(const Interval &x);
263*35238bceSAndroid Build Coastguard Worker int sign(const Interval &x);
264*35238bceSAndroid Build Coastguard Worker Interval abs(const Interval &x);
265*35238bceSAndroid Build Coastguard Worker Interval inverseSqrt(const Interval &x);
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker Interval operator+(const Interval &x, const Interval &y);
268*35238bceSAndroid Build Coastguard Worker Interval operator-(const Interval &x, const Interval &y);
269*35238bceSAndroid Build Coastguard Worker Interval operator*(const Interval &x, const Interval &y);
270*35238bceSAndroid Build Coastguard Worker Interval operator/(const Interval &nom, const Interval &den);
271*35238bceSAndroid Build Coastguard Worker 
operator +=(Interval & x,const Interval & y)272*35238bceSAndroid Build Coastguard Worker inline Interval &operator+=(Interval &x, const Interval &y)
273*35238bceSAndroid Build Coastguard Worker {
274*35238bceSAndroid Build Coastguard Worker     return (x = x + y);
275*35238bceSAndroid Build Coastguard Worker }
operator -=(Interval & x,const Interval & y)276*35238bceSAndroid Build Coastguard Worker inline Interval &operator-=(Interval &x, const Interval &y)
277*35238bceSAndroid Build Coastguard Worker {
278*35238bceSAndroid Build Coastguard Worker     return (x = x - y);
279*35238bceSAndroid Build Coastguard Worker }
operator *=(Interval & x,const Interval & y)280*35238bceSAndroid Build Coastguard Worker inline Interval &operator*=(Interval &x, const Interval &y)
281*35238bceSAndroid Build Coastguard Worker {
282*35238bceSAndroid Build Coastguard Worker     return (x = x * y);
283*35238bceSAndroid Build Coastguard Worker }
operator /=(Interval & x,const Interval & y)284*35238bceSAndroid Build Coastguard Worker inline Interval &operator/=(Interval &x, const Interval &y)
285*35238bceSAndroid Build Coastguard Worker {
286*35238bceSAndroid Build Coastguard Worker     return (x = x / y);
287*35238bceSAndroid Build Coastguard Worker }
288*35238bceSAndroid Build Coastguard Worker 
289*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const Interval &interval);
290*35238bceSAndroid Build Coastguard Worker 
291*35238bceSAndroid Build Coastguard Worker #define TCU_SET_INTERVAL_BOUNDS(DST, VAR, SETLOW, SETHIGH)        \
292*35238bceSAndroid Build Coastguard Worker     do                                                            \
293*35238bceSAndroid Build Coastguard Worker     {                                                             \
294*35238bceSAndroid Build Coastguard Worker         DE_FENV_ACCESS_ON                                         \
295*35238bceSAndroid Build Coastguard Worker         ::tcu::ScopedRoundingMode VAR##_ctx_;                     \
296*35238bceSAndroid Build Coastguard Worker         ::tcu::Interval &VAR##_dst_ = (DST);                      \
297*35238bceSAndroid Build Coastguard Worker         ::tcu::Interval VAR##_lo_;                                \
298*35238bceSAndroid Build Coastguard Worker         ::tcu::Interval VAR##_hi_;                                \
299*35238bceSAndroid Build Coastguard Worker                                                                   \
300*35238bceSAndroid Build Coastguard Worker         {                                                         \
301*35238bceSAndroid Build Coastguard Worker             ::tcu::Interval &VAR = VAR##_lo_;                     \
302*35238bceSAndroid Build Coastguard Worker             ::deSetRoundingMode(DE_ROUNDINGMODE_TO_NEGATIVE_INF); \
303*35238bceSAndroid Build Coastguard Worker             SETLOW;                                               \
304*35238bceSAndroid Build Coastguard Worker         }                                                         \
305*35238bceSAndroid Build Coastguard Worker         {                                                         \
306*35238bceSAndroid Build Coastguard Worker             ::tcu::Interval &VAR = VAR##_hi_;                     \
307*35238bceSAndroid Build Coastguard Worker             ::deSetRoundingMode(DE_ROUNDINGMODE_TO_POSITIVE_INF); \
308*35238bceSAndroid Build Coastguard Worker             SETHIGH;                                              \
309*35238bceSAndroid Build Coastguard Worker         }                                                         \
310*35238bceSAndroid Build Coastguard Worker                                                                   \
311*35238bceSAndroid Build Coastguard Worker         VAR##_dst_ = VAR##_lo_ | VAR##_hi_;                       \
312*35238bceSAndroid Build Coastguard Worker     } while (false)
313*35238bceSAndroid Build Coastguard Worker 
314*35238bceSAndroid Build Coastguard Worker #define TCU_SET_INTERVAL(DST, VAR, BODY) TCU_SET_INTERVAL_BOUNDS(DST, VAR, BODY, BODY)
315*35238bceSAndroid Build Coastguard Worker 
316*35238bceSAndroid Build Coastguard Worker //! Set the interval DST to the image of BODY on ARG, assuming that BODY on
317*35238bceSAndroid Build Coastguard Worker //! ARG is a monotone function. In practice, BODY is evaluated on both the
318*35238bceSAndroid Build Coastguard Worker //! upper and lower bound of ARG, and DST is set to the union of these
319*35238bceSAndroid Build Coastguard Worker //! results. While evaluating BODY, PARAM is bound to the bound of ARG, and
320*35238bceSAndroid Build Coastguard Worker //! the output of BODY should be stored in VAR.
321*35238bceSAndroid Build Coastguard Worker #define TCU_INTERVAL_APPLY_MONOTONE1(DST, PARAM, ARG, VAR, BODY) \
322*35238bceSAndroid Build Coastguard Worker     do                                                           \
323*35238bceSAndroid Build Coastguard Worker     {                                                            \
324*35238bceSAndroid Build Coastguard Worker         const ::tcu::Interval &VAR##_arg_ = (ARG);               \
325*35238bceSAndroid Build Coastguard Worker         ::tcu::Interval &VAR##_dst_       = (DST);               \
326*35238bceSAndroid Build Coastguard Worker         ::tcu::Interval VAR##_lo_;                               \
327*35238bceSAndroid Build Coastguard Worker         ::tcu::Interval VAR##_hi_;                               \
328*35238bceSAndroid Build Coastguard Worker         if (VAR##_arg_.empty())                                  \
329*35238bceSAndroid Build Coastguard Worker             VAR##_dst_ = Interval();                             \
330*35238bceSAndroid Build Coastguard Worker         else                                                     \
331*35238bceSAndroid Build Coastguard Worker         {                                                        \
332*35238bceSAndroid Build Coastguard Worker             {                                                    \
333*35238bceSAndroid Build Coastguard Worker                 const double PARAM   = VAR##_arg_.lo();          \
334*35238bceSAndroid Build Coastguard Worker                 ::tcu::Interval &VAR = VAR##_lo_;                \
335*35238bceSAndroid Build Coastguard Worker                 BODY;                                            \
336*35238bceSAndroid Build Coastguard Worker             }                                                    \
337*35238bceSAndroid Build Coastguard Worker             {                                                    \
338*35238bceSAndroid Build Coastguard Worker                 const double PARAM   = VAR##_arg_.hi();          \
339*35238bceSAndroid Build Coastguard Worker                 ::tcu::Interval &VAR = VAR##_hi_;                \
340*35238bceSAndroid Build Coastguard Worker                 BODY;                                            \
341*35238bceSAndroid Build Coastguard Worker             }                                                    \
342*35238bceSAndroid Build Coastguard Worker             VAR##_dst_ = VAR##_lo_ | VAR##_hi_;                  \
343*35238bceSAndroid Build Coastguard Worker         }                                                        \
344*35238bceSAndroid Build Coastguard Worker         if (VAR##_arg_.hasNaN())                                 \
345*35238bceSAndroid Build Coastguard Worker             VAR##_dst_ |= TCU_NAN;                               \
346*35238bceSAndroid Build Coastguard Worker     } while (false)
347*35238bceSAndroid Build Coastguard Worker 
348*35238bceSAndroid Build Coastguard Worker #define TCU_INTERVAL_APPLY_MONOTONE2(DST, P0, A0, P1, A1, VAR, BODY) \
349*35238bceSAndroid Build Coastguard Worker     TCU_INTERVAL_APPLY_MONOTONE1(DST, P0, A0, tmp2_, TCU_INTERVAL_APPLY_MONOTONE1(tmp2_, P1, A1, VAR, BODY))
350*35238bceSAndroid Build Coastguard Worker 
351*35238bceSAndroid Build Coastguard Worker #define TCU_INTERVAL_APPLY_MONOTONE3(DST, P0, A0, P1, A1, P2, A2, VAR, BODY) \
352*35238bceSAndroid Build Coastguard Worker     TCU_INTERVAL_APPLY_MONOTONE1(DST, P0, A0, tmp3_, TCU_INTERVAL_APPLY_MONOTONE2(tmp3_, P1, A1, P2, A2, VAR, BODY))
353*35238bceSAndroid Build Coastguard Worker 
354*35238bceSAndroid Build Coastguard Worker typedef double DoubleFunc1(double);
355*35238bceSAndroid Build Coastguard Worker typedef double DoubleFunc2(double, double);
356*35238bceSAndroid Build Coastguard Worker typedef double DoubleFunc3(double, double, double);
357*35238bceSAndroid Build Coastguard Worker typedef Interval DoubleIntervalFunc1(double);
358*35238bceSAndroid Build Coastguard Worker typedef Interval DoubleIntervalFunc2(double, double);
359*35238bceSAndroid Build Coastguard Worker typedef Interval DoubleIntervalFunc3(double, double, double);
360*35238bceSAndroid Build Coastguard Worker 
361*35238bceSAndroid Build Coastguard Worker Interval applyMonotone(DoubleFunc1 &func, const Interval &arg0);
362*35238bceSAndroid Build Coastguard Worker Interval applyMonotone(DoubleFunc2 &func, const Interval &arg0, const Interval &arg1);
363*35238bceSAndroid Build Coastguard Worker Interval applyMonotone(DoubleIntervalFunc1 &func, const Interval &arg0);
364*35238bceSAndroid Build Coastguard Worker Interval applyMonotone(DoubleIntervalFunc2 &func, const Interval &arg0, const Interval &arg1);
365*35238bceSAndroid Build Coastguard Worker 
366*35238bceSAndroid Build Coastguard Worker } // namespace tcu
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker #endif // _TCUINTERVAL_HPP
369