SeqAn3
3.4.0
The Modern C++ library for sequence analysis.
Toggle main menu visibility
Loading...
Searching...
No Matches
math.hpp
Go to the documentation of this file.
1
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
2
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
3
// SPDX-License-Identifier: BSD-3-Clause
4
9
10
#pragma once
11
12
#include <bit>
13
#include <
cassert
>
14
#include <
cmath
>
15
#include <concepts>
16
#include <
stdexcept
>
17
#include <
string
>
18
19
#include <
seqan3/core/platform.hpp
>
20
21
namespace
seqan3::detail
22
{
23
51
template
<std::
unsigned
_
int
egral
unsigned
_t>
52
constexpr
unsigned_t floor_log2(unsigned_t
const
n)
noexcept
53
{
54
assert(n > 0u);
// n == 0 is undefined behaviour
55
return
std::bit_width(n) - 1;
56
}
57
85
template
<std::
unsigned
_
int
egral
unsigned
_t>
86
constexpr
unsigned_t ceil_log2(unsigned_t
const
n)
noexcept
87
{
88
assert(n > 0u);
// n == 0 is undefined behaviour
89
return
(n == 1u) ? 0u : seqan3::detail::floor_log2(n - 1u) + 1u;
90
}
91
92
}
// namespace seqan3::detail
93
94
namespace
seqan3
95
{
118
template
<
typename
base_t, std::
unsigned
_
int
egral exp_t>
119
requires
(std::same_as<base_t, uint64_t> || std::same_as<base_t, int64_t>)
120
base_t
pow
(base_t base, exp_t exp)
121
{
122
base_t result{1};
123
#ifndef NDEBUG
124
if
(base == 0)
125
return
0;
126
127
auto
check = [base](base_t result)
128
{
129
if
(base > 0)
130
{
131
return
result >
std::numeric_limits<base_t>::max
() / base;
132
}
133
else
if
(result < 0)
// and base < 0
134
{
135
return
result < std::numeric_limits<base_t>::max() / base;
136
}
137
else
// base < 0 and result > 0
138
{
139
return
base < std::numeric_limits<base_t>::min() / result;
140
}
141
};
142
143
for
(exp_t i = 0; i < exp; ++i)
144
{
145
if
(check(result))
146
{
147
std::string
error_message{
"Calculating "
+
std::to_string
(base) +
'^'
+
std::to_string
(exp)
148
+
" will result in an "
149
+ (std::same_as<base_t, int64_t> ?
"int64_t"
:
"uint64_t"
)};
150
if
(base < 0)
151
throw
std::underflow_error
{error_message +
" underflow."
};
152
else
153
throw
std::overflow_error
{error_message +
" overflow."
};
154
}
155
result *= base;
156
}
157
#else
158
for
(; exp; exp >>= 1, base *= base)
159
result *= (exp & 1) ? base : 1;
160
#endif
161
return
result;
162
}
163
165
// If base and exponent are unsigned integrals, promote the base to `uint64_t`.
166
template
<std::
int
egral base_t, std::
unsigned
_
int
egral exp_t>
167
requires
(std::unsigned_integral<base_t> && !std::same_as<base_t, uint64_t>)
168
uint64_t
pow
(base_t base, exp_t exp)
169
{
170
return
pow
(
static_cast<
uint64_t
>
(base), exp);
171
}
172
173
// If the base is a signed integral and the exponent is an unsigned integral, promote the base to `int64_t`.
174
template
<std::
int
egral base_t, std::
unsigned
_
int
egral exp_t>
175
requires
(!std::unsigned_integral<base_t> && !std::same_as<base_t, int64_t>)
176
int64_t
pow
(base_t base, exp_t exp)
177
{
178
return
pow
(
static_cast<
int64_t
>
(base), exp);
179
}
180
181
// Otherwise delegate to `std::pow`.
182
template
<
typename
base_t,
typename
exp_t>
183
requires
(!(std::integral<base_t> && std::unsigned_integral<exp_t>))
184
auto
pow
(base_t base, exp_t exp)
185
{
186
return
std::pow
(base, exp);
187
}
189
190
}
// namespace seqan3
std::string
cassert
cmath
seqan3::pow
base_t pow(base_t base, exp_t exp)
Computes the value of base raised to the power exp.
Definition
math.hpp:120
std::numeric_limits::max
T max(T... args)
seqan3
The main SeqAn3 namespace.
Definition
aligned_sequence_concept.hpp:26
std::overflow_error
platform.hpp
Provides platform and dependency checks.
std::pow
T pow(T... args)
stdexcept
string
std::to_string
T to_string(T... args)
std::underflow_error
Hide me
Version:
seqan3
utility
math.hpp
Generated on
for SeqAn3 by
1.17.0