File indexing completed on 2026-07-16 08:07:43
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <cassert>
0012 #include <cmath>
0013 #include <type_traits>
0014
0015 namespace Acts {
0016
0017
0018
0019
0020
0021 template <typename T>
0022 constexpr T abs(const T n) {
0023 if (std::is_constant_evaluated()) {
0024 if constexpr (std::is_signed_v<T>) {
0025 if (n < 0) {
0026 return -n;
0027 }
0028 }
0029 return n;
0030 } else {
0031 return std::abs(n);
0032 }
0033 }
0034
0035
0036
0037
0038
0039
0040 template <typename out_t, typename sign_t>
0041 constexpr out_t copySign(const out_t& copyTo, const sign_t& sign) {
0042 if constexpr (std::is_enum_v<sign_t>) {
0043 return copySign(copyTo, static_cast<std::underlying_type_t<sign_t>>(sign));
0044 } else {
0045 constexpr sign_t zero = 0;
0046 return sign >= zero ? copyTo : -copyTo;
0047 }
0048 }
0049
0050
0051
0052
0053
0054 template <typename T, std::integral P>
0055 constexpr T pow(T x, P p) {
0056 if (std::is_constant_evaluated()) {
0057 constexpr T one = 1;
0058 if constexpr (std::is_signed_v<P>) {
0059 if (p < 0 && abs(x) > std::numeric_limits<T>::epsilon()) {
0060 x = one / x;
0061 p = -p;
0062 }
0063 }
0064 using unsigned_p = std::make_unsigned_t<P>;
0065 return p == 0 ? one : x * pow(x, static_cast<unsigned_p>(p) - 1);
0066 } else {
0067 return static_cast<T>(std::pow(x, static_cast<T>(p)));
0068 }
0069 }
0070
0071
0072
0073
0074 template <typename T>
0075 constexpr auto square(T x) {
0076 return x * x;
0077 }
0078
0079
0080
0081
0082 template <typename... T>
0083 constexpr auto hypotSquare(T... args) {
0084 return (square(args) + ...);
0085 }
0086
0087
0088
0089
0090 template <typename... T>
0091 constexpr auto fastHypot(T... args) {
0092 return std::sqrt(hypotSquare(args...));
0093 }
0094
0095
0096
0097
0098
0099 template <std::integral T>
0100 constexpr T sumUpToN(const T N) {
0101 return N * (N + 1) / 2;
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111 template <std::unsigned_integral T>
0112 constexpr T product(const T lowerN, const T upperN) {
0113 if (lowerN == static_cast<T>(0)) {
0114 return 0;
0115 }
0116 T value{1};
0117 for (T iter = std::max(static_cast<T>(2), lowerN); iter <= upperN; ++iter) {
0118 assert(value * iter > value);
0119 value *= iter;
0120 }
0121 return value;
0122 }
0123
0124
0125 template <std::unsigned_integral T>
0126 constexpr T factorial(const T N) {
0127 return product<T>(1, N);
0128 }
0129
0130
0131
0132
0133
0134
0135
0136 template <std::unsigned_integral T>
0137 constexpr T binomial(const T n, const T k) {
0138 assert(k <= n);
0139 return product<T>(n - k + 1, n) / factorial<T>(k);
0140 }
0141
0142 }