Home | History | Annotate | Download | only in common
      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 
     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 
     43 Interval applyMonotone (DoubleIntervalFunc1& func, const Interval& arg0)
     44 {
     45 	return Interval(func(arg0.lo()), func(arg0.hi()));
     46 }
     47 
     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 
     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 
     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 
     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 
     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 
     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 
    113 static double negate (double x)
    114 {
    115 	return -x;
    116 }
    117 
    118 Interval operator- (const Interval& x)
    119 {
    120 	return applyMonotone(negate, x);
    121 }
    122 
    123 Interval exp2 (const Interval& x)
    124 {
    125 	return applyMonotone(std::pow, 2.0, x);
    126 }
    127 
    128 Interval exp (const Interval& x)
    129 {
    130 	return applyMonotone(std::exp, x);
    131 }
    132 
    133 Interval sqrt (const Interval& x)
    134 {
    135 	return applyMonotone(std::sqrt, x);
    136 }
    137 
    138 Interval inverseSqrt (const Interval& x)
    139 {
    140 	return 1.0 / sqrt(x);
    141 }
    142 
    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 
    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