ampsci
High-precision calculations for one- and two-valence atomic systems
Maths.hpp
1#pragma once
2#include "Vector.hpp"
3#include <cmath>
4#include <type_traits>
5
6namespace qip {
7
8/*!
9 @brief Function object for comparisons by absolute value.
10
11 @details
12 Compares |lhs| < |rhs| using std::abs. Works like std::less.
13 T must be arithmetic.
14*/
15struct less_abs {
16 template <class T>
17 constexpr bool operator()(const T &lhs, const T &rhs) const {
18 static_assert(std::is_arithmetic_v<T>,
19 "In less_abs<T>(), T must be arithmetic");
20 return std::abs(lhs) < std::abs(rhs);
21 }
22};
23
24//==============================================================================
25
26//! Returns the maximum of any number of parameters (variadic).
27template <typename T, typename... Args>
28T max(T first, Args... rest) {
29 if constexpr (sizeof...(rest) == 0) {
30 return first;
31 } else {
32 const auto max_rest = max(rest...);
33 if (first >= max_rest)
34 return first;
35 return max_rest;
36 }
37}
38
39//! Returns the minimum of any number of parameters (variadic).
40template <typename T, typename... Args>
41T min(T first, Args... rest) {
42 if constexpr (sizeof...(rest) == 0) {
43 return first;
44 } else {
45 const auto min_rest = min(rest...);
46 if (first <= min_rest)
47 return first;
48 return min_rest;
49 }
50}
51
52//! Returns the value with maximum absolute value of any number of parameters (variadic).
53template <typename T, typename... Args>
54T max_abs(T first, Args... rest) {
55 static_assert(std::is_arithmetic_v<T>,
56 "In max_abs<T>(), T must be arithmetic");
57 if constexpr (sizeof...(rest) == 0) {
58 return first;
59 } else {
60 const auto max_rest = max_abs(rest...);
61 if (std::abs(first) >= std::abs(max_rest))
62 return first;
63 return max_rest;
64 }
65}
66
67//! Returns the value with minimum absolute value of any number of parameters (variadic).
68template <typename T, typename... Args>
69T min_abs(T first, Args... rest) {
70 static_assert(std::is_arithmetic_v<T>,
71 "In min_abs<T>(), T must be arithmetic");
72 if constexpr (sizeof...(rest) == 0) {
73 return first;
74 } else {
75 const auto min_rest = min_abs(rest...);
76 if (std::abs(first) <= std::abs(min_rest))
77 return first;
78 return min_rest;
79 }
80}
81
82//! Returns max - min over any number of arguments (variadic).
83template <typename T, typename... Args>
84T max_difference(T first, Args... rest) {
85 static_assert(std::is_arithmetic_v<T>,
86 "In max_difference<T>(), T must be arithmetic");
87 return max(first, rest...) - min(first, rest...);
88}
89
90//==============================================================================
91/*!
92 @brief x^n for compile-time integer n, x any arithmetic type.
93
94 @details
95 Returns double for negative n, T otherwise.
96*/
97template <int n, typename T>
98constexpr auto pow(T x) {
99 using namespace qip::overloads;
100 // Returns double for inverse powers, T otherwise
101 if constexpr (n < 0) {
102 return double(1.0) / pow<-n>(x);
103 } else if constexpr (n == 0) {
104 (void)x; // 'x' unused in this branch
105 return static_cast<T>(1);
106 } else if constexpr (n == 1) {
107 return x;
108 } else {
109 return x * pow<n - 1>(x);
110 }
111}
112
113//! x^n for runtime integer n; T must be floating point.
114template <typename T>
115constexpr T pow(T x, int n) {
116 static_assert(std::is_floating_point_v<T>,
117 "In pow(T x, int n), T must be foating point");
118 if (n < 0) {
119 return static_cast<T>(1) / pow<T>(x, -n);
120 }
121 // T result = static_cast<T>(1);
122 T result{1};
123 for (int i = 0; i < n; ++i) {
124 result *= x;
125 }
126 return result;
127}
128
129//==============================================================================
130
131//! Factorial x! - takes integer, returns double.
132template <typename T>
133constexpr double factorial(T x) {
134 static_assert(std::is_integral_v<T>,
135 "In factorial(T), T must be an integral type");
136 return (x <= 1) ? 1.0 : double(x) * factorial<T>(x - 1);
137}
138
139//! Double factorial x!! - takes integer, returns double.
140template <typename T>
141constexpr double double_factorial(T x) {
142 static_assert(std::is_integral_v<T>,
143 "double_factorial(T): T must be an integral type");
144
145 return (x <= 1) ? 1.0 : double(x) * double_factorial<T>(x - 2);
146}
147
148//==============================================================================
149
150//! Returns the sign of value. Note: sign(0) == 0.
151template <typename T>
152constexpr int sign(T value) {
153 static_assert(std::is_arithmetic_v<T>,
154 "In sign(T value), T must be arithmetic");
155 return (T(0) < value) - (value < T(0));
156}
157
158//! Clamps value to [-max_abs, max_abs] - i.e., using abs.
159template <typename T>
160constexpr T clamp_abs(T value, T max_abs) {
161 static_assert(std::is_arithmetic_v<T>,
162 "In clamp_abs(T value, T max_abs), T must be arithmetic");
163 if (value > max_abs)
164 return max_abs;
165 if (value < -max_abs)
166 return -max_abs;
167 return value;
168}
169
170//! Sets value to zero if |value| < min_abs, otherwise returns value unchanged.
171template <typename T>
172constexpr T chop(T value, T min_abs) {
173 static_assert(std::is_arithmetic_v<T>,
174 "In cjop(T value, T min_abs), T must be arithmetic");
175 if (std::abs(value) < min_abs)
176 return static_cast<T>(0);
177 return value;
178}
179
180} // namespace qip
Operator overloads for std::vector.
Definition Vector.hpp:503
General-purpose utility library.
Definition Array.hpp:23
T max_difference(T first, Args... rest)
Returns max - min over any number of arguments (variadic).
Definition Maths.hpp:84
T max(T first, Args... rest)
Returns the maximum of any number of parameters (variadic).
Definition Maths.hpp:28
constexpr double double_factorial(T x)
Double factorial x!! - takes integer, returns double.
Definition Maths.hpp:141
constexpr int sign(T value)
Returns the sign of value. Note: sign(0) == 0.
Definition Maths.hpp:152
constexpr T clamp_abs(T value, T max_abs)
Clamps value to [-max_abs, max_abs] - i.e., using abs.
Definition Maths.hpp:160
T max_abs(T first, Args... rest)
Returns the value with maximum absolute value of any number of parameters (variadic).
Definition Maths.hpp:54
constexpr double factorial(T x)
Factorial x! - takes integer, returns double.
Definition Maths.hpp:133
T min(T first, Args... rest)
Returns the minimum of any number of parameters (variadic).
Definition Maths.hpp:41
constexpr T chop(T value, T min_abs)
Sets value to zero if |value| < min_abs, otherwise returns value unchanged.
Definition Maths.hpp:172
T min_abs(T first, Args... rest)
Returns the value with minimum absolute value of any number of parameters (variadic).
Definition Maths.hpp:69
constexpr auto pow(T x)
x^n for compile-time integer n, x any arithmetic type.
Definition Maths.hpp:98
Function object for comparisons by absolute value.
Definition Maths.hpp:15