kblib 0.2.3
General utilities library for modern C++
stats.h
Go to the documentation of this file.
1/* *****************************************************************************
2 * kblib is a general utility library for C++14 and C++17, intended to provide
3 * performant high-level abstractions and more expressive ways to do simple
4 * things.
5 *
6 * Copyright (c) 2021 killerbee
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * ****************************************************************************/
21
31#ifndef KBLIB_STATS_H
32#define KBLIB_STATS_H
33
34#include <array>
35#include <cassert>
36#include <cinttypes>
37#include <cstdlib>
38#include <limits>
39#include <numeric>
40
41#include "fakestd.h"
42#include "logic.h"
43#include "tdecl.h"
44
45namespace KBLIB_NS {
46
47template <typename T, typename U>
48KBLIB_NODISCARD constexpr auto div(T num, U den) noexcept
49 -> decltype(std::div(num, den)) {
50 decltype(std::div(num, den)) ret{};
51 ret.quot = num / den;
52 ret.rem = num % den;
53 return ret;
54}
55
60template <typename T>
64};
65
66#if 0 and KBLIB_USE_CXX17
67
74template <typename T, std::size_t N>
75using trivial_array = std::array<T, N>;
76
77#else
78
83template <typename T, std::size_t N>
85 T arr[N];
86 KBLIB_NODISCARD constexpr auto operator[](std::size_t n) -> T& {
87 return arr[n];
88 }
89 KBLIB_NODISCARD constexpr auto operator[](std::size_t n) const -> const T& {
90 return arr[n];
91 }
92 KBLIB_NODISCARD constexpr auto size() const -> std::size_t { return N; }
93 KBLIB_NODISCARD constexpr auto begin() & noexcept -> T* { return arr; }
94 KBLIB_NODISCARD constexpr auto begin() const& noexcept -> const T* {
95 return arr;
96 }
97 KBLIB_NODISCARD constexpr auto end() & noexcept -> T* { return arr + N; }
98 KBLIB_NODISCARD constexpr auto end() const& noexcept -> const T* {
99 return arr + N;
100 }
101
102 KBLIB_NODISCARD constexpr friend auto operator==(
103 const trivial_array& a, const trivial_array& b) noexcept -> bool {
104 return equal(a.begin(), a.end(), b.begin());
105 }
106 KBLIB_NODISCARD constexpr friend auto operator!=(
107 const trivial_array& a, const trivial_array& b) noexcept -> bool {
108 return not (a == b);
109 }
110};
111
112#endif
113
131template <typename U>
132KBLIB_NODISCARD constexpr auto calc_fib_size() noexcept -> std::size_t {
133 static_assert(std::is_unsigned<U>::value, "U must be unsigned");
134 std::size_t n{};
135 trivial_pair<U> state{0, 1};
136 U& a = state.first;
137 U& b = state.second;
138 while (b >= a) {
139 state = {b, static_cast<U>(a + b)};
140 ++n;
141 }
142 return n;
143}
144
155template <typename U, std::size_t N = calc_fib_size<U>() + 1>
156KBLIB_NODISCARD constexpr auto make_fib_arr() noexcept -> trivial_array<U, N> {
157 static_assert(
158 implies<(N > calc_fib_size<U>()), std::is_unsigned<U>::value>::value,
159 "signed U with large N would trigger signed overflow");
160 // Initialize the first two elements of the array
161 trivial_array<U, N> ret{{0, 1}};
162 // A loop initializes the rest
163 for (std::size_t i = 2; i < N; ++i) {
164 ret[i] = ret[i - 1] + ret[i - 2];
165 }
166 return ret;
167}
168
176template <typename U = std::uintmax_t>
177KBLIB_NODISCARD constexpr auto fibonacci(int n) noexcept -> U {
178 constexpr auto arr = make_fib_arr<U>();
179 assert(n >= 0 and static_cast<std::size_t>(n) < arr.size());
180 return arr[to_unsigned(n)];
181}
182
183inline namespace nums {
194 constexpr struct max_t {
195 template <typename T,
196 std::enable_if_t<std::numeric_limits<T>::is_specialized,
197 void>* = nullptr>
198 constexpr /* implicit*/ operator T() const
199 noexcept(noexcept(std::numeric_limits<T>::max())) {
201 }
202 template <typename T>
203 KBLIB_NODISCARD constexpr static auto of() noexcept(
204 noexcept(std::numeric_limits<T>::max())) {
206 }
207
211 template <typename L, typename R>
212 KBLIB_NODISCARD constexpr auto operator()(L&& lhs, R&& rhs) const noexcept
213 -> decltype(auto) {
214 return std::less<>{}(lhs, rhs) ? std::forward<R>(rhs)
215 : std::forward<L>(lhs);
216 }
217
218 KBLIB_NODISCARD constexpr inline friend auto operator==(max_t, max_t)
219 -> std::true_type {
220 return {};
221 }
222 KBLIB_NODISCARD constexpr inline friend auto operator!=(max_t, max_t)
223 -> std::false_type {
224 return {};
225 }
226 KBLIB_NODISCARD constexpr inline friend auto operator<(max_t, max_t)
227 -> std::false_type {
228 return {};
229 }
230 KBLIB_NODISCARD constexpr inline friend auto operator>(max_t, max_t)
231 -> std::false_type {
232 return {};
233 }
234 KBLIB_NODISCARD constexpr inline friend auto operator<=(max_t, max_t)
235 -> std::true_type {
236 return {};
237 }
238 KBLIB_NODISCARD constexpr inline friend auto operator>=(max_t, max_t)
239 -> std::true_type {
240 return {};
241 }
242
243 template <typename T>
244 KBLIB_NODISCARD constexpr friend auto operator==(T t, max_t) -> bool {
245 return t == of<T>();
246 }
247 template <typename T>
248 KBLIB_NODISCARD constexpr friend auto operator==(max_t, T t) -> bool {
249 return t == of<T>();
250 }
251 template <typename T>
252 KBLIB_NODISCARD constexpr friend auto operator!=(T t, max_t) -> bool {
253 return t != of<T>();
254 }
255 template <typename T>
256 KBLIB_NODISCARD constexpr friend auto operator!=(max_t, T t) -> bool {
257 return t != of<T>();
258 }
259
260 template <typename T>
261 KBLIB_NODISCARD constexpr friend auto operator<(T t, max_t) -> bool {
262 return t < of<T>();
263 }
264 template <typename T>
265 KBLIB_NODISCARD constexpr friend auto operator<(max_t, T t) -> bool {
266 return of<T>() < t;
267 }
268 template <typename T>
269 KBLIB_NODISCARD constexpr friend auto operator>(T t, max_t) -> bool {
270 return t > of<T>();
271 }
272 template <typename T>
273 KBLIB_NODISCARD constexpr friend auto operator>(max_t, T t) -> bool {
274 return of<T>() > t;
275 }
276
277 template <typename T>
278 KBLIB_NODISCARD constexpr friend auto operator<=(T t, max_t) -> bool {
279 return t <= of<T>();
280 }
281 template <typename T>
282 KBLIB_NODISCARD constexpr friend auto operator<=(max_t, T t) -> bool {
283 return of<T>() <= t;
284 }
285 template <typename T>
286 KBLIB_NODISCARD constexpr friend auto operator>=(T t, max_t) -> bool {
287 return t >= of<T>();
288 }
289 template <typename T>
290 KBLIB_NODISCARD constexpr friend auto operator>=(max_t, T t) -> bool {
291 return of<T>() >= t;
292 }
293
294 } max;
306 constexpr struct min_t {
307 template <typename T, enable_if_t<std::numeric_limits<T>::is_specialized,
308 void>* = nullptr>
309 constexpr /* implicit*/ operator T() const
310 noexcept(noexcept(std::numeric_limits<T>::min())) {
312 }
313 template <typename T>
314 KBLIB_NODISCARD constexpr static auto of() noexcept(
315 noexcept(std::numeric_limits<T>::min())) {
317 }
318
322 template <typename L, typename R>
323 KBLIB_NODISCARD constexpr auto operator()(L&& lhs, R&& rhs) const noexcept
324 -> decltype(auto) {
325 return std::less<>{}(lhs, rhs) ? std::forward<R>(lhs)
326 : std::forward<L>(rhs);
327 }
328
329 template <typename T>
330 KBLIB_NODISCARD constexpr friend auto operator==(T t, min_t) -> bool {
331 return t == of<T>();
332 }
333 template <typename T>
334 KBLIB_NODISCARD constexpr friend auto operator==(min_t, T t) -> bool {
335 return t == of<T>();
336 }
337 template <typename T>
338 KBLIB_NODISCARD constexpr friend auto operator!=(T t, min_t) -> bool {
339 return t != of<T>();
340 }
341 template <typename T>
342 KBLIB_NODISCARD constexpr friend auto operator!=(min_t, T t) -> bool {
343 return t != of<T>();
344 }
345
346 template <typename T>
347 KBLIB_NODISCARD constexpr friend auto operator<(T t, min_t) -> bool {
348 return t < of<T>();
349 }
350 template <typename T>
351 KBLIB_NODISCARD constexpr friend auto operator<(min_t, T t) -> bool {
352 return of<T>() < t;
353 }
354 template <typename T>
355 KBLIB_NODISCARD constexpr friend auto operator>(T t, min_t) -> bool {
356 return t > of<T>();
357 }
358 template <typename T>
359 KBLIB_NODISCARD constexpr friend auto operator>(min_t, T t) -> bool {
360 return of<T>() > t;
361 }
362
363 template <typename T>
364 KBLIB_NODISCARD constexpr friend auto operator<=(T t, min_t) -> bool {
365 return t <= of<T>();
366 }
367 template <typename T>
368 KBLIB_NODISCARD constexpr friend auto operator<=(min_t, T t) -> bool {
369 return of<T>() <= t;
370 }
371 template <typename T>
372 KBLIB_NODISCARD constexpr friend auto operator>=(T t, min_t) -> bool {
373 return t >= of<T>();
374 }
375 template <typename T>
376 KBLIB_NODISCARD constexpr friend auto operator>=(min_t, T t) -> bool {
377 return of<T>() >= t;
378 }
379
380 KBLIB_NODISCARD constexpr inline friend auto operator==(min_t, min_t)
381 -> std::true_type {
382 return {};
383 }
384 KBLIB_NODISCARD constexpr inline friend auto operator!=(min_t, min_t)
385 -> std::false_type {
386 return {};
387 }
388 KBLIB_NODISCARD constexpr inline friend auto operator<(min_t, min_t)
389 -> std::false_type {
390 return {};
391 }
392 KBLIB_NODISCARD constexpr inline friend auto operator>(min_t, min_t)
393 -> std::false_type {
394 return {};
395 }
396 KBLIB_NODISCARD constexpr inline friend auto operator<=(min_t, min_t)
397 -> std::true_type {
398 return {};
399 }
400 KBLIB_NODISCARD constexpr inline friend auto operator>=(min_t, min_t)
401 -> std::true_type {
402 return {};
403 }
404
405 KBLIB_NODISCARD constexpr inline friend auto operator==(max_t, min_t)
406 -> std::false_type {
407 return {};
408 }
409 KBLIB_NODISCARD constexpr inline friend auto operator==(min_t, max_t)
410 -> std::false_type {
411 return {};
412 }
413 KBLIB_NODISCARD constexpr inline friend auto operator!=(max_t, min_t)
414 -> std::true_type {
415 return {};
416 }
417 KBLIB_NODISCARD constexpr inline friend auto operator!=(min_t, max_t)
418 -> std::true_type {
419 return {};
420 }
421 KBLIB_NODISCARD constexpr inline friend auto operator<(max_t, min_t)
422 -> std::false_type {
423 return {};
424 }
425 KBLIB_NODISCARD constexpr inline friend auto operator<(min_t, max_t)
426 -> std::true_type {
427 return {};
428 }
429 KBLIB_NODISCARD constexpr inline friend auto operator>(max_t, min_t)
430 -> std::true_type {
431 return {};
432 }
433 KBLIB_NODISCARD constexpr inline friend auto operator>(min_t, max_t)
434 -> std::false_type {
435 return {};
436 }
437 KBLIB_NODISCARD constexpr inline friend auto operator<=(max_t, min_t)
438 -> std::false_type {
439 return {};
440 }
441 KBLIB_NODISCARD constexpr inline friend auto operator<=(min_t, max_t)
442 -> std::true_type {
443 return {};
444 }
445 KBLIB_NODISCARD constexpr inline friend auto operator>=(max_t, min_t)
446 -> std::true_type {
447 return {};
448 }
449 KBLIB_NODISCARD constexpr inline friend auto operator>=(min_t, max_t)
450 -> std::false_type {
451 return {};
452 }
453
454 } min;
457} // namespace nums
458
459template <typename T = double>
460KBLIB_NODISCARD constexpr auto pi() -> T {
461 return 3.1415926535897932384626433832795028841971693993751l;
462}
463template <typename T = double>
464KBLIB_NODISCARD constexpr auto tau() -> T {
465 return 2 * pi<T>;
466}
467template <typename T = double>
468KBLIB_NODISCARD constexpr auto e() -> T {
469 return 2.7182818284590452353602874713526624977572470937000l;
470}
471template <typename T = double>
472KBLIB_NODISCARD constexpr auto root_2() -> T {
473 return 1.4142135623730950488016887242096980785696718753769l;
474}
475template <typename T = double>
476KBLIB_NODISCARD constexpr auto phi() -> T {
477 return 1.6180339887498948482045868343656381177203091798058l;
478}
479
480// saturating to_unsigned
481template <typename A, typename F>
482KBLIB_NODISCARD constexpr auto saturating_cast(F x) noexcept
483 -> enable_if_t<std::is_integral<A>::value and std::is_integral<F>::value
484 and std::is_unsigned<A>::value,
485 A> {
486 if (x < 0) {
487 return 0;
488 } else if (to_unsigned(x) > A(max)) {
489 return max;
490 } else {
491 return static_cast<A>(x);
492 }
493}
494
495// saturating to_signed(signed)
496template <typename A, typename F>
497KBLIB_NODISCARD constexpr auto saturating_cast(F x) noexcept
498 -> enable_if_t<std::is_integral<A>::value and std::is_integral<F>::value
499 and std::is_signed<A>::value
500 and std::is_signed<F>::value,
501 A> {
502 if (x < A(min)) {
503 return min;
504 } else if (to_unsigned(x) > A(max)) {
505 return max;
506 } else {
507 return x;
508 }
509}
510// saturating to_signed(unsigned)
511template <typename A, typename F>
512KBLIB_NODISCARD constexpr auto saturating_cast(F x) noexcept
513 -> enable_if_t<std::is_integral<A>::value and std::is_integral<F>::value
514 and std::is_signed<A>::value
515 and std::is_unsigned<F>::value,
516 A> {
517 if (x > to_unsigned(A(max))) {
518 return max;
519 } else {
520 return x;
521 }
522}
523
526
536template <typename T, typename F>
537KBLIB_NODISCARD constexpr auto quantize_step(F low, F delta, F val) noexcept
538 -> T {
539 static_assert(std::is_unsigned<T>::value, "Destination must be unsigned.");
540 return static_cast<T>((val - low) * static_cast<T>(max) * delta);
541}
542
552template <typename T, typename F>
553KBLIB_NODISCARD constexpr auto quantize_range(F low, F high, F val) noexcept
554 -> T {
555 static_assert(std::is_unsigned<T>::value, "Destination must be unsigned.");
556 auto delta = (high - low) / static_cast<T>(max);
557 return static_cast<T>((val - low) * static_cast<T>(max) * delta);
558}
559
560} // namespace KBLIB_NS
561
562#endif // KBLIB_STATS_H
This header provides some features of C++17 <type_traits> and other headers for C++14,...
Provides basic compile-time logic operations.
constexpr struct kblib::nums::min_t min
constexpr struct kblib::nums::max_t max
constexpr auto quantize_step(F low, F delta, F val) noexcept -> T
Quantize a real-valued value into a discrete integer.
Definition: stats.h:537
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:255
constexpr auto fibonacci(int n) noexcept -> U
Compile-time table fibonacci function.
Definition: stats.h:177
constexpr auto root_2() -> T
Definition: stats.h:472
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:54
constexpr auto e() -> T
Definition: stats.h:468
constexpr auto pi() -> T
Definition: stats.h:460
constexpr auto calc_fib_size() noexcept -> std::size_t
Calculate the index of the largest fibonacci number that can be represented by a given unsigned integ...
Definition: stats.h:132
constexpr auto phi() -> T
Definition: stats.h:476
constexpr auto make_fib_arr() noexcept -> trivial_array< U, N >
Generates the first N values of the fibonacci sequence.
Definition: stats.h:156
constexpr auto tau() -> T
Definition: stats.h:464
constexpr auto quantize_range(F low, F high, F val) noexcept -> T
Quantize a real-valued value into a discrete integer.
Definition: stats.h:553
constexpr auto saturating_cast(F x) noexcept -> enable_if_t< std::is_integral< A >::value and std::is_integral< F >::value and std::is_unsigned< A >::value, A >
Definition: stats.h:482
constexpr auto div(T num, U den) noexcept -> decltype(std::div(num, den))
Definition: stats.h:48
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
Definition: fakestd.h:586
constexpr auto equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) -> bool
Definition: fakestd.h:960
Definition: bits.h:721
A metafunction for logical implication. That is, if A, then B. If not A, B is unimportant.
Definition: logic.h:45
Shorthand for std::numeric_limits::max().
Definition: stats.h:194
constexpr friend auto operator>=(max_t, T t) -> bool
Definition: stats.h:290
constexpr friend auto operator!=(T t, max_t) -> bool
Definition: stats.h:252
constexpr friend auto operator==(T t, max_t) -> bool
Definition: stats.h:244
constexpr friend auto operator>(max_t, T t) -> bool
Definition: stats.h:273
static constexpr auto of() noexcept(noexcept(std::numeric_limits< T >::max()))
Definition: stats.h:203
constexpr friend auto operator>(T t, max_t) -> bool
Definition: stats.h:269
constexpr friend auto operator<(T t, max_t) -> bool
Definition: stats.h:261
constexpr friend auto operator>=(T t, max_t) -> bool
Definition: stats.h:286
constexpr friend auto operator==(max_t, T t) -> bool
Definition: stats.h:248
constexpr auto operator()(L &&lhs, R &&rhs) const noexcept -> decltype(auto)
Return the larger of two values. Returns lhs if equal.
Definition: stats.h:212
constexpr friend auto operator<=(T t, max_t) -> bool
Definition: stats.h:278
constexpr friend auto operator!=(max_t, T t) -> bool
Definition: stats.h:256
constexpr friend auto operator<(max_t, max_t) -> std::false_type
Definition: stats.h:226
constexpr friend auto operator!=(max_t, max_t) -> std::false_type
Definition: stats.h:222
constexpr friend auto operator<=(max_t, max_t) -> std::true_type
Definition: stats.h:234
constexpr friend auto operator>=(max_t, max_t) -> std::true_type
Definition: stats.h:238
constexpr friend auto operator>(max_t, max_t) -> std::false_type
Definition: stats.h:230
constexpr friend auto operator==(max_t, max_t) -> std::true_type
Definition: stats.h:218
constexpr friend auto operator<(max_t, T t) -> bool
Definition: stats.h:265
constexpr friend auto operator<=(max_t, T t) -> bool
Definition: stats.h:282
Shorthand for std::numeric_limits::min()
Definition: stats.h:306
constexpr friend auto operator<=(min_t, min_t) -> std::true_type
Definition: stats.h:396
constexpr friend auto operator>(T t, min_t) -> bool
Definition: stats.h:355
constexpr friend auto operator>=(T t, min_t) -> bool
Definition: stats.h:372
constexpr friend auto operator>(max_t, min_t) -> std::true_type
Definition: stats.h:429
constexpr friend auto operator!=(min_t, min_t) -> std::false_type
Definition: stats.h:384
constexpr friend auto operator<=(T t, min_t) -> bool
Definition: stats.h:364
constexpr friend auto operator>(min_t, T t) -> bool
Definition: stats.h:359
constexpr friend auto operator==(min_t, max_t) -> std::false_type
Definition: stats.h:409
constexpr friend auto operator<(min_t, max_t) -> std::true_type
Definition: stats.h:425
constexpr friend auto operator>=(max_t, min_t) -> std::true_type
Definition: stats.h:445
constexpr friend auto operator==(T t, min_t) -> bool
Definition: stats.h:330
constexpr friend auto operator<(min_t, min_t) -> std::false_type
Definition: stats.h:388
constexpr friend auto operator==(max_t, min_t) -> std::false_type
Definition: stats.h:405
constexpr friend auto operator<(min_t, T t) -> bool
Definition: stats.h:351
constexpr friend auto operator>=(min_t, max_t) -> std::false_type
Definition: stats.h:449
constexpr friend auto operator>(min_t, max_t) -> std::false_type
Definition: stats.h:433
constexpr friend auto operator<(T t, min_t) -> bool
Definition: stats.h:347
constexpr friend auto operator==(min_t, T t) -> bool
Definition: stats.h:334
constexpr friend auto operator!=(min_t, T t) -> bool
Definition: stats.h:342
static constexpr auto of() noexcept(noexcept(std::numeric_limits< T >::min()))
Definition: stats.h:314
constexpr friend auto operator>(min_t, min_t) -> std::false_type
Definition: stats.h:392
constexpr auto operator()(L &&lhs, R &&rhs) const noexcept -> decltype(auto)
Returns the smaller of two values. Returns rhs if equal.
Definition: stats.h:323
constexpr friend auto operator!=(T t, min_t) -> bool
Definition: stats.h:338
constexpr friend auto operator<=(min_t, max_t) -> std::true_type
Definition: stats.h:441
constexpr friend auto operator==(min_t, min_t) -> std::true_type
Definition: stats.h:380
constexpr friend auto operator>=(min_t, T t) -> bool
Definition: stats.h:376
constexpr friend auto operator!=(max_t, min_t) -> std::true_type
Definition: stats.h:413
constexpr friend auto operator<=(max_t, min_t) -> std::false_type
Definition: stats.h:437
constexpr friend auto operator!=(min_t, max_t) -> std::true_type
Definition: stats.h:417
constexpr friend auto operator<=(min_t, T t) -> bool
Definition: stats.h:368
constexpr friend auto operator<(max_t, min_t) -> std::false_type
Definition: stats.h:421
constexpr friend auto operator>=(min_t, min_t) -> std::true_type
Definition: stats.h:400
std::array isn't constexpr enough in C++14, so a dedicated array class is needed for constexpr functi...
Definition: stats.h:84
constexpr auto size() const -> std::size_t
Definition: stats.h:92
constexpr auto begin() const &noexcept -> const T *
Definition: stats.h:94
constexpr auto begin() &noexcept -> T *
Definition: stats.h:93
constexpr auto end() const &noexcept -> const T *
Definition: stats.h:98
constexpr auto operator[](std::size_t n) -> T &
Definition: stats.h:86
constexpr auto operator[](std::size_t n) const -> const T &
Definition: stats.h:89
constexpr friend auto operator==(const trivial_array &a, const trivial_array &b) noexcept -> bool
Definition: stats.h:102
constexpr auto end() &noexcept -> T *
Definition: stats.h:97
constexpr friend auto operator!=(const trivial_array &a, const trivial_array &b) noexcept -> bool
Definition: stats.h:106
std::pair isn't constexpr enough, so I'm stuck with this. All I use it for is removing a temporary va...
Definition: stats.h:61
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NS
Definition: tdecl.h:113
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129