array<int, SIZE> t
As mentionned, with C++17 you can use constexpr
vector<int> countBits(int num) { static constexpr int SIZE = 100000; static constexpr array<int, SIZE> t {[]() constexpr { constexpr uint32_t size = SIZE; array<int, size> v{}; for (int i = 0; i < size; i++) v[i] = v[i>>1] + (i & 1); // or simply v[i] = __builtin_popcount(i); return v;}()}; vector<int> v(t.begin(), t.begin() + num + 1); return v; }
However you will have to use the c++ array type.
int t[SIZE]
If you really want to use a C array int [SIZE], different from array<int, SIZE> use the following trick:
Declare a global array and then compute values inside the main to create the static array at compile time:
int w[100000] = {0}; vector<int> countBits(int num) { vector<int> v(w, w + num + 1); return v; } int main(void) { for (int i = 0; i < 100000; i++) w[i] = __builtin_popcount(i); }
Results
Output at runtime (awful indeed):
OK ( 591 cycles) 0,1,1, -> 0,1,1, OK ( 453 cycles) 0,1,1,2,1,2, -> 0,1,1,2,1,2, OK ( 455 cycles) 0,1,1,2,1,2,2,3,1,2,... -> 0,1,1,2,1,2,2,3,1,2,...
Average Output with the constexpr array:
OK ( 1 cycles) 0,1,1, -> 0,1,1, OK ( 2 cycles) 0,1,1,2,1,2, -> 0,1,1,2,1,2, OK ( 24 cycles) 0,1,1,2,1,2,2,3,1,2,... -> 0,1,1,2,1,2,2,3,1,2,...
Average Output with the second method (slightly faster as we get rid of the overhead of C++ array):
OK ( 0 cycles) 0,1,1, -> 0,1,1, OK ( 1 cycles) 0,1,1,2,1,2, -> 0,1,1,2,1,2, OK ( 23 cycles) 0,1,1,2,1,2,2,3,1,2,... -> 0,1,1,2,1,2,2,3,1,2,...
Benchmark
I benchmarked with:
#include <vector> #include <string> #include <cstdint> #include <array> #include <iostream> #include <ctime> #include <iterator> #include <sstream> using namespace std; vector<int> nums = {2, 5}; vector<vector<int>> expected = {{0,1,1}, {0,1,1,2,1,2}}; // feel free to add more tests for (int i = 0; i < expected.size(); i++) { clock_t start = clock(); vector<int> res = countBits(nums[i]); double elapsedTime = (clock() - start); printf("%s \033[30m(%4.0lf cycles)\033[0m\t %s -> %s\n", (expected[i] == res) ? "\033[34mOK" : "\033[31mKO", elapsedTime, toString(res).c_str(), toString(expected[i]).c_str()); }