Skip to content

Instantly share code, notes, and snippets.

@Len42
Last active May 25, 2022 20:13
Show Gist options
  • Save Len42/c65a26797001df988a218e00eb7ae96b to your computer and use it in GitHub Desktop.
Save Len42/c65a26797001df988a218e00eb7ae96b to your computer and use it in GitHub Desktop.
DataTable - Compile-time calculation of data lookup tables in C++
// DataTable - Compile-time calculation of data lookup tables
// by Len Popp
// Ref:
// https://github.com/AshleyRoll/cppcon21/blob/main/code/table_gen_1.cpp - Ashley Roll
// https://tinyurl.com/constexpr2021 - Jason Turner
#include <array>
#include <algorithm>
#include <ranges>
// DataTable - Class template for static tables of pre-calculated data
// The table contains NUM_VALUES values of type VALUE_T.
// Each value is calculated by function FUNC_CALC1 which has this signature:
// VALUE_T FUNC_CALC1(std::size_t index, std::size_t numValues)
// Access to the data is read-only.
template<typename VALUE_T, std::size_t NUM_VALUES, VALUE_T FUNC_CALC1(std::size_t index, std::size_t numValues)>
class DataTable
{
public:
// Constructor uses FUNC_CALC1 to fill dataArray
constexpr DataTable()
{
for (std::size_t index = 0; index < NUM_VALUES; ++index) {
dataArray[index] = FUNC_CALC1(index, NUM_VALUES);
}
}
constexpr std::size_t size() const { return NUM_VALUES; }
constexpr const auto& getArray() const { return dataArray; }
constexpr const VALUE_T& operator[](std::size_t index) const { return dataArray[index]; }
private:
// dataArray is a fixed-size array of values that is initialized at compile time
VALUE_T dataArray[NUM_VALUES];
};
// MakeDataTable - Compile-time calculation of data lookup tables
// by Len Popp
#include "DataTable.h"
#include <cmath>
#include <numbers>
#include <iostream>
// Example: SquareTable - A simple table calculated by a lambda
static constexpr DataTable<uint16_t, 10,
[](const std::size_t index, const std::size_t /*numValues*/) {
return static_cast<uint16_t>(index * index);
}>
SquareTable;
// Example: SineTable - A table of sine values converted to positive integers
// One extra entry is included (513 instead of 512) to help with interpolation.
// NOTE: This isn't supposed to work, but GCC declares most functions in <cmath>
// to be constexpr, which is non-standard but very useful!
#if defined(__GNUC__)
template<typename VALUE_T>
constexpr VALUE_T sineCalc(std::size_t index, std::size_t numValues)
{
constexpr VALUE_T half = std::numeric_limits<VALUE_T>::max() / 2;
double phase = 2 * std::numbers::pi / (numValues-1) * index;
double sine = (std::sin(phase) + 1) * half;
return static_cast<VALUE_T>(std::round(sine));
}
static constexpr DataTable<uint16_t, 512+1, sineCalc> SineTable;
#endif
int main()
{
for (auto n : SquareTable.getArray()) {
std::cout << n << ' ';
}
std::cout << '\n';
#if defined(__GNUC__)
for (auto n : SineTable.getArray()) {
std::cout << n << ' ';
}
std::cout << '\n';
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment