.. _program_listing_file_src_comparisons.hpp: Program Listing for File comparisons.hpp ======================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/comparisons.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* This file is part of brille. Copyright © 2020 Greg Tucker brille is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. brille is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with brille. If not, see . */ #ifndef BRILLE_COMPARISONS_HPP_ #define BRILLE_COMPARISONS_HPP_ #include #include "approx.hpp" namespace brille { enum class cmp { lt, //< less than gt, //< greater than le, //< less than or equal ge, //< greater than or equal eq, //< equal nle, //< not less than or equal nge, //< not greather than or equal neq, //< not equal le_ge, //< (less than or equal) OR (greater than or equal) }; template class Comparer{ private: bool useT; T relT; R relR; T absT; R absR; std::function scalar; std::function vector; public: Comparer(const cmp op){ // predetermine tolerances and which we should use: bool c; std::tie(c, this->useT, this->relT, this->relR, this->absT, this->absR) = brille::approx::tols(); // set the comparison function switch(op){ case cmp::lt: scalar = [&](const T& a, const R& b){ return !brille::approx::_scalar(a,b,useT,relT,relR,absT,absR) && ab; }; break; case cmp::le: scalar = [&](const T& a, const R& b){ return brille::approx::_scalar(a,b,useT,relT,relR,absT,absR) || ab; }; break; case cmp::eq: scalar = [&](const T& a, const R& b){ return brille::approx::_scalar(a,b,useT,relT,relR,absT,absR); }; break; case cmp::nle: scalar = [&](const T& a, const R& b){ return !brille::approx::_scalar(a,b,useT,relT,relR,absT,absR) && a>b; }; break; case cmp::nge: scalar = [&](const T& a, const R& b){ return !brille::approx::_scalar(a,b,useT,relT,relR,absT,absR) && ascalar(a[i*sa], b[i*sb]); return ret; }; break; // A vector IS X if all of the elements ARE X default: vector = [&](const size_t n, const T* a, const size_t sa, const R* b, const size_t sb){ bool ret{true}; for (size_t i=0; iscalar(a[i*sa], b[i*sb]); return ret; }; } } // call the comparison function for two scalars bool operator()(const T a, const R b) const {return this->scalar(a,b);} // call the comparison function for two raw vectors bool operator()(const size_t n, const T* a, const R* b) const { return this->vector(n, a, 1u, b, 1u); } // call the comparison function for two strided raw vectors bool operator()(const size_t n, const T* a, const size_t sa, const R* b, const size_t sb) const { return this->vector(n, a, sa, b, sb); } }; enum class ops { plus, //< plus minus, //< minus times, //< times rdiv, //< right divide ldiv, //< left divide }; template class RawBinaryOperator{ ops operation; std::function binop; public: RawBinaryOperator(ops op): operation(op) { switch (operation){ case ops::plus: binop = [](const T& a, const T& b){return a+b;}; break; case ops::minus: binop = [](const T& a, const T& b){return a-b;}; break; case ops::times: binop = [](const T& a, const T& b){return a*b;}; break; case ops::rdiv: binop = [](const T& a, const T& b){return a/b;}; break; case ops::ldiv: binop = [](const T& a, const T& b){return b/a;}; break; default: throw std::runtime_error("Unhandled operation!"); } } T operator()(const T a, const T b) const {return this->binop(a,b);} void operator()(const size_t n, T* c, const T* a, const T* b) const { for (size_t i=0; ibinop(a[i],b[i]); } void operator()(const size_t n, T* c, const size_t sc, const T* a, const size_t sa, const T* b, const size_t sb) const { for (size_t i=0; ibinop(a[i*sa],b[i*sb]); } }; template std::string to_string(const T& x){ return std::to_string(x); } template<> std::string to_string(const cmp& c); template<> std::string to_string(const ops& o); } // namespace brille #endif