1 //
2 // special.hpp
3 //
4 // LGPL Version 2.1 HEADER START
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 //
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 // MA 02110-1301  USA
21 //
22 // LGPL Version 2.1 HEADER END
23 //
24 
25 //
26 // Copyright (c) 2020, Regents of the University of Minnesota.
27 // All rights reserved.
28 //
29 // Contributors:
30 //    Yaser Afshar
31 //
32 
33 #ifndef SPECIAL_HPP
34 #define SPECIAL_HPP
35 
36 #include <cmath>
37 #include <type_traits>
38 
39 /*!
40  * \file special.hpp
41  *
42  * \brief This file contains special helper functions and a Pi constant
43  *
44  * The special helper functions and a constant are:
45  * \c MY_PI Pi constant
46  * \c Square x**2, use instead of std::pow(x, 2.0)
47  * \c Cube x**3, use instead of std::pow(x, 3.0)
48  * \c PowInt optimized version of std::pow(x, n) with n being integer
49  * \c IsOne return true if the input is (close to) one within a tolerance
50  * \c IsNotOne return true if the input is not (close to) one within a tolerance
51  * \c IsZero return true if the input is (close to) zero within a tolerance
52  * \c IsNotZero return true if the input is not (close to) zero within a
53  *              tolerance
54  * \c FloatDivZero returns zero if the denominator (d) is zero in f/d
55  */
56 
57 namespace special {
58 static constexpr double MY_PI = 3.14159265358979323846;
59 
60 template <typename DataType>
61 static inline constexpr
62     typename std::enable_if<std::is_floating_point<DataType>::value,
63                             DataType>::type
Square(DataType const & x)64     Square(DataType const &x) {
65   return x * x;
66 }
67 
68 template <typename DataType>
69 static inline constexpr
70     typename std::enable_if<std::is_floating_point<DataType>::value,
71                             DataType>::type
Cube(DataType const & x)72     Cube(DataType const &x) {
73   return x * x * x;
74 }
75 
76 template <typename DataType>
77 static inline typename std::enable_if<std::is_floating_point<DataType>::value,
78                                       DataType>::type
PowInt(DataType const & x,int const n)79 PowInt(DataType const &x, int const n) {
80   if (x == 0.0) {
81     return 0.0;
82   }
83   int nn = (n > 0) ? n : -n;
84   DataType ww = x;
85   DataType yy;
86   for (yy = 1.0; nn != 0; nn >>= 1, ww *= ww) {
87     if (nn & 1) {
88       yy *= ww;
89     }
90   }
91   return (n > 0) ? yy : 1.0 / yy;
92 }
93 
94 template <typename DataType>
95 static inline constexpr
96     typename std::enable_if<std::is_floating_point<DataType>::value, bool>::type
IsOne(DataType const f,double const tol=1e-20)97     IsOne(DataType const f, double const tol = 1e-20) {
98   return std::abs(f - 1.0) < tol;
99 }
100 
101 template <typename DataType>
102 static inline constexpr
103     typename std::enable_if<std::is_floating_point<DataType>::value, bool>::type
IsNotOne(DataType const f,double const tol=1e-20)104     IsNotOne(DataType const f, double const tol = 1e-20) {
105   return std::abs(f - 1.0) >= tol;
106 }
107 
108 template <typename DataType>
109 static inline constexpr
110     typename std::enable_if<std::is_floating_point<DataType>::value, bool>::type
IsZero(DataType const f,double const tol=1e-20)111     IsZero(DataType const f, double const tol = 1e-20) {
112   return std::abs(f) < tol;
113 }
114 
115 template <typename DataType>
116 static inline constexpr
117     typename std::enable_if<std::is_floating_point<DataType>::value, bool>::type
IsNotZero(DataType const f,double const tol=1e-20)118     IsNotZero(DataType const f, double const tol = 1e-20) {
119   return std::abs(f) >= tol;
120 }
121 
122 template <typename DataType>
123 static inline constexpr
124     typename std::enable_if<std::is_floating_point<DataType>::value,
125                             DataType>::type
FloatDivZero(DataType const f,DataType const d)126     FloatDivZero(DataType const f, DataType const d) {
127   return IsZero<DataType>(d) ? 0.0 : f / d;
128 }
129 }  // namespace special
130 
131 #endif  // SPECIAL_HPP