mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
fn.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cctype>
5#include <chrono>
6#include <cmath>
7#include <cstring>
8#include <ctime>
9#include <filesystem>
10#include <initializer_list>
11#include <iomanip>
12#include <iostream>
13#include <limits>
14#include <memory>
15#include <mutable/mutable-config.hpp>
19#include <regex>
20#include <sstream>
21#include <type_traits>
22#include <typeinfo>
23#include <unistd.h>
24#include <variant>
25
26
27namespace m {
28
29inline bool streq(const char *first, const char *second) { return 0 == strcmp(M_notnull(first), M_notnull(second)); }
30inline bool strneq(const char *first, const char *second, std::size_t n)
31{
32 return 0 == strncmp(M_notnull(first), M_notnull(second), n);
33}
34
35inline std::string replace_all(std::string str, const std::string &from, const std::string &to)
36{
37 std::string::size_type pos = 0;
38 while ((pos = str.find(from, pos)) != std::string::npos) {
39 str.replace(pos, from.length(), to);
40 pos += to.length();
41 }
42 return str;
43}
44
45
46inline uint64_t FNV1a(const char *c_str)
47{
48 /* FNV-1a 64 bit */
49 uint64_t hash = 0xcbf29ce484222325UL;
50 char c;
51 while ((c = *c_str++)) {
52 hash = hash ^ c;
53 hash = hash * 0x100000001b3UL;
54 }
55 return hash;
56}
57
58inline uint64_t FNV1a(const char *c_str, std::size_t len)
59{
60 /* FNV-1a 64 bit */
61 uint64_t hash = 0xcbf29ce484222325;
62 for (auto end = c_str + len; c_str != end and *c_str; ++c_str) {
63 hash = hash ^ *c_str;
64 hash = hash * 0x100000001b3UL;
65 }
66 return hash;
67}
68
70struct M_EXPORT StrHash
71{
74 using is_transparent = void;
75
76 uint64_t operator()(const char *c_str) const { return FNV1a(c_str); }
77 uint64_t operator()(const char *c_str, std::size_t len) const { return FNV1a(c_str, len); }
78 uint64_t operator()(const std::string &s) const { return operator()(s.c_str()); }
79 uint64_t operator()(const std::string_view &sv) const { return FNV1a(sv.data(), sv.size()); }
80
81 template<typename T>
82 requires requires (T &&t) { std::string_view(std::forward<T>(t)); }
83 uint64_t operator()(T &&t) {
84 const auto sv = std::string_view(std::forward<T>(t));
85 return FNV1a(sv.data(), sv.length());
86 }
87};
88
90struct M_EXPORT StrEqual
91{
94 using is_transparent = void;
95
96 bool operator()(const char *first, const char *second) const { return streq(first, second); }
97 bool operator()(const std::string_view &first, const std::string_view &second) const { return first == second; }
98
99 template<typename T, typename U>
100 requires requires (T &&t) { std::string_view(std::forward<T>(t)); } and
101 requires (U &&u) { std::string_view(std::forward<U>(u)); }
102 bool operator()(T &&first, U &&second) const {
103 return std::string_view(std::forward<T>(first)) == std::string_view(std::forward<U>(second));
104 }
105};
106
108struct M_EXPORT StrEqualWithNull
109{
110 bool operator()(const char *first, const char *second) const {
111 return first == second or (first != nullptr and second != nullptr and streq(first, second));
112 }
113};
114
116template<typename T1, typename T2, typename H1 = std::hash<T1>, typename H2 = std::hash<T2>>
117struct M_EXPORT PairHash
118{
119 uint64_t operator()(const std::pair<T1, T2> &p) const {
120 H1 h1;
121 H2 h2;
122 return std::rotl(h1(p.first), 32) ^ h2(p.second);
123 }
124};
125
126template<typename T>
127requires unsigned_integral<T>
128M_EXPORT
129constexpr bool is_pow_2(T n)
130{
131 return n ? (n & (n - T(1))) == T(0) : false;
132}
133
134template<typename T>
135typename std::enable_if_t<std::is_integral_v<T> and std::is_unsigned_v<T> and sizeof(T) <= sizeof(unsigned long long), T>
136M_EXPORT
137ceil_to_pow_2(T n)
138{
139 if (n <= 1) return 1;
140
141 /* Count leading zeros. */
142 int lz;
143 if constexpr (sizeof(T) <= sizeof(unsigned)) {
144 lz = __builtin_clz(n - 1U);
145 } else if constexpr (sizeof(T) <= sizeof(unsigned long)) {
146 lz = __builtin_clzl(n - 1UL);
147 } else if constexpr (sizeof(T) <= sizeof(unsigned long long)) {
148 lz = __builtin_clzll(n - 1ULL);
149 } else {
150 static_assert(sizeof(T) > sizeof(unsigned long long), "unsupported width of integral type");
151 }
152 M_insist(lz > 0, "ceiled value would exceed data type");
153
154 T ceiled = T(1) << (8 * sizeof(T) - lz);
155 M_insist(n <= ceiled, "the ceiled value must be greater or equal to the original value");
156 M_insist((n << 1) == 0 or ceiled < (n << 1), "the ceiled value must be smaller than twice the original value");
157 M_insist(is_pow_2(ceiled));
158 return ceiled;
159}
160template<typename T>
161typename std::enable_if<std::is_floating_point<T>::value, T>::type
162M_EXPORT
163ceil_to_pow_2(T f)
164{
165 return ceil_to_pow_2((unsigned long) std::ceil(f));
166}
167
169template<typename T>
170typename std::enable_if_t<std::is_integral_v<T> and std::is_unsigned_v<T>, T>
171M_EXPORT
172ceil_to_multiple_of_pow_2(T n, T power_of_two)
173{
174 M_insist(is_pow_2(power_of_two));
175 T ceiled = (n + (power_of_two - T(1))) & ~(power_of_two - T(1));
176 M_insist(ceiled % power_of_two == T(0));
177 return ceiled;
178}
179
180template<typename T>
181typename std::enable_if_t<std::is_integral_v<T> and std::is_unsigned_v<T>, T>
182M_EXPORT
183round_up_to_multiple(T val, T factor)
184{
185 if (val == 0) return val;
186 if (factor == 0)
187 throw m::invalid_argument("factor must not be 0");
188 T d = val / factor;
189 T differ = (d * factor) != val;
190 return (d + differ) * factor;
191}
192
193template<typename T>
194typename std::enable_if_t<std::is_integral_v<T> and std::is_unsigned_v<T> and sizeof(T) <= sizeof(unsigned long long), T>
195M_EXPORT
196log2_floor(T n)
197{
198 if constexpr (sizeof(T) <= sizeof(unsigned)) {
199 return sizeof(T) * 8 - __builtin_clz(n) - 1;
200 } else if constexpr (sizeof(T) <= sizeof(unsigned long)) {
201 return sizeof(T) * 8 - __builtin_clzl(n) - 1;
202 } else if constexpr (sizeof(T) <= sizeof(unsigned long long)) {
203 return sizeof(T) * 8 - __builtin_clzll(n) - 1;
204 } else {
205 static_assert(sizeof(T) > sizeof(unsigned long long), "unsupported width of integral type");
206 }
207}
208
209template<typename T>
210typename std::enable_if_t<std::is_integral_v<T> and std::is_unsigned_v<T> and sizeof(T) <= sizeof(unsigned long long), T>
211M_EXPORT
212log2_ceil(T n)
213{
214 return n <= 1 ? 0 : log2_floor(n - T(1)) + T(1);
215}
216
218template<typename To, typename From>
219requires (not is_unique_ptr<From>) and (not is_reference_wrapper<From>) and (not is_unsharable_shared_ptr<From>)
220To * M_EXPORT cast(From *v) { return dynamic_cast<To*>(v); }
221
222template<typename To, typename From>
223To * M_EXPORT cast(std::reference_wrapper<From> v) { return dynamic_cast<To*>(&v.get()); }
224
225template<typename To, typename From>
226std::unique_ptr<To> M_EXPORT cast(std::unique_ptr<From> &v) {
227 if (auto ptr = dynamic_cast<To*>(v.get())) {
228 v.release(); // still referenced by ptr
229 return std::unique_ptr<To>(ptr);
230 } else {
231 return std::unique_ptr<To>(nullptr);
232 }
233}
234
235template<typename To, typename From>
236unsharable_shared_ptr<To> M_EXPORT cast(unsharable_shared_ptr<From> v) {
237 return std::dynamic_pointer_cast<To>(std::move(v));
238};
239
241template<typename To, typename From>
242requires (not is_unique_ptr<From>) and (not is_reference_wrapper<From>) and (not is_unsharable_shared_ptr<From>)
243bool M_EXPORT is(From *v) { return cast<To>(v) != nullptr; }
244
245template<typename To, typename From>
246requires (not is_unique_ptr<From>) and (not is_reference_wrapper<From>) and (not is_unsharable_shared_ptr<From>)
247bool M_EXPORT is(From &v) { return is<To>(&v); }
248
249template<typename To, typename From>
250bool M_EXPORT is(std::reference_wrapper<From> v) { return is<To>(v.get()); }
251
252template<typename To, typename From>
253bool M_EXPORT is(const std::unique_ptr<From> &v) { return is<To>(v.get()); }
254
255template<typename To, typename From>
256bool M_EXPORT is(const unsharable_shared_ptr<From> &v) { return cast<To>(v).get() != nullptr; }
257
260template<typename To, typename From>
261requires (not is_unique_ptr<From>) and (not is_reference_wrapper<From>) and (not is_unsharable_shared_ptr<From>)
262To * M_EXPORT as(From *v) { M_insist(is<To>(v)); return static_cast<To*>(v); }
263
264template<typename To, typename From>
265requires (not is_unique_ptr<From>) and (not is_reference_wrapper<From>) and (not is_unsharable_shared_ptr<From>)
266To & M_EXPORT as(From &v) { return *as<To>(&v); }
267
268template<typename To, typename From>
269To & M_EXPORT as(std::reference_wrapper<From> v) { return as<To>(v.get()); }
270
271template<typename To, typename From>
272std::unique_ptr<To> M_EXPORT as(std::unique_ptr<From> v) { return std::unique_ptr<To>(as<To>(v.release())); }
273
274template<typename To, typename From>
275unsharable_shared_ptr<To> M_EXPORT as(unsharable_shared_ptr<From> v) {
276 M_insist(is<To>(v));
277 return std::static_pointer_cast<To>(std::move(v));
278}
279
280template<typename T, typename... Us>
281T & get_as(std::variant<Us...> &v)
282{
283 return *M_notnull(std::get_if<T>(&v));
284}
285
286template<typename T, typename... Us>
287const T & get_as(const std::variant<Us...> &v)
288{
289 return *M_notnull(std::get_if<T>(&v));
290}
291
292inline std::string escape(char c)
293{
294 switch (c) {
295 default: return std::string(1, c);
296 case '\\': return "\\\\";
297 case '\"': return "\\\"";
298 case '\n': return "\\n";
299 }
300}
301
302std::string M_EXPORT escape(const std::string &str, char esc = '\\', char quote = '"');
303
304std::string M_EXPORT unescape(const std::string &str, char esc = '\\', char quote = '"');
305
306inline std::string quote(const std::string &str) { return std::string("\"") + str + '"'; }
307
308inline std::string unquote(const std::string &str, char quote = '"')
309{
310 using std::next, std::prev;
311 if (str.length() < 2)
312 throw m::invalid_argument("string must be at least two quotes long"); // two quotes
313 if (str[0] != quote) return str; // nothing to do
314 if (*str.rbegin() != quote)
315 throw m::invalid_argument("unmatched opening quote");
316 return std::string(next(str.begin()), prev(str.end())); // return substring str[1:-1]
317}
318
319inline std::string interpret(const std::string &str, char esc = '\\', char quote = '"')
320{
321 return unescape(unquote(str, quote), esc, quote);
322} // M_LCOV_EXCL_LINE
323
325std::string M_EXPORT html_escape(std::string str);
326
328inline std::regex pattern_to_regex(const char *pattern, const bool optimize = false, const char escape_char = '\\')
329{
330 if ('_' == escape_char or '%' == escape_char)
331 throw m::invalid_argument("illegal escape character");
332
333 std::stringstream ss;
334 for (const char *c = pattern; *c; ++c) {
335 if (*c == escape_char) {
336 ++c;
337 if ('_' == *c or '%' == *c) {
338 /* This is an escaped character of the input SQL pattern. */
339 ss << *c;
340 continue;
341 } else if (escape_char == *c) {
342 /* This is an escaped character of the input SQL pattern. Nothing to be done. Fallthrough. */
343 } else {
344 throw m::runtime_error("invalid escape sequence");
345 }
346 }
347 switch (*c) {
348 default:
349 ss << *c;
350 break;
351 case '%':
352 ss << "(.*)";
353 break;
354 case '_':
355 ss << '.';
356 break;
357 case '[':
358 case ']':
359 case '(':
360 case ')':
361 case '\\':
362 case '.':
363 case '*':
364 case '+':
365 case '^':
366 case '?':
367 case '|':
368 case '{':
369 case '}':
370 case '$':
371 ss << "\\" << *c;
372 break;
373 }
374 }
375 return optimize ? std::regex(ss.str(), std::regex::optimize) : std::regex(ss.str());
376}
377
379bool M_EXPORT like(const std::string &str, const std::string &pattern, const char escape_char = '\\');
380
382template<typename H, typename N>
383bool M_EXPORT contains(const H &haystack, const N &needle)
384{
385 using std::find, std::begin, std::end;
386 return find(begin(haystack), end(haystack), needle) != end(haystack);
387}
388
390template<typename T, typename U>
391bool M_EXPORT equal(const T &first, const U &second)
392{
393 for (auto t : first) {
394 if (not contains(second, t))
395 return false;
396 }
397 for (auto t : second) {
398 if (not contains(first, t))
399 return false;
400 }
401 return true;
402}
403
405template<typename Container, typename Set>
406bool M_EXPORT subset(const Container &subset, const Set &set)
407{
408 for (auto t : subset) {
409 if (set.count(t) == 0)
410 return false;
411 }
412 return true;
413}
414
416template<typename Container, typename Set>
417bool M_EXPORT intersect(const Container &first, const Set &second)
418{
419 for (auto t : first) {
420 if (second.count(t))
421 return true;
422 }
423 return false;
424}
425
427template<integral T, unsigned_integral U>
428T M_EXPORT powi(const T base, const U exp)
429{
430 M_insist(exp >= U(0));
431 if (exp == U(0))
432 return 1;
433 else if (exp & 0x1)
434 return base * powi(base, exp - U(1));
435 else {
436 T tmp = powi(base, exp / U(2));
437 return tmp * tmp;
438 }
439}
440
441template<typename T>
442void M_EXPORT setbit(T *bytes, bool value, uint32_t n)
443{
444 *bytes ^= (-T(value) ^ *bytes) & (T(1) << n); // set n-th bit to `value`
445}
446
447template<typename T, typename... Args>
448std::ostream & M_EXPORT operator<<(std::ostream &out, const std::variant<T, Args...> value)
449{
450 std::visit([&](auto &&arg) { out << arg; }, value);
451 return out;
452}
453
454/* Helper type to define visitors of std::variant */
455template<class... Ts> struct M_EXPORT overloaded : Ts... { using Ts::operator()...; };
456template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
457
466inline uint64_t murmur3_64(uint64_t v)
467{
468 v ^= v >> 31;
469 v *= 0x7fb5d329728ea185ULL;
470 v ^= v >> 27;
471 v *= 0x81dadef4bc2dd44dULL;
472 v ^= v >> 33;
473 return v;
474}
475
476struct M_EXPORT put_tm
477{
478 private:
479 std::tm tm_;
480
481 public:
482 put_tm(std::tm tm) : tm_(tm) { }
483
484 friend std::ostream & operator<<(std::ostream &out, const put_tm &pt) {
485 using std::setw;
486 const auto oldfill = out.fill('0');
487 const auto oldflags = out.flags();
488 out << std::internal;
489 if (pt.tm_.tm_year < -1900)
490 out << '-' << setw(4) << -(pt.tm_.tm_year + 1900);
491 else
492 out << setw(4) << pt.tm_.tm_year + 1900;
493 out << '-'
494 << setw(2) << pt.tm_.tm_mon + 1 << '-'
495 << setw(2) << pt.tm_.tm_mday << ' '
496 << setw(2) << pt.tm_.tm_hour << ':'
497 << setw(2) << pt.tm_.tm_min << ':'
498 << setw(2) << pt.tm_.tm_sec;
499 out.flags(oldflags);
500 out.fill(oldfill);
501 return out;
502 }
503};
504
505struct M_EXPORT get_tm
506{
507 private:
508 std::tm &tm_;
509
510 public:
511 get_tm(std::tm &tm) : tm_(tm) { }
512
513 friend std::istream & operator>>(std::istream &in, get_tm gt) {
514 in >> gt.tm_.tm_year;
515 if (in and in.peek() == '-') in.get(); else return in;
516 in >> gt.tm_.tm_mon;
517 if (in and in.peek() == '-') in.get(); else return in;
518 in >> gt.tm_.tm_mday;
519 if (in and in.peek() == ' ') in.get(); else return in;
520 in >> gt.tm_.tm_hour;
521 if (in and in.peek() == ':') in.get(); else return in;
522 in >> gt.tm_.tm_min;
523 if (in and in.peek() == ':') in.get(); else return in;
524 in >> gt.tm_.tm_sec;
525
526 gt.tm_.tm_year -= 1900;
527 gt.tm_.tm_mon -= 1;
528 return in;
529 }
530};
531
532template<typename Clock, typename Duration>
533struct M_EXPORT put_timepoint
534{
535 private:
536 std::chrono::time_point<Clock, Duration> tp_;
537 bool utc_;
538
539 public:
540 put_timepoint(std::chrono::time_point<Clock, Duration> tp, bool utc = false) : tp_(tp), utc_(utc) { }
541
543 friend std::ostream & operator<<(std::ostream &out, const put_timepoint &ptp) {
544 using namespace std::chrono;
545 time_t time;
546
547 /* Convert `std::chrono::time_point` to `std::time_t`. */
548 if constexpr (std::is_same_v<Clock, system_clock>) {
549 time = system_clock::to_time_t(ptp.tp_); // convert the clock's time_point to std::time_t
550 } else {
551 /* The time point cannot directly be converted to time_t. To do so, we first must relate the time point in
552 * `Clock` to a time point in the `system_clock`. */
553 auto tpc_now = Clock::now();
554 auto sys_now = system_clock::now();
555 auto tp_sys = time_point_cast<system_clock::duration>(ptp.tp_ - tpc_now + sys_now);
556 time = system_clock::to_time_t(tp_sys);
557 }
558
559 /* Convert `std::time_t` to `std::tm`. */
560 std::tm tm;
561 std::tm *chk;
562 if (ptp.utc_)
563 chk = gmtime_r(&time, &tm); // convert the given `time_t` to UTC `std::tm`
564 else
565 chk = localtime_r(&time, &tm); // convert the given `time_t` to local `std::tm`
566 M_insist(chk == &tm);
567
568 /* Print `std::tm`. */
569 return out << put_tm(tm);
570 }
571};
572
573/* Template class definition to concatenate more types to std::variant. */
574template <typename T, typename... Args> struct Concat;
575
576template <typename... Args0, typename... Args1>
577struct M_EXPORT Concat<std::variant<Args0...>, Args1...> {
578 using type = std::variant<Args0..., Args1...>;
579};
580
581
582/* Detect whether an instance of type `T` can be streamted to an instance of type `S`. */
583template<typename S, typename T, typename = void>
584struct is_streamable : std::false_type {};
585template<typename S, typename T>
586struct is_streamable<S, T, std::void_t<decltype( std::declval<S&>() << std::declval<T>() )>> : std::true_type {};
587
588inline bool is_oct (int c) { return '0' <= c && c <= '7'; }
589inline bool is_dec (int c) { return '0' <= c && c <= '9'; }
590inline bool is_hex (int c) { return is_dec(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); }
591inline bool is_lower(int c) { return ('a' <= c && c <= 'z'); }
592inline bool is_upper(int c) { return ('A' <= c && c <= 'Z'); }
593inline bool is_alpha(int c) { return is_lower(c) || is_upper(c); }
594inline bool is_alnum(int c) { return is_dec(c) || is_alpha(c); }
595
597inline std::filesystem::path get_home_path()
598{
599 std::filesystem::path path;
600#if __linux
601 auto home = getenv("HOME");
602 if (home)
603 path = home;
604#elif __APPLE__
605 auto home = getenv("HOME");
606 if (home)
607 path = home;
608#elif _WIN32
609 auto homedrive = getenv("HOMEDRIVE");
610 auto homepath = getenv("HOMEPATH");
611 if (homedrive and homepath) {
612 path = homedrive;
613 path /= homepath;
614 }
615#else
616 path = ".";
617#endif
618 return path;
619}
620
622inline bool isspace(const char *s, std::size_t len)
623{
624 return std::all_of(s, s + len, static_cast<int(*)(int)>(std::isspace));
625}
626
627inline bool isspace(const char *s) { return isspace(s, strlen(s)); }
628
629void M_EXPORT exec(const char *executable, std::initializer_list<const char*> args);
630
631/*--- Add without overflow; clamp at max value. ----------------------------------------------------------------------*/
632template<typename T, typename U>
633auto M_EXPORT add_wo_overflow(T left, U right)
634{
635 static_assert(std::is_integral_v<T>, "LHS must be an integral type");
636 static_assert(std::is_integral_v<U>, "RHS must be an integral type");
637
638 static_assert(not std::is_signed_v<T>, "LHS must be unsigned");
639 static_assert(not std::is_signed_v<U>, "RHS must be unsigned");
640
641 using CT = std::common_type_t<T, U>;
642 CT res;
643 if (__builtin_add_overflow(CT(left), CT(right), &res))
644 return std::numeric_limits<CT>::max();
645 return res;
646}
647
648template<typename N0, typename N1>
649auto M_EXPORT sum_wo_overflow(N0 n0, N1 n1)
650{
651 return add_wo_overflow(n0, n1);
652}
653
656template<typename N0, typename N1, typename... Numbers>
657auto M_EXPORT sum_wo_overflow(N0 n0, N1 n1, Numbers... numbers)
658{
659 return sum_wo_overflow(add_wo_overflow(n0, n1), numbers...);
660}
661
662/*--- Multiply without overflow; clamp at max value. -----------------------------------------------------------------*/
663template<typename T, typename U>
664auto M_EXPORT mul_wo_overflow(T left, U right)
665{
666 static_assert(std::is_integral_v<T>, "LHS must be an integral type");
667 static_assert(std::is_integral_v<U>, "RHS must be an integral type");
668
669 static_assert(not std::is_signed_v<T>, "LHS must be unsigned");
670 static_assert(not std::is_signed_v<U>, "RHS must be unsigned");
671
672 using CT = std::common_type_t<T, U>;
673 CT res;
674 if (__builtin_mul_overflow(CT(left), CT(right), &res))
675 return std::numeric_limits<CT>::max();
676 return res;
677}
678
679template<typename N0, typename N1>
680auto M_EXPORT prod_wo_overflow(N0 n0, N1 n1)
681{
682 return mul_wo_overflow(n0, n1);
683}
684
687template<typename N0, typename N1, typename... Numbers>
688auto M_EXPORT prod_wo_overflow(N0 n0, N1 n1, Numbers... numbers)
689{
690 return prod_wo_overflow(prod_wo_overflow(n0, n1), numbers...);
691}
692
694inline const char * strdupn(const char *str) { return str ? strdup(str) : nullptr; }
695
697std::size_t M_EXPORT get_pagesize();
698
700inline std::size_t Is_Page_Aligned(std::size_t n) { return (n & (get_pagesize() - 1UL)) == 0; }
701
703inline std::size_t Ceil_To_Next_Page(std::size_t n) { return ((n - 1UL) | (get_pagesize() - 1UL)) + 1UL; }
704
708inline uint64_t sequence_number(double x)
709{
710 uint64_t u64;
711 std::memcpy(&u64, &x, sizeof u64);
712 if (u64 & 0x8000000000000000UL) {
713 u64 ^= 0x8000000000000000UL;
714 return 0x8000000000000000UL - u64;
715 }
716 return u64 + 0x8000000000000000UL;
717}
718
722inline uint32_t sequence_number(float x)
723{
724 uint32_t u32;
725 std::memcpy(&u32, &x, sizeof u32);
726 if (u32 & 0x80000000U) {
727 u32 ^= 0x80000000U;
728 return 0x80000000U - u32;
729 }
730 return u32 + 0x80000000U;
731}
732
734template<typename T>
735constexpr bool M_EXPORT is_range_wide_enough(T a, T b, std::size_t n)
736{
737 using std::swap;
738 if (a > b) swap(a, b);
739
740 if (n == 0) return true;
741
742 M_insist(a <= b);
743 M_insist(n > 0);
744 if constexpr (integral<T>) {
745 if constexpr (signed_integral<T>) {
746 using U = std::make_unsigned_t<T>;
747
748 if ((a < 0) == (b < 0)) { // equal signs
749 return U(b - a) >= n - 1;
750 } else { // different signs
751 M_insist(a < 0);
752 M_insist(b >= 0);
753 U a_abs = U(~a) + 1U; // compute absolute without overflow
754 return a_abs >= n or (U(b) >= n - a_abs - 1);
755 }
756 } else { // unsigned
757 return (b - a) >= n - 1;
758 }
759 } else if constexpr (std::floating_point<T>) {
760 return sequence_number(b) - sequence_number(a) >= n - 1;
761 } else {
762 static_assert(std::is_same_v<T, T>, "unsupported type");
763 }
764}
765
768template<typename T>
769std::enable_if_t<std::is_integral_v<T>, unsigned long long>
770M_EXPORT
771n_choose_k_approx(T n, T k)
772{
773 return std::exp(std::lgamma(n + T(1)) - std::lgamma(k + T(1)) - std::lgamma(n - k + T(1)));
774}
775
777inline float fast_reciprocal_sqrtf(const float n)
778{
779 const int32_t i = 0x5F375A86 - (*reinterpret_cast<const int32_t*>(&n) >> 1);
780 const float f = *reinterpret_cast<const float*>(&i);
781 return (int32_t(3) - n * f * f) * f * 0.5f;
782}
783inline float fast_reciprocal_sqrt(const float n) { return fast_reciprocal_sqrtf(n); }
784
787inline double fast_reciprocal_sqrtd(const double n)
788{
789 const int64_t l = 0x5fe6eb50c7b537a9 - (*reinterpret_cast<const int64_t*>(&n) >> 1);
790 const double d = *reinterpret_cast<const double*>(&l);
791 return (int64_t(3) - n * d * d) * d * 0.5f;
792}
793inline double fast_reciprocal_sqrt(const double n) { return fast_reciprocal_sqrtd(n); }
794
795inline float fast_sqrtf(float n)
796{
797 return n * fast_reciprocal_sqrtf(n); // n * 1/sqrt(n) = sqrt(n)^2 / sqrt(n) = sqrt(n)
798}
799inline float fast_sqrt(float n) { return fast_sqrtf(n); }
800
801inline double fast_sqrtd(double n)
802{
803 return n * fast_reciprocal_sqrtd(n); // n * 1/sqrt(n) = sqrt(n)^2 / sqrt(n) = sqrt(n)
804}
805inline double fast_sqrt(double n) { return fast_sqrtd(n); }
806
807#ifdef __aarch64__
808
809inline uint64_t _pdep_u64(uint64_t source, uint64_t mask) {
810 uint64_t result = 0;
811 uint64_t srcBit = 1;
812 uint64_t dstBit = 1;
813
814 for (int i = 0; i < 64; i++) {
815 if (mask & dstBit) {
816 if (source & srcBit)
817 result |= dstBit;
818 srcBit <<= 1;
819 }
820 dstBit <<= 1;
821 }
822
823 return result;
824}
825
826inline uint64_t pext_u64(uint64_t source, uint64_t mask) {
827 uint64_t result = 0;
828 uint64_t srcBit = 1;
829 uint64_t dstBit = 1;
830
831 for (int i = 0; i < 64; i++) {
832 if (source & srcBit) {
833 if (mask & dstBit)
834 result |= dstBit;
835 dstBit <<= 1;
836 }
837 srcBit <<= 1;
838 }
839
840 return result;
841}
842
843#endif
844
845template<class Factory>
846struct lazy_construct
847{
848 using result_type = std::invoke_result_t<const Factory&>;
849
850 private:
851 Factory factory_;
852
853 public:
854 lazy_construct(Factory&& factory) : factory_(std::move(factory)) { }
855
856 operator result_type() const { return factory_(); }
857};
858
859}
and(sizeof(T)==4) U64x1 reinterpret_to_U64(m
Definition: WasmAlgo.cpp:266
#define M_notnull(ARG)
Definition: macro.hpp:182
#define M_insist(...)
Definition: macro.hpp:129
Bool< L > uint8_t n
Definition: WasmUtil.hpp:1318
std::conditional_t< std::is_signed_v< T >, int16_t, uint16_t > To
Definition: WasmDSL.hpp:2408
‍mutable namespace
Definition: Backend.hpp:10
std::string replace_all(std::string str, const std::string &from, const std::string &to)
Definition: fn.hpp:35
std::string escape(char c)
Definition: fn.hpp:292
M_EXPORT constexpr bool is_pow_2(T n)
Definition: fn.hpp:129
uint64_t FNV1a(const char *c_str)
Definition: fn.hpp:46
std::string unquote(const std::string &str, char quote='"')
Definition: fn.hpp:308
bool M_EXPORT intersect(const Container &first, const Set &second)
Checks whether first and second intersect.
Definition: fn.hpp:417
T M_EXPORT powi(const T base, const U exp)
Power function for integral types.
Definition: fn.hpp:428
bool M_EXPORT subset(const Container &subset, const Set &set)
Checks whether subset is a subset of set.
Definition: fn.hpp:406
bool M_EXPORT equal(const T &first, const U &second)
Checks whether first and second are equal considering permutations.
Definition: fn.hpp:391
uint64_t murmur3_64(uint64_t v)
This function implements the 64-bit finalizer of Murmur3_x64 by Austin Appleby, available at https://...
Definition: fn.hpp:466
bool streq(const char *first, const char *second)
Definition: fn.hpp:29
bool strneq(const char *first, const char *second, std::size_t n)
Definition: fn.hpp:30
bool M_EXPORT contains(const H &haystack, const N &needle)
Checks whether haystack contains needle.
Definition: fn.hpp:383
std::string quote(const std::string &str)
Definition: fn.hpp:306
std::string M_EXPORT unescape(const std::string &str, char esc='\\', char quote='"')
Definition: fn.cpp:35
T(x)
std::string M_EXPORT html_escape(std::string str)
Escapes special characters in a string to be printable in HTML documents.
Definition: fn.cpp:60
and
Definition: enum_ops.hpp:12
std::regex pattern_to_regex(const char *pattern, const bool optimize=false, const char escape_char='\\')
Transforms a SQL-style LIKE pattern into a std::regex.
Definition: fn.hpp:328
bool M_EXPORT like(const std::string &str, const std::string &pattern, const char escape_char='\\')
Compares a SQL-style LIKE pattern with the given std::string.
Definition: fn.cpp:68
M_LCOV_EXCL_START std::ostream & operator<<(std::ostream &out, const PlanTableBase< Actual > &PT)
Definition: PlanTable.hpp:401
and arithmetic< U > and same_signedness< T, U > U
Definition: concepts.hpp:90
std::string interpret(const std::string &str, char esc='\\', char quote='"')
Definition: fn.hpp:319
T & get_as(std::variant< Us... > &v)
Definition: fn.hpp:281
void M_EXPORT setbit(T *bytes, bool value, uint32_t n)
Definition: fn.hpp:442
STL namespace.
std::variant< Args0..., Args1... > type
Definition: fn.hpp:578
Computes the XOR-hash for a pair.
Definition: fn.hpp:118
uint64_t operator()(const std::pair< T1, T2 > &p) const
Definition: fn.hpp:119
Compares two cstrings for equality.
Definition: fn.hpp:109
bool operator()(const char *first, const char *second) const
Definition: fn.hpp:110
Compares two cstrings for equality.
Definition: fn.hpp:91
bool operator()(const std::string_view &first, const std::string_view &second) const
Definition: fn.hpp:97
void is_transparent
‍Mark this callable as transparent, allowing for comparing various types that are interoperable.
Definition: fn.hpp:94
bool operator()(const char *first, const char *second) const
Definition: fn.hpp:96
bool operator()(T &&first, U &&second) const
Definition: fn.hpp:102
Computes the FNV-1a 64-bit hash of a cstring.
Definition: fn.hpp:71
uint64_t operator()(const char *c_str) const
Definition: fn.hpp:76
uint64_t operator()(T &&t)
Definition: fn.hpp:83
void is_transparent
‍Mark this callable as transparent, allowing for computing the hash of various types that are interop...
Definition: fn.hpp:74
uint64_t operator()(const char *c_str, std::size_t len) const
Definition: fn.hpp:77
uint64_t operator()(const std::string &s) const
Definition: fn.hpp:78
uint64_t operator()(const std::string_view &sv) const
Definition: fn.hpp:79
std::tm & tm_
Definition: fn.hpp:508
get_tm(std::tm &tm)
Definition: fn.hpp:511
friend std::istream & operator>>(std::istream &in, get_tm gt)
Definition: fn.hpp:513
Signals that an argument to a function of method was invalid.
Definition: exception.hpp:37
std::chrono::time_point< Clock, Duration > tp_
Definition: fn.hpp:536
friend std::ostream & operator<<(std::ostream &out, const put_timepoint &ptp)
Print the given std::chrono::time_point in the given format.
Definition: fn.hpp:543
put_timepoint(std::chrono::time_point< Clock, Duration > tp, bool utc=false)
Definition: fn.hpp:540
std::tm tm_
Definition: fn.hpp:479
put_tm(std::tm tm)
Definition: fn.hpp:482
friend std::ostream & operator<<(std::ostream &out, const put_tm &pt)
Definition: fn.hpp:484
Signals a runtime error that mu*t*able is not responsible for and that mu*t*able was not able to reco...
Definition: exception.hpp:49