1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Interval arithmetic.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "tcuInterval.hpp"
25 
26 #include "deMath.h"
27 
28 #include <cmath>
29 
30 namespace tcu
31 {
32 
33 using std::ldexp;
34 
applyMonotone(DoubleFunc1 & func,const Interval & arg0)35 Interval applyMonotone (DoubleFunc1& func, const Interval& arg0)
36 {
37 	Interval ret;
38 	TCU_INTERVAL_APPLY_MONOTONE1(ret, x, arg0, val,
39 								 TCU_SET_INTERVAL(val, point, point = func(x)));
40 	return ret;
41 }
42 
applyMonotone(DoubleIntervalFunc1 & func,const Interval & arg0)43 Interval applyMonotone (DoubleIntervalFunc1& func, const Interval& arg0)
44 {
45 	return Interval(func(arg0.lo()), func(arg0.hi()));
46 }
47 
applyMonotone(DoubleFunc2 & func,const Interval & arg0,const Interval & arg1)48 Interval applyMonotone (DoubleFunc2& func, const Interval& arg0, const Interval& arg1)
49 {
50 	Interval ret;
51 
52 	TCU_INTERVAL_APPLY_MONOTONE2(ret, x, arg0, y, arg1, val,
53 								 TCU_SET_INTERVAL(val, point, point = func(x, y)));
54 
55 	return ret;
56 }
57 
applyMonotone(DoubleIntervalFunc2 & func,const Interval & arg0,const Interval & arg1)58 Interval applyMonotone (DoubleIntervalFunc2& func, const Interval& arg0, const Interval& arg1)
59 {
60 	double	lo0 = arg0.lo(), hi0 = arg0.hi(), lo1 = arg1.lo(), hi1 = arg1.hi();
61 	return Interval(Interval(func(lo0, lo1), func(lo0, hi1)),
62 					Interval(func(hi0, lo1), func(hi0, hi1)));
63 }
64 
operator +(const Interval & x,const Interval & y)65 Interval operator+ (const Interval& x, const Interval& y)
66 {
67 	Interval ret;
68 
69 	if (!x.empty() && !y.empty())
70 		TCU_SET_INTERVAL_BOUNDS(ret, p, p = x.lo() + y.lo(), p = x.hi() + y.hi());
71 	if (x.hasNaN() || y.hasNaN())
72 		ret |= TCU_NAN;
73 
74 	return ret;
75 }
76 
operator -(const Interval & x,const Interval & y)77 Interval operator- (const Interval& x, const Interval& y)
78 {
79 	Interval ret;
80 
81 	TCU_INTERVAL_APPLY_MONOTONE2(ret, xp, x, yp, y, val,
82 								 TCU_SET_INTERVAL(val, point, point = xp - yp));
83 	return ret;
84 }
85 
operator *(const Interval & x,const Interval & y)86 Interval operator* (const Interval& x, const Interval& y)
87 {
88 	Interval ret;
89 
90 	TCU_INTERVAL_APPLY_MONOTONE2(ret, xp, x, yp, y, val,
91 								 TCU_SET_INTERVAL(val, point, point = xp * yp));
92 	return ret;
93 }
94 
operator /(const Interval & nom,const Interval & den)95 Interval operator/ (const Interval& nom, const Interval& den)
96 {
97 	if (den.contains(0.0))
98 	{
99 		// \todo [2014-03-21 lauri] Non-inf endpoint when one den endpoint is
100 		// zero and nom doesn't cross zero?
101 		return Interval::unbounded();
102 	}
103 	else
104 	{
105 		Interval ret;
106 
107 		TCU_INTERVAL_APPLY_MONOTONE2(ret, nomp, nom, denp, den, val,
108 									 TCU_SET_INTERVAL(val, point, point = nomp / denp));
109 		return ret;
110 	}
111 }
112 
negate(double x)113 static double negate (double x)
114 {
115 	return -x;
116 }
117 
operator -(const Interval & x)118 Interval operator- (const Interval& x)
119 {
120 	return applyMonotone(negate, x);
121 }
122 
exp2(const Interval & x)123 Interval exp2 (const Interval& x)
124 {
125 	return applyMonotone(std::pow, 2.0, x);
126 }
127 
exp(const Interval & x)128 Interval exp (const Interval& x)
129 {
130 	return applyMonotone(std::exp, x);
131 }
132 
sqrt(const Interval & x)133 Interval sqrt (const Interval& x)
134 {
135 	return applyMonotone(std::sqrt, x);
136 }
137 
inverseSqrt(const Interval & x)138 Interval inverseSqrt (const Interval& x)
139 {
140 	return 1.0 / sqrt(x);
141 }
142 
abs(const Interval & x)143 Interval abs (const Interval& x)
144 {
145 	const Interval mono = applyMonotone(std::abs, x);
146 
147 	if (x.contains(0.0))
148 		return Interval(0.0, mono);
149 
150 	return mono;
151 }
152 
operator <<(std::ostream & os,const Interval & interval)153 std::ostream& operator<< (std::ostream& os, const Interval& interval)
154 {
155 	if (interval.empty())
156 		if (interval.hasNaN())
157 			os << "[NaN]";
158 		else
159 			os << "()";
160 	else
161 		os << (interval.hasNaN() ? "~" : "")
162 		   << "[" << interval.lo() << ", " << interval.hi() << "]";
163 	return os;
164 }
165 
166 } // tcu
167