22#include <absl/base/nullability.h>
23#include <absl/base/optimization.h>
24#include <absl/log/absl_check.h>
25#include <absl/numeric/bits.h>
26#include <absl/strings/ascii.h>
34template <
class T, std::enable_if_t<std::is_trivially_copyable_v<T>,
int> = 0>
35constexpr T
min(T a, T b) {
36 return std::min(a, b);
42 std::is_same_v<internal::remove_cvref_t<L>, internal::remove_cvref_t<R>>
43 && !std::is_trivially_copyable_v<internal::remove_cvref_t<L>>
44 && std::is_lvalue_reference_v<L> && std::is_lvalue_reference_v<R>,
46constexpr const std::remove_reference_t<L> &
min(L &&a, R &&b) {
47 return std::min(std::forward<L>(a), std::forward<R>(b));
50template <
class T, std::enable_if_t<std::is_trivially_copyable_v<T>,
int> = 0>
51constexpr T
max(T a, T b) {
52 return std::max(a, b);
58 std::is_same_v<internal::remove_cvref_t<L>, internal::remove_cvref_t<R>>
59 && !std::is_trivially_copyable_v<internal::remove_cvref_t<L>>
60 && std::is_lvalue_reference_v<L> && std::is_lvalue_reference_v<R>,
62constexpr const std::remove_reference_t<L> &
max(L &&a, R &&b) {
63 return std::max(std::forward<L>(a), std::forward<R>(b));
66template <
class T,
class Comp = std::less<>,
67 std::enable_if_t<std::is_trivially_copyable_v<T>,
int> = 0>
68constexpr std::pair<T, T>
minmax(T a, T b, Comp &&comp = {}) {
69 return std::minmax(a, b, std::forward<Comp>(comp));
73 class L,
class R,
class Comp = std::less<>,
75 std::is_same_v<internal::remove_cvref_t<L>, internal::remove_cvref_t<R>>
76 && !std::is_trivially_copyable_v<internal::remove_cvref_t<L>>
77 && std::is_lvalue_reference_v<L> && std::is_lvalue_reference_v<R>,
79constexpr std::pair<const std::remove_reference_t<L> &,
80 const std::remove_reference_t<L> &>
81minmax(L &&a, R &&b, Comp &&comp = {}) {
82 return std::minmax(std::forward<L>(a), std::forward<R>(b),
83 std::forward<Comp>(comp));
86template <
class T, std::enable_if_t<std::is_trivially_copyable_v<T>,
int> = 0>
87constexpr T
clamp(T v, T l, T h) {
88 return std::clamp(v, l, h);
92 class T,
class L,
class H,
94 std::is_same_v<internal::remove_cvref_t<T>, internal::remove_cvref_t<L>>
95 && std::is_same_v<internal::remove_cvref_t<L>,
96 internal::remove_cvref_t<H>>
97 && !std::is_trivially_copyable_v<internal::remove_cvref_t<T>>
98 && std::is_lvalue_reference_v<T> && std::is_lvalue_reference_v<L>
99 && std::is_lvalue_reference_v<H>,
101constexpr const std::remove_reference_t<T> &
clamp(T &&v, L &&l, H &&h) {
102 return std::clamp(std::forward<T>(v), std::forward<L>(l), std::forward<H>(h));
106 class PowersetStream {
108 explicit PowersetStream(
int n): n_(n), r_(0), r_max_(0), state_(0) { }
110 PowersetStream &next() {
111 if (state_ >= r_max_) {
114 if (ABSL_PREDICT_FALSE(!*
this))
117 r_max_ |= 1U << (n_ - r_);
118 state_ = (1U << r_) - 1;
122 constexpr auto nbits = std::numeric_limits<
decltype(state_)>::digits;
123 unsigned int shifted = state_ << (nbits - n_);
125 unsigned int leading_ones = absl::countl_one(shifted);
126 unsigned int stripped = (shifted << leading_ones) >> leading_ones;
128 int leading_zeros = absl::countl_zero(stripped);
129 int next_one_bit =
nuri::max(n_ - leading_zeros - 1, 0);
131 unsigned int mask = (1U << next_one_bit) - 1;
132 state_ = ((1U << (leading_ones + 1)) - 1) << (next_one_bit + 1)
137 unsigned int state()
const {
return state_; }
139 operator bool()
const {
return r_ <= n_; }
148 inline PowersetStream &operator>>(PowersetStream &ps,
unsigned int &state) {
157template <
class E,
class U =
internal::underlying_type_t<E>, U = 0>
158constexpr E operator|(E lhs, E rhs) {
159 return static_cast<E
>(
static_cast<U
>(lhs) |
static_cast<U
>(rhs));
162template <
class E,
class U =
internal::underlying_type_t<E>, U = 0>
163constexpr E &operator|=(E &self, E rhs) {
164 return self = self | rhs;
167template <
class E,
class U =
internal::underlying_type_t<E>, U = 0>
168constexpr E operator&(E lhs, E rhs) {
169 return static_cast<E
>(
static_cast<U
>(lhs) &
static_cast<U
>(rhs));
172template <
class E,
class U =
internal::underlying_type_t<E>, U = 0>
173constexpr E &operator&=(E &self, E rhs) {
174 return self = self & rhs;
177template <
class E,
class U =
internal::underlying_type_t<E>, U = 0>
178constexpr E operator^(E lhs, E rhs) {
179 return static_cast<E
>(
static_cast<U
>(lhs) ^
static_cast<U
>(rhs));
182template <
class E,
class U =
internal::underlying_type_t<E>, U = 0>
183constexpr E &operator^=(E &self, E rhs) {
184 return self = self ^ rhs;
187template <
class E,
class U =
internal::underlying_type_t<E>, U = 0>
188constexpr E operator~(E val) {
189 return static_cast<E
>(~static_cast<U>(val));
192template <
class E,
class U =
internal::underlying_type_t<E>, U = 0,
193 std::enable_if_t<std::is_
unsigned_v<U>,
int> = 0>
194constexpr E operator-(E val) {
195 return static_cast<E
>(-
static_cast<U
>(val));
200 constexpr bool check_flag(E flags, E flag) {
202 return static_cast<bool>(flags & flag);
205 template <
class E,
class U = extract_if_enum_t<E>,
206 std::enable_if_t<std::is_
unsigned_v<U>, U> = 0>
207 constexpr E &update_flag(E &flags,
bool cond, E flag) {
208 E mask = -
static_cast<E
>(cond);
209 flags = (flags & ~flag) | (mask & flag);
213 template <
class E,
class U = extract_if_enum_t<E>,
214 std::enable_if_t<std::is_
unsigned_v<U>, U> = 0>
215 constexpr E &set_flag_if(E &flags,
bool cond, E flag) {
216 E mask = -
static_cast<E
>(cond);
217 flags |= mask & flag;
221 template <
class E,
class U = extract_if_enum_t<E>,
222 std::enable_if_t<std::is_
unsigned_v<U>, U> = 0>
223 constexpr E &unset_flag_if(E &flags,
bool cond, E flag) {
224 E mask = -
static_cast<E
>(cond);
225 flags &= ~(mask & flag);
231 return static_cast<int>(std::lround(x));
234 constexpr int negate_if_false(
bool cond) {
235 int ret = (
static_cast<int>(cond) << 1) - 1;
236 ABSL_ASSUME(ret == 1 || ret == -1);
241template <
int N = Eigen::Dynamic,
int... Extra>
242auto generate_index(Eigen::Index size) {
243 Array<int, N, 1, 0, Extra...> result(size);
244 std::iota(result.begin(), result.end(), 0);
248template <
int N = Eigen::Dynamic,
int... Extra,
class Container,
249 class Comp = std::less<>>
250auto argsort(
const Container &container, Comp op = {}) {
251 auto idxs = generate_index<N, Extra...>(std::size(container));
252 std::sort(idxs.begin(), idxs.end(),
253 [&](
int i,
int j) { return op(container[i], container[j]); });
257template <
int N = Eigen::Dynamic,
int... Extra,
class Container,
258 class Comp = std::less<>>
259auto argpartition(
const Container &container,
int count, Comp op = {}) {
260 auto idxs = generate_index<N, Extra...>(std::size(container));
261 std::nth_element(idxs.begin(), idxs.begin() + count - 1, idxs.end(),
263 return op(container[i], container[j]);
268template <
class Container>
269void mask_to_map(Container &mask) {
270 typename Container::value_type idx = 0;
271 for (
int i = 0; i < mask.size(); ++i) {
272 mask[i] = mask[i] ? idx++ : -1;
276template <
typename Derived,
typename Base>
277std::unique_ptr<Derived>
278static_unique_ptr_cast(std::unique_ptr<Base> &&p)
noexcept {
279 auto d =
static_cast<Derived *
>(p.release());
280 return std::unique_ptr<Derived>(d);
283inline std::string_view extension_no_dot(
const std::filesystem::path &ext) {
284 const std::string_view ext_view = ext.native();
285 if (ABSL_PREDICT_TRUE(!ext_view.empty())) {
286 return ext_view.substr(1);
291constexpr std::string_view slice(std::string_view str, std::size_t begin,
293 return str.substr(begin, end - begin);
296inline std::string_view slice_strip(std::string_view str, std::size_t begin,
298 return absl::StripAsciiWhitespace(slice(str, begin, end));
301inline std::string_view slice_rstrip(std::string_view str, std::size_t begin,
303 return absl::StripTrailingAsciiWhitespace(slice(str, begin, end));
306constexpr std::string_view safe_substr(std::string_view str,
size_t begin,
307 size_t count = std::string_view::npos) {
308 if (ABSL_PREDICT_FALSE(begin > str.size()))
311 return str.substr(begin, count);
314constexpr std::string_view safe_slice(std::string_view str,
size_t begin,
316 if (ABSL_PREDICT_FALSE(begin > str.size()))
319 return slice(str, begin, end);
322inline std::string_view safe_slice_strip(std::string_view str,
size_t begin,
324 return absl::StripAsciiWhitespace(safe_slice(str, begin, end));
327inline std::string_view safe_slice_rstrip(std::string_view str,
size_t begin,
329 return absl::StripTrailingAsciiWhitespace(safe_slice(str, begin, end));
333 template <
bool = (sizeof(
double) * 3) % alignof(Vector3d) == 0>
334 inline void stack_impl(Matrix3Xd &m,
const std::vector<Vector3d> &vs) {
335 for (
int i = 0; i < vs.size(); ++i)
340 inline void stack_impl<true>(Matrix3Xd &m,
const std::vector<Vector3d> &vs) {
341 ABSL_DCHECK(
reinterpret_cast<ptrdiff_t
>(vs[0].data()) +
sizeof(
double) * 3
342 ==
reinterpret_cast<ptrdiff_t
>(vs[1].data()))
344 std::memcpy(m.data(), vs[0].data(), vs.size() *
sizeof(
double) * 3);
348inline Matrix3Xd stack(
const std::vector<Vector3d> &vs) {
349 if (ABSL_PREDICT_FALSE(vs.empty()))
350 return Matrix3Xd(3, 0);
352 Matrix3Xd m(3, vs.size());
353 internal::stack_impl(m, vs);
357template <
class T =
int, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
358constexpr T value_if(
bool cond, T val = 1) {
359 return static_cast<T
>(
static_cast<int>(cond)) * val;
362template <
class Scalar, std::enable_if_t<std::is_arithmetic_v<Scalar>
363 && (!std::is_
integral_v<Scalar>
364 || std::is_
signed_v<Scalar>),
366constexpr Scalar nonnegative(Scalar x) {
367 return nuri::max(x,
static_cast<Scalar
>(0));
371 std::enable_if_t<std::is_integral_v<UInt> && !std::is_signed_v<UInt>,
373constexpr UInt nonnegative(UInt x) {
378 std::enable_if_t<std::is_same_v<UInt, unsigned int>,
int> = 0>
379constexpr int log_base10(UInt x) {
380 int lg = (x >= 1000000000) ? 9
381 : (x >= 100000000) ? 8
382 : (x >= 10000000) ? 7
393template <
class Int, std::enable_if_t<std::is_same_v<Int,
int>,
int> = 0>
395constexpr int log_base10(Int x) {
396 int lg = value_if(x < 0);
397 lg += log_base10(
static_cast<unsigned int>(x < 0 ? -x : x));
405 using Nonnull = T absl_nonnull;
407 using Nullable = T absl_nullable;
409 using NullabilityUnknown = T absl_nullability_unknown;
412 using absl::NullabilityUnknown;
413 using absl::Nullable;
constexpr T min(T a, T b)
Definition utils.h:35
constexpr std::pair< T, T > minmax(T a, T b, Comp &&comp={})
Definition utils.h:68
constexpr T clamp(T v, T l, T h)
Definition utils.h:87
constexpr T max(T a, T b)
Definition utils.h:51