img
i
회원가입시 광고가 제거 됩니다
Balancing Magic Numbers and Readability in C++ Code
5 \$\begingroup\$ I have written a C++ program that calculates the floor of 64 divided by n for values of n from 1 to 64. I'm trying to get a faster SWAR algorithm that avoids costly divisions. The problem is that the SWAR method uses a lot of magic numbers. I used constexpr functions to show the origin of the magic numbers, but the code has become long and unreadable. Is it possible to find a middle ground where the code is both concise and readable? Or should I leave the long constexpr code? Here is my code: #include #include #include #include // Function floor(64/n)=⌊64/n⌋, for 0(64u / n); } // Function to generate an array of ⌊64/n⌋ values for n from 1 to 64 constexpr std::array generateResultArray() { std::array result = {}; for (uint8_t i = 1; i RESULT_TO_GENERATE = generateResultArray(); // Union to allow access to a 64-bit integer as an array of 8-bit integers union Union64_8 { uint64_t as_uint64; std::array as_array_uint8; }; // Function to generate an array of indices n, where the value of ⌊64/n⌋ changes constexpr Union64_8 jumpsBy1() { Union64_8 jumps = {0}; jumps.as_array_uint8 = {}; uint8_t idx = 0; for (uint8_t i = 8; i RESULT_TO_GENERATE[i + 1]) { jumps.as_array_uint8[idx++] = i; } } jumps.as_array_uint8[idx] = 65u; return jumps; } // Precomputed array of indices where the value of ⌊64/n⌋ changes constexpr Union64_8 JUMPS_BY_1 = jumpsBy1(); // Multiplicator array initialized to all ones. // By multiplying with an 8 bit uint, makes 8 copies bitshifted. constexpr Union64_8 MULTIPLICATOR = {.as_array_uint8 = {{1, 1, 1, 1, 1, 1, 1, 1}}}; // This array of compare flags is initialized with each element set to 0b10000000 (128 in decimal) // It is used to flag the bits that change during multiple SWAR comparison operations x> (8 * n)) & 255ULL; } // For n >= 8, use the SWAR technique uint64_t substraction = (JUMPS_BY_1.as_uint64 | COMPARE_FLAGS.as_uint64) - n * MULTIPLICATOR.as_uint64; uint8_t result = __builtin_popcountll(substraction & COMPARE_FLAGS.as_uint64); return result; }; int main() { // Print the precomputed array of ⌊64/n⌋ values std::cout (RESULT_TO_GENERATE[i]) (jump) (n) (result) << std::endl; } return 0; } c++performanceconstantsc++23constant-expression Share Follow edited 6 hours ago J_H 35.5k33 gold badges3333 silver badges130130 bronze badges asked 9 hours ago wepajakegwepajakeg 16377 bronze badges \$\endgroup\$ 1 2 \$\begingroup\$ Using a union for type punning is not legal in C++. \$\endgroup\$ – indi Commented 9 hours ago Add a comment  |