A library for working with phylogenetic and population genetic data.
v0.32.0
common.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_MATH_COMMON_H_
2 #define GENESIS_UTILS_MATH_COMMON_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2023 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
34 #include <algorithm>
35 #include <cassert>
36 #include <cmath>
37 #include <cstdint>
38 #include <functional>
39 #include <limits>
40 #include <stdexcept>
41 #include <type_traits>
42 #include <utility>
43 #include <vector>
44 
45 namespace genesis {
46 namespace utils {
47 
48 // =================================================================================================
49 // Constants and General Functions
50 // =================================================================================================
51 
55 constexpr double PI = 3.141592653589793238463;
56 
57 inline double circumference( double radius )
58 {
59  return 2.0 * PI * radius;
60 }
61 
62 // =================================================================================================
63 // Number Handling
64 // =================================================================================================
65 
69 template <typename T> inline
70 void ascending( T& f, T& s )
71 {
72  if( f > s ) {
73  std::swap( f, s );
74  }
75 }
76 
80 template <typename T> inline
81 void descending( T& f, T& s )
82 {
83  if( f < s ) {
84  std::swap( f, s );
85  }
86 }
87 
94 template< typename T > inline constexpr
95 T abs_diff( T const& lhs, T const& rhs )
96 {
97  return ((lhs > rhs) ? (lhs - rhs) : (rhs - lhs));
98 }
99 
103 template <typename T> inline constexpr
104 int signum(T x, std::false_type )
105 {
106  // The tag type `std::false_type` is unnamed in order to avoid compiler warnings about an
107  // unused parameter. As this function is `constexpr`, we cannot shut this warning down by
108  // using `(void) param`, so making it unnamed is a reasonable solution in this case.
109  return T(0) < x;
110 }
111 
115 template <typename T> inline constexpr
116 int signum(T x, std::true_type )
117 {
118  // The tag type `std::false_type` is unnamed in order to avoid compiler warnings about an
119  // unused parameter. As this function is `constexpr`, we cannot shut this warning down by
120  // using `(void) param`, so making it unnamed is a reasonable solution in this case.
121  return (T(0) < x) - (x < T(0));
122 }
123 
132 template <typename T> inline constexpr
133 int signum(T x)
134 {
135  return signum( x, std::is_signed<T>() );
136 }
137 
144 template <typename T, typename U>
145 inline constexpr int compare_threeway( T lhs, U rhs )
146 {
147  // Branchless comparison of the values
148  // https://stackoverflow.com/a/10997428/4184258
149  static_assert( static_cast<int>( false ) == 0, "static_cast<int>( false ) != 0" );
150  static_assert( static_cast<int>( true ) == 1, "static_cast<int>( true ) != 1" );
151  return static_cast<int>( lhs > rhs ) - static_cast<int>( lhs < rhs );
152 }
153 
158  double lhs,
159  double rhs,
160  double max_rel_diff = std::numeric_limits<double>::epsilon()
161 ) {
162  // Calculate the difference.
163  auto diff = std::abs( lhs - rhs );
164 
165  // Find the larger number.
166  auto largest = std::max( std::abs( lhs ), std::abs( rhs ));
167 
168  // Do the comparison.
169  return ( diff <= largest * max_rel_diff );
170 }
171 
175 inline double round_to( double x, size_t accuracy_order )
176 {
177  double factor = std::pow( 10, accuracy_order );
178  return std::round( x * factor ) / factor;
179 }
180 
191 inline size_t int_pow( size_t base, size_t exp )
192 {
193  // Using Exponentiation by squaring, see
194  // http://stackoverflow.com/a/101613/4184258
195  size_t result = 1;
196  while( exp ) {
197  if( exp & 1 ) {
198  result *= base;
199  }
200  exp >>= 1;
201  base *= base;
202  }
203  return result;
204 }
205 
211 inline bool is_valid_int_pow( size_t base, size_t exp )
212 {
213  return std::pow( base, exp ) < static_cast<double>( std::numeric_limits<size_t>::max() );
214 }
215 
223 inline constexpr double squared( double x )
224 {
225  return x * x;
226 }
227 
235 inline constexpr double cubed( double x )
236 {
237  return x * x * x;
238 }
239 
240 // =================================================================================================
241 // Helper Functions
242 // =================================================================================================
243 
251 template <class ForwardIteratorA, class ForwardIteratorB>
252 std::pair<std::vector<double>, std::vector<double>> finite_pairs(
253  ForwardIteratorA first_a, ForwardIteratorA last_a,
254  ForwardIteratorB first_b, ForwardIteratorB last_b
255 ) {
256  // Prepare result.
257  std::vector<double> vec_a;
258  std::vector<double> vec_b;
259 
260  // Iterate in parallel.
261  while( first_a != last_a && first_b != last_b ) {
262  if( std::isfinite( *first_a ) && std::isfinite( *first_b ) ) {
263  vec_a.push_back( *first_a );
264  vec_b.push_back( *first_b );
265  }
266  ++first_a;
267  ++first_b;
268  }
269  if( first_a != last_a || first_b != last_b ) {
270  throw std::runtime_error(
271  "Ranges need to have same length."
272  );
273  }
274 
275  assert( vec_a.size() == vec_b.size() );
276  return { vec_a, vec_b };
277 }
278 
285 template <class ForwardIteratorA, class ForwardIteratorB>
287  ForwardIteratorA first_a, ForwardIteratorA last_a,
288  ForwardIteratorB first_b, ForwardIteratorB last_b,
289  std::function<void( double value_a, double value_b )> execute
290 ) {
291  // Iterate in parallel.
292  while( first_a != last_a && first_b != last_b ) {
293  if( std::isfinite( *first_a ) && std::isfinite( *first_b ) ) {
294  execute( *first_a, *first_b );
295  }
296  ++first_a;
297  ++first_b;
298  }
299 
300  // Check if the ranges have the same length.
301  if( first_a != last_a || first_b != last_b ) {
302  throw std::runtime_error( "Ranges need to have same length." );
303  }
304 }
305 
306 } // namespace utils
307 } // namespace genesis
308 
309 #endif // include guard
genesis::placement::swap
void swap(Sample &lhs, Sample &rhs)
Definition: sample.cpp:104
genesis::utils::compare_threeway
constexpr int compare_threeway(T lhs, U rhs)
Three-way comparison (spaceship operator) for C++ <20.
Definition: common.hpp:145
genesis::utils::abs_diff
constexpr T abs_diff(T const &lhs, T const &rhs)
Calculate the absolute differenence between two values.
Definition: common.hpp:95
genesis::utils::signum
constexpr int signum(T x, std::false_type)
Implementation of signum(T x) for unsigned types. See there for details.
Definition: common.hpp:104
genesis::utils::almost_equal_relative
bool almost_equal_relative(double lhs, double rhs, double max_rel_diff=std::numeric_limits< double >::epsilon())
Check whether two doubles are almost equal, using a relative epsilon to compare them.
Definition: common.hpp:157
genesis::utils::cubed
constexpr double cubed(double x)
Cube of a number.
Definition: common.hpp:235
genesis::utils::circumference
double circumference(double radius)
Definition: common.hpp:57
genesis::utils::int_pow
size_t int_pow(size_t base, size_t exp)
Calculate the power base^exp for positive integer values.
Definition: common.hpp:191
genesis::utils::finite_pairs
std::pair< std::vector< double >, std::vector< double > > finite_pairs(ForwardIteratorA first_a, ForwardIteratorA last_a, ForwardIteratorB first_b, ForwardIteratorB last_b)
Helper function that cleans two ranges of double of the same length from non-finite values.
Definition: common.hpp:252
genesis::utils::PI
constexpr double PI
Make the world go round.
Definition: common.hpp:55
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::descending
void descending(T &f, T &s)
Sort two values in descending order, inplace.
Definition: common.hpp:81
genesis::utils::ascending
void ascending(T &f, T &s)
Sort two values in ascending order, inplace.
Definition: common.hpp:70
genesis::utils::is_valid_int_pow
bool is_valid_int_pow(size_t base, size_t exp)
Return whether the given power can be stored within a size_t.
Definition: common.hpp:211
genesis::utils::for_each_finite_pair
void for_each_finite_pair(ForwardIteratorA first_a, ForwardIteratorA last_a, ForwardIteratorB first_b, ForwardIteratorB last_b, std::function< void(double value_a, double value_b)> execute)
Iterate two ranges of double values in parallel, and execute a function for each pair of values from ...
Definition: common.hpp:286
genesis::utils::squared
constexpr double squared(double x)
Square of a number.
Definition: common.hpp:223
genesis::utils::round_to
double round_to(double x, size_t accuracy_order)
Retun the value of x, rounded to the decimal digit given by accuracy_order.
Definition: common.hpp:175