qxLib
common.inl
Go to the documentation of this file.
1 /**
2 
3  @file common.inl
4  @author Khrapov
5  @date 29.04.2023
6  @copyright © Nick Khrapov, 2023. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 template<class T>
14 constexpr T abs(T value)
15 {
16  return value < 0 ? -value : value;
17 }
18 
19 template<std::integral T>
20 constexpr bool is_odd(T val)
21 {
22  return (val & 1) == 1;
23 }
24 
25 template<std::integral T>
26 constexpr bool is_even(T val)
27 {
28  return (val & 1) == 0;
29 }
30 
31 constexpr int gcd(int nFirst, int nSecond)
32 {
33  if (nFirst == 0 || nSecond == 0)
34  return 0;
35 
36  while (nSecond != 0)
37  {
38  const int nRemainder = nFirst % nSecond;
39  nFirst = nSecond;
40  nSecond = nRemainder;
41  }
42 
43  return abs(nFirst);
44 }
45 
46 constexpr int lcm(int nFirst, int nSecond)
47 {
48  if (nFirst == 0 || nSecond == 0)
49  return 0;
50 
51  nFirst = abs(nFirst);
52  nSecond = abs(nSecond);
53 
54  return nFirst / gcd(nFirst, nSecond) * nSecond;
55 }
56 
57 template<class T>
58 constexpr double pow(T number, int nPower)
59 {
60  static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>, "Integral or floating point required");
61 
62  if (!std::is_constant_evaluated())
63  {
64  const bool bNegativePower = nPower < 0;
65  const size_t nPositivePower = static_cast<size_t>(std::abs(nPower));
66 
67  double fResult = 1.0;
68  switch (nPositivePower)
69  {
70  case 0:
71  break;
72 
73  case 1:
74  fResult = static_cast<double>(number);
75  break;
76 
77  case 2:
78  fResult = static_cast<double>(number * number);
79  break;
80 
81  default:
82  const std::bitset<std::numeric_limits<int>::digits> powerBitSet(nPositivePower);
83 
84  std::array<double, std::numeric_limits<int>::digits> powers;
85 
86  powers[0] = static_cast<double>(number);
87 
88  size_t nCurPower = 1;
89  size_t nCurIndex = 1;
90 
91  while (nCurPower < nPositivePower)
92  {
93  powers[nCurIndex] = powers[nCurIndex - 1] * powers[nCurIndex - 1];
94  nCurPower *= 2;
95  nCurIndex++;
96  }
97 
98  for (size_t i = 0; i < nCurIndex; ++i)
99  if (powerBitSet.test(i))
100  fResult *= powers[i];
101 
102  break;
103  }
104 
105  return bNegativePower ? 1.0 / fResult : fResult;
106  }
107  else
108  {
109  if (nPower == 0)
110  {
111  return 1.0;
112  }
113  else if (nPower < 0)
114  {
115  return 1.0 / pow(number, -nPower);
116  }
117  else
118  {
119  double fResult = 1.0;
120  for (int i = 0; i < nPower; ++i)
121  fResult *= static_cast<double>(number);
122 
123  return fResult;
124  }
125  }
126 }
127 
128 template<std::integral I>
129 I maxpot(I nValue)
130 {
131  if (nValue == 0)
132  return 0;
133 
134  std::bitset<std::numeric_limits<I>::digits> powers(static_cast<size_t>(abs(nValue)));
135 
136  I nPow = static_cast<I>(std::numeric_limits<I>::digits - 1);
137  while (!powers.test(static_cast<size_t>(nPow)))
138  --nPow;
139 
140  return nPow;
141 }
142 
143 } // namespace qx
constexpr int lcm(int nFirst, int nSecond)
Least common multiple.
Definition: common.inl:46
I maxpot(I nValue)
Max power of two in integer.
Definition: common.inl:129
constexpr bool is_odd(T val)
Check if value is odd.
Definition: common.inl:20
constexpr T abs(T value)
Constexpr absolute value.
Definition: common.inl:14
constexpr bool is_even(T val)
Check if value is even.
Definition: common.inl:26
constexpr double pow(T number, int nPower)
Power function for integer power.
Definition: common.inl:58
constexpr int gcd(int nFirst, int nSecond)
Greatest common divisor.
Definition: common.inl:31