/src/serenity/AK/IntegralMath.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2022, Leon Albrecht <leon2002.la@gmail.com> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/BuiltinWrappers.h> |
10 | | #include <AK/Concepts.h> |
11 | | #include <AK/Types.h> |
12 | | |
13 | | namespace AK { |
14 | | |
15 | | template<Integral T> |
16 | | constexpr T exp2(T exponent) |
17 | 788k | { |
18 | 788k | return static_cast<T>(1) << exponent; |
19 | 788k | } _ZN2AK4exp2ITkNS_8Concepts8IntegralEmEET_S2_ Line | Count | Source | 17 | 40.4k | { | 18 | 40.4k | return static_cast<T>(1) << exponent; | 19 | 40.4k | } |
_ZN2AK4exp2ITkNS_8Concepts8IntegralEjEET_S2_ Line | Count | Source | 17 | 619k | { | 18 | 619k | return static_cast<T>(1) << exponent; | 19 | 619k | } |
_ZN2AK4exp2ITkNS_8Concepts8IntegralElEET_S2_ Line | Count | Source | 17 | 19.2k | { | 18 | 19.2k | return static_cast<T>(1) << exponent; | 19 | 19.2k | } |
_ZN2AK4exp2ITkNS_8Concepts8IntegralEiEET_S2_ Line | Count | Source | 17 | 91.1k | { | 18 | 91.1k | return static_cast<T>(1) << exponent; | 19 | 91.1k | } |
_ZN2AK4exp2ITkNS_8Concepts8IntegralEhEET_S2_ Line | Count | Source | 17 | 18.0k | { | 18 | 18.0k | return static_cast<T>(1) << exponent; | 19 | 18.0k | } |
|
20 | | |
21 | | template<Integral T> |
22 | | constexpr T log2(T x) |
23 | 1.08M | { |
24 | 1.08M | return x ? (8 * sizeof(T) - 1) - count_leading_zeroes(static_cast<MakeUnsigned<T>>(x)) : 0; |
25 | 1.08M | } _ZN2AK4log2ITkNS_8Concepts8IntegralEmEET_S2_ Line | Count | Source | 23 | 142 | { | 24 | 142 | return x ? (8 * sizeof(T) - 1) - count_leading_zeroes(static_cast<MakeUnsigned<T>>(x)) : 0; | 25 | 142 | } |
_ZN2AK4log2ITkNS_8Concepts8IntegralEjEET_S2_ Line | Count | Source | 23 | 1.08M | { | 24 | 1.08M | return x ? (8 * sizeof(T) - 1) - count_leading_zeroes(static_cast<MakeUnsigned<T>>(x)) : 0; | 25 | 1.08M | } |
Unexecuted instantiation: _ZN2AK4log2ITkNS_8Concepts8IntegralEiEET_S2_ _ZN2AK4log2ITkNS_8Concepts8IntegralEtEET_S2_ Line | Count | Source | 23 | 1.76k | { | 24 | 1.76k | return x ? (8 * sizeof(T) - 1) - count_leading_zeroes(static_cast<MakeUnsigned<T>>(x)) : 0; | 25 | 1.76k | } |
Unexecuted instantiation: _ZN2AK4log2ITkNS_8Concepts8IntegralEhEET_S2_ |
26 | | |
27 | | template<Integral T> |
28 | | constexpr T ceil_log2(T x) |
29 | 680 | { |
30 | 680 | if (x <= 1) |
31 | 538 | return 0; |
32 | | |
33 | 142 | return AK::log2(x - 1) + 1; |
34 | 680 | } _ZN2AK9ceil_log2ITkNS_8Concepts8IntegralEmEET_S2_ Line | Count | Source | 29 | 680 | { | 30 | 680 | if (x <= 1) | 31 | 538 | return 0; | 32 | | | 33 | 142 | return AK::log2(x - 1) + 1; | 34 | 680 | } |
Unexecuted instantiation: _ZN2AK9ceil_log2ITkNS_8Concepts8IntegralEjEET_S2_ Unexecuted instantiation: _ZN2AK9ceil_log2ITkNS_8Concepts8IntegralEiEET_S2_ |
35 | | |
36 | | template<Integral I> |
37 | | constexpr I pow(I base, I exponent) |
38 | 315 | { |
39 | | // https://en.wikipedia.org/wiki/Exponentiation_by_squaring |
40 | 315 | if (exponent < 0) |
41 | 0 | return 0; |
42 | 315 | if (exponent == 0) |
43 | 0 | return 1; |
44 | | |
45 | 315 | I res = 1; |
46 | 1.14k | while (exponent > 0) { |
47 | 828 | if (exponent & 1) |
48 | 355 | res *= base; |
49 | 828 | base *= base; |
50 | 828 | exponent /= 2u; |
51 | 828 | } |
52 | 315 | return res; |
53 | 315 | } |
54 | | |
55 | | template<auto base, UnsignedIntegral U = decltype(base)> |
56 | | constexpr bool is_power_of(U x) |
57 | | { |
58 | | if constexpr (base == 1) |
59 | | return x == 1; |
60 | | else if constexpr (base == 2) |
61 | | return is_power_of_two(x); |
62 | | |
63 | | if (base == 0 && x == 0) |
64 | | return true; |
65 | | if (base == 0 || x == 0) |
66 | | return false; |
67 | | |
68 | | while (x != 1) { |
69 | | if (x % base != 0) |
70 | | return false; |
71 | | x /= base; |
72 | | } |
73 | | return true; |
74 | | } |
75 | | |
76 | | template<UnsignedIntegral T> |
77 | | constexpr T reinterpret_as_octal(T decimal) |
78 | | { |
79 | | T result = 0; |
80 | | T n = 0; |
81 | | while (decimal > 0) { |
82 | | result += pow<T>(8, n++) * (decimal % 10); |
83 | | decimal /= 10; |
84 | | } |
85 | | return result; |
86 | | } |
87 | | |
88 | | template<UnsignedIntegral T> |
89 | | constexpr MakeSigned<T> sign_extend(T value, u8 bits) |
90 | 145k | { |
91 | | // C++ considers the shift by sizeof(T) * 8 UB, and it doesn’t make logical sense to sign-extend 0 bits anyways. |
92 | 145k | VERIFY(bits > 0); |
93 | 145k | auto shift = sizeof(T) * 8 - bits; |
94 | 145k | return static_cast<MakeSigned<T>>(value << shift) >> shift; |
95 | 145k | } _ZN2AK11sign_extendITkNS_8Concepts16UnsignedIntegralEhEENS_6Detail12__MakeSignedIT_E4TypeES4_h Line | Count | Source | 90 | 635 | { | 91 | | // C++ considers the shift by sizeof(T) * 8 UB, and it doesn’t make logical sense to sign-extend 0 bits anyways. | 92 | 635 | VERIFY(bits > 0); | 93 | 635 | auto shift = sizeof(T) * 8 - bits; | 94 | 635 | return static_cast<MakeSigned<T>>(value << shift) >> shift; | 95 | 635 | } |
_ZN2AK11sign_extendITkNS_8Concepts16UnsignedIntegralEmEENS_6Detail12__MakeSignedIT_E4TypeES4_h Line | Count | Source | 90 | 141k | { | 91 | | // C++ considers the shift by sizeof(T) * 8 UB, and it doesn’t make logical sense to sign-extend 0 bits anyways. | 92 | 141k | VERIFY(bits > 0); | 93 | 141k | auto shift = sizeof(T) * 8 - bits; | 94 | 141k | return static_cast<MakeSigned<T>>(value << shift) >> shift; | 95 | 141k | } |
_ZN2AK11sign_extendITkNS_8Concepts16UnsignedIntegralEjEENS_6Detail12__MakeSignedIT_E4TypeES4_h Line | Count | Source | 90 | 3.63k | { | 91 | | // C++ considers the shift by sizeof(T) * 8 UB, and it doesn’t make logical sense to sign-extend 0 bits anyways. | 92 | 3.63k | VERIFY(bits > 0); | 93 | 3.63k | auto shift = sizeof(T) * 8 - bits; | 94 | 3.63k | return static_cast<MakeSigned<T>>(value << shift) >> shift; | 95 | 3.63k | } |
|
96 | | |
97 | | } |