Empirical
math.h
Go to the documentation of this file.
1 
12 #ifndef EMP_MATH_H
13 #define EMP_MATH_H
14 
15 #include <initializer_list>
16 #include <algorithm>
17 #include <cmath>
18 
19 #include "../base/assert.h"
20 #include "../meta/reflection.h"
21 #include "const.h"
22 
23 namespace emp {
24 
26  inline constexpr int Mod(int in_val, int mod_val) {
27  emp_assert(mod_val != 0);
28  in_val %= mod_val;
29  return (in_val < 0) ? (in_val + mod_val) : in_val;
30  }
31 
33  // @CAO Make constexpr?
34  inline double Mod(double in_val, double mod_val) {
35  emp_assert(mod_val != 0);
36  const double remain = std::remainder(in_val, mod_val);
37  return (remain < 0.0) ? (remain + mod_val) : remain;
38  }
39 
41  template <typename T> constexpr T Abs(T in) { return (in > 0) ? in : (-in); }
42 
44  template <typename TYPE> constexpr TYPE ToRange(const TYPE & value, const TYPE & in_min, const TYPE & in_max) {
45  emp_assert(in_min <= in_max);
46  return (value < in_min) ? in_min : ((value > in_max) ? in_max : value);
47  }
48 
50  template <typename T> constexpr T Min(T in1) { return in1; }
51 
53  template <typename T, typename... Ts>
54  constexpr T Min(T in1, T in2, Ts... extras) {
55  T cur_result = Min(in2, extras...);
56  return (in1 < cur_result) ? in1 : cur_result;
57  }
58 
59 
61  template <typename T> constexpr T Max(T in1) { return in1; }
62 
64  template <typename T, typename... Ts>
65  constexpr T Max(T in1, T in2, Ts... extras) {
66  T cur_result = Max(in2, extras...);
67  return (in1 < cur_result) ? cur_result : in1;
68  }
69 
72  template <typename T> constexpr const T & MinRef(const T& in1) { return in1; }
73 
75  template <typename T, typename... Ts>
76  constexpr const T & MinRef(const T& in1, const T& in2, const Ts&... extras) {
77  const T & cur_result = MinRef(in2, extras...);
78  return (in1 < cur_result) ? in1 : cur_result;
79  }
80 
81 
84  template <typename T> constexpr const T & MaxRef(const T& in1) { return in1; }
85 
87  template <typename T, typename... Ts>
88  constexpr const T & MaxRef(const T& in1, const T& in2, const Ts&... extras) {
89  const T & cur_result = MaxRef(in2, extras...);
90  return (in1 < cur_result) ? cur_result : in1;
91  }
92 
93 
94  namespace internal {
95  // A compile-time log calculator for values [1,2)
96  static constexpr double Log2_base(double x) {
97  emp_assert(x > 0);
98  return log2_chart_1_2[(int)((x-1.0)*1024)];
99  // return InterpolateTable(log2_chart_1_2, x-1.0, 1024);
100  }
101 
102  // A compile-time log calculator for values < 1
103  static constexpr double Log2_frac(double x) {
104  emp_assert(x > 0);
105  return (x >= 1.0) ? Log2_base(x) : (Log2_frac(x*2.0) - 1.0);
106  }
107 
108  // A compile-time log calculator for values >= 2
109  static constexpr double Log2_pos(double x) {
110  emp_assert(x > 0);
111  emp_assert(x != INFINITY);
112  return (x < 2.0) ? Log2_base(x) : (Log2_pos(x/2.0) + 1.0);
113  }
114 
115  }
116 
118 
120  static constexpr double Log2(double x) {
121  emp_assert(x > 0);
122  return (x < 1.0) ? internal::Log2_frac(x) : internal::Log2_pos(x);
123  }
124 
126  static constexpr double Log(double x, double base=10.0) { return Log2(x) / Log2(base); }
128  static constexpr double Ln(double x) { return Log(x, emp::E); } // Natural Log...
130  static constexpr double Log10(double x) { return Log(x, 10.0); }
131 
133  template <typename T>
134  static constexpr T Square(T val) { return val * val; }
135 
136  // Pow helper functions.
137  namespace internal {
138  static constexpr double Pow2_lt1(double exp, int id=0) {
139  return (id==32) ? 1.0 :
140  ( (exp > 0.5) ? (pow2_chart_bits[id]*Pow2_lt1(exp*2.0-1.0,id+1)) : Pow2_lt1(exp*2.0,id+1) );
141  }
142 
143  static constexpr double Pow2_impl(double exp) {
144  return (exp >= 1.0) ? (2.0*Pow2_impl(exp-1.0)) : Pow2_lt1(exp);
145  }
146  }
147 
149  template <typename T>
150  static constexpr type_if<T, std::is_integral> Pow(T base, T p) {
151  if (p <= 0) return 1;
152  if (p & 1) return base * Pow(base, p-1); // Odd exponent: strip one mulitple off and recurse.
153  return Square( Pow(base,p/2) ); // Even exponent: calc for half and square result.
154  }
155 
157  static constexpr double Pow2(double exp) {
158  return (exp < 0.0) ? (1.0/internal::Pow2_impl(-exp)) : internal::Pow2_impl(exp);
159  }
160 
162  template <typename TYPE>
163  static constexpr TYPE IntPow(TYPE base, TYPE exp) {
164  emp_assert(exp < 65536); // Set a crazy-high limit for exp to identify problems...
165  return exp < 1 ? 1 : (base * IntPow(base, exp-1));
166  }
167 
169  static constexpr double Pow(double base, double exp) {
170  // Normally, convert to a base of 2 and then use Pow2.
171  // If base is negative, we don't want to deal with imaginary numbers, so use IntPow.
172  return (base > 0) ? Pow2(Log2(base) * exp) : IntPow(base,exp);
173  }
174 
175  // A fast (O(log p)) integer-power command.
176  // static constexpr int Pow(int base, int p) {
177  // return (p <= 0) ? 1 : (base * Pow(base, p-1));
178  // }
179 
181  static constexpr double Exp(double exp) {
182  return Pow2(Log2(emp::E) * exp); // convert to a base of e.
183  }
184 
185 
187  template <typename TYPE>
188  static constexpr int IntLog2(TYPE x) { return x <= 1 ? 0 : (IntLog2(x/2) + 1); }
189 
191  template <typename TYPE>
192  static constexpr int CountOnes(TYPE x) { return x == 0 ? 0 : (CountOnes(x/2) + (x&1)); }
193 
195  template <typename TYPE>
196  static constexpr TYPE MaskLow(std::size_t num_bits) {
197  return (num_bits == 8*sizeof(TYPE)) ? ((TYPE)-1) : ((((TYPE)1) << num_bits) - 1);
198  }
199 
201  template <typename TYPE>
202  static constexpr TYPE MaskHigh(std::size_t num_bits) {
203  return MaskLow<TYPE>(num_bits) << (8*sizeof(TYPE)-num_bits);
204  }
205 
207  template <typename T> constexpr const T & Min(const T& in1, const T& in2, const T& in3) {
208  return std::min(std::min(in1,in2), in3);
209  }
210 
212  template <typename T> const T & Min(std::initializer_list<const T&> lst) {
213  emp_assert(lst.size > 0); // Nothing to return if nothing in the list!
214  auto min_found = lst.begin();
215  for (auto it = lst.begin()+1; it < lst.end(); it++) {
216  if (*it < *min_found) min_found = it;
217  }
218  return *min_found;
219  }
220 
222  template <typename T> const T & Max(std::initializer_list<const T&> lst) {
223  emp_assert(lst.size > 0); // Nothing to return if nothing in the list!
224  auto max_found = lst.begin();
225  for (auto it = lst.begin()+1; it < lst.end(); it++) {
226  if (*it > *max_found) max_found = it;
227  }
228  return *max_found;
229  }
230 
231 
232 }
233 
234 #endif
static constexpr size_t Log2(size_t x)
An anonymous log2 calculator for hashing below.
Definition: Ptr.h:36
constexpr const double pow2_chart_bits[]
Table to provide results of Pow2 for values of bits (0.1, 0.01, 0.001, etc, in binary) ...
Definition: const.h:184
constexpr T Min(T in1)
Min of only one element is that element itself!
Definition: math.h:50
static constexpr double Log10(double x)
Compile-time log base 10 calculator.
Definition: math.h:130
constexpr const double E
e
Definition: const.h:18
static constexpr TYPE IntPow(TYPE base, TYPE exp)
A fast method for calculating exponents for int types.
Definition: math.h:163
static constexpr double Pow2(double exp)
A fast 2^x command.
Definition: math.h:157
static constexpr int IntLog2(TYPE x)
A compile-time int-log calculator (aka, significant bits)
Definition: math.h:188
static constexpr double Pow2_lt1(double exp, int id=0)
Definition: math.h:138
static constexpr double Log2_frac(double x)
Definition: math.h:103
static constexpr double Ln(double x)
Compile-time natural log calculator.
Definition: math.h:128
constexpr const T & MinRef(const T &in1)
Definition: math.h:72
static constexpr int CountOnes(TYPE x)
A compile-time bit counter.
Definition: math.h:192
static constexpr TYPE MaskHigh(std::size_t num_bits)
Quick bit-mask generator for high bits.
Definition: math.h:202
constexpr int Mod(int in_val, int mod_val)
% is actually remainder; Mod is a proper modulus command that handles negative #&#39;s correctly ...
Definition: math.h:26
constexpr T Abs(T in)
Find the absolute value for any variable.
Definition: math.h:41
static constexpr double Log(double x, double base=10.0)
Compile-time log calculator.
Definition: math.h:126
typename internal::EMP_eval_type< T, FILTER< T >::value >::type type_if
Definition: reflection.h:193
static constexpr TYPE MaskLow(std::size_t num_bits)
Quick bit-mask generator for low bits.
Definition: math.h:196
constexpr T Max(T in1)
Max of only one element is that element itself!
Definition: math.h:61
static constexpr type_if< T, std::is_integral > Pow(T base, T p)
A fast (O(log p)) integral-power command.
Definition: math.h:150
static constexpr double Log2_base(double x)
Definition: math.h:96
Commonly used constant values.
If we are in emscripten, make sure to include the header.
Definition: array.h:37
static constexpr double Log2_pos(double x)
Definition: math.h:109
static constexpr T Square(T val)
A simple function to square a value.
Definition: math.h:134
static constexpr double Exp(double exp)
A fast method of calculating e^x.
Definition: math.h:181
#define emp_assert(...)
Definition: assert.h:199
constexpr const T & MaxRef(const T &in1)
Definition: math.h:84
static constexpr bool cur_result
Definition: TypePack.h:110
constexpr const double log2_chart_1_2[]
Large table to log base-2 results.
Definition: const.h:46
static constexpr double Pow2_impl(double exp)
Definition: math.h:143
constexpr TYPE ToRange(const TYPE &value, const TYPE &in_min, const TYPE &in_max)
Run both min and max on a value to put it into a desired range.
Definition: math.h:44