| /*------------------------------------------------------------------------- | |
| * 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 |