/*------------------------------------------------------------------------- * drawElements Quality Program Tester Core * ---------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Interval arithmetic. *//*--------------------------------------------------------------------*/ #include "tcuInterval.hpp" #include "deMath.h" #include <cmath> namespace tcu { using std::ldexp; Interval applyMonotone (DoubleFunc1& func, const Interval& arg0) { Interval ret; TCU_INTERVAL_APPLY_MONOTONE1(ret, x, arg0, val, TCU_SET_INTERVAL(val, point, point = func(x))); return ret; } Interval applyMonotone (DoubleIntervalFunc1& func, const Interval& arg0) { return Interval(func(arg0.lo()), func(arg0.hi())); } Interval applyMonotone (DoubleFunc2& func, const Interval& arg0, const Interval& arg1) { Interval ret; TCU_INTERVAL_APPLY_MONOTONE2(ret, x, arg0, y, arg1, val, TCU_SET_INTERVAL(val, point, point = func(x, y))); return ret; } Interval applyMonotone (DoubleIntervalFunc2& func, const Interval& arg0, const Interval& arg1) { double lo0 = arg0.lo(), hi0 = arg0.hi(), lo1 = arg1.lo(), hi1 = arg1.hi(); return Interval(Interval(func(lo0, lo1), func(lo0, hi1)), Interval(func(hi0, lo1), func(hi0, hi1))); } Interval operator+ (const Interval& x, const Interval& y) { Interval ret; if (!x.empty() && !y.empty()) TCU_SET_INTERVAL_BOUNDS(ret, p, p = x.lo() + y.lo(), p = x.hi() + y.hi()); if (x.hasNaN() || y.hasNaN()) ret |= TCU_NAN; return ret; } Interval operator- (const Interval& x, const Interval& y) { Interval ret; TCU_INTERVAL_APPLY_MONOTONE2(ret, xp, x, yp, y, val, TCU_SET_INTERVAL(val, point, point = xp - yp)); return ret; } Interval operator* (const Interval& x, const Interval& y) { Interval ret; TCU_INTERVAL_APPLY_MONOTONE2(ret, xp, x, yp, y, val, TCU_SET_INTERVAL(val, point, point = xp * yp)); return ret; } Interval operator/ (const Interval& nom, const Interval& den) { if (den.contains(0.0)) { // \todo [2014-03-21 lauri] Non-inf endpoint when one den endpoint is // zero and nom doesn't cross zero? return Interval::unbounded(); } else { Interval ret; TCU_INTERVAL_APPLY_MONOTONE2(ret, nomp, nom, denp, den, val, TCU_SET_INTERVAL(val, point, point = nomp / denp)); return ret; } } static double negate (double x) { return -x; } Interval operator- (const Interval& x) { return applyMonotone(negate, x); } Interval exp2 (const Interval& x) { return applyMonotone(std::pow, 2.0, x); } Interval exp (const Interval& x) { return applyMonotone(std::exp, x); } Interval sqrt (const Interval& x) { return applyMonotone(std::sqrt, x); } Interval inverseSqrt (const Interval& x) { return 1.0 / sqrt(x); } Interval abs (const Interval& x) { const Interval mono = applyMonotone(std::abs, x); if (x.contains(0.0)) return Interval(0.0, mono); return mono; } std::ostream& operator<< (std::ostream& os, const Interval& interval) { if (interval.empty()) if (interval.hasNaN()) os << "[NaN]"; else os << "()"; else os << (interval.hasNaN() ? "~" : "") << "[" << interval.lo() << ", " << interval.hi() << "]"; return os; } } // tcu