C++Guns – RoboBlog

12.07.2018

C++ Guns: create compile time lookup table

Filed under: Allgemein — Tags: — Thomas @ 20:07

Eine lookup table LUT fest im Programm compilieren sollte mit C++ und constexpr kein Problem sein. Zur Kontrolle ob es funktioniert der erzeugte Assembler Code

Beispiel 1 nutzt std::array da es zur Compilezeit eine bekannte Länge hat und eine normale ausgeschriebene Schleife. Unschön ist, dass das Array erst deklariert und danach erst initialisiert wird. Also kein RAII. Zusätzlich muss von Hand der return Type der Funktion f bestimmt werden. Auf jeden Fall funktioniert es. Im Assembercode sind die vorraus berechneten Konstanten zu sehen, die einfach in das Array kopiert werden.

template<size_t N, typename Function>
constexpr auto makeLookUpTable(Function f) {
    using T = std::invoke_result_t<Function,size_t>;

    std::array<T,N> arr{};
    for(size_t i=0; i < N; ++i) {
        arr[i] = f(i);
    }
    return arr;
}

auto func() {
    auto f = [](size_t i){ return std::sin(i/4.0*M_PI); };
    constexpr auto arr = makeLookUpTable<4>(f);
    return arr;
}
func():
        movq    %rdi, %rax
        movq    $0x000000000, (%rdi)
        movq    .LC1(%rip), %rdx
        movq    %rdx, 8(%rdi)
        movq    .LC2(%rip), %rcx
        movq    %rcx, 16(%rdi)
        movq    .LC3(%rip), %rsi
        movq    %rsi, 24(%rdi)
        ret
.LC1:
        .long   1719614412
        .long   1072079006
.LC2:
        .long   0
        .long   1072693248
.LC3:
        .long   1719614413
        .long   1072079006

Die nächste Beispiel nutzt fold expressions und keine explizite Schleife mehr. Damit ist auch RAII wieder Möglich. Der erzeugte Assemblercode ist identisch, da ja auch das selbe gemacht wird. Nur die Syntax ändert sich ein wenig. Was gibt es noch zu sagen? Eigentlich nichts. Ich frage mich wie viel Konstanten erzeugt werden können, bevor die Binary platz.

template<size_t N, typename Function>
constexpr auto makeLookUpTable2(Function f) {
    auto impl = [&f]<std::size_t... Ints>(std::index_sequence<Ints...>) {
        return std::array{(f(Ints))...};
        };
    return impl(std::make_index_sequence<N>{}); 
}

auto func2() {
    auto f = [](size_t i){ return std::sin(i/4.0*M_PI); };
    constexpr auto arr = makeLookUpTable2<4>(f);
    return arr;
}
func2():
        movq    %rdi, %rax
        movq    $0x000000000, (%rdi)
        movq    .LC1(%rip), %rdx
        movq    %rdx, 8(%rdi)
        movq    .LC2(%rip), %rcx
        movq    %rcx, 16(%rdi)
        movq    .LC3(%rip), %rsi
        movq    %rsi, 24(%rdi)
        ret
.LC1:
        .long   1719614412
        .long   1072079006
.LC2:
        .long   0
        .long   1072693248
.LC3:
        .long   1719614413
        .long   1072079006

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress