{"id":3582,"date":"2018-07-12T20:49:56","date_gmt":"2018-07-12T19:49:56","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=3582"},"modified":"2018-07-12T20:49:56","modified_gmt":"2018-07-12T19:49:56","slug":"c-guns-create-compile-time-lookup-table","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=3582","title":{"rendered":"C++ Guns: create compile time lookup table"},"content":{"rendered":"<p>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<\/p>\n<p>Beispiel 1 nutzt std::array da es zur Compilezeit eine bekannte L\u00e4nge hat und eine normale ausgeschriebene Schleife. Unsch\u00f6n ist, dass das Array erst deklariert und danach erst initialisiert wird. Also kein RAII. Zus\u00e4tzlich 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.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate&lt;size_t N, typename Function&gt;\r\nconstexpr auto makeLookUpTable(Function f) {\r\n    using T = std::invoke_result_t&lt;Function,size_t&gt;;\r\n\r\n    std::array&lt;T,N&gt; arr{};\r\n    for(size_t i=0; i &lt; N; ++i) {\r\n        arr&#x5B;i] = f(i);\r\n    }\r\n    return arr;\r\n}\r\n\r\nauto func() {\r\n    auto f = &#x5B;](size_t i){ return std::sin(i\/4.0*M_PI); };\r\n    constexpr auto arr = makeLookUpTable&lt;4&gt;(f);\r\n    return arr;\r\n}\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nfunc():\r\n        movq    %rdi, %rax\r\n        movq    $0x000000000, (%rdi)\r\n        movq    .LC1(%rip), %rdx\r\n        movq    %rdx, 8(%rdi)\r\n        movq    .LC2(%rip), %rcx\r\n        movq    %rcx, 16(%rdi)\r\n        movq    .LC3(%rip), %rsi\r\n        movq    %rsi, 24(%rdi)\r\n        ret\r\n.LC1:\r\n        .long   1719614412\r\n        .long   1072079006\r\n.LC2:\r\n        .long   0\r\n        .long   1072693248\r\n.LC3:\r\n        .long   1719614413\r\n        .long   1072079006\r\n<\/pre>\n<p>Die n\u00e4chste Beispiel nutzt fold expressions und keine explizite Schleife mehr. Damit ist auch RAII wieder M\u00f6glich. Der erzeugte Assemblercode ist identisch, da ja auch das selbe gemacht wird. Nur die Syntax \u00e4ndert sich ein wenig. Was gibt es noch zu sagen? Eigentlich nichts. Ich frage mich wie viel Konstanten erzeugt werden k\u00f6nnen, bevor die Binary platz.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate&lt;size_t N, typename Function&gt;\r\nconstexpr auto makeLookUpTable2(Function f) {\r\n    auto impl = &#x5B;&amp;f]&lt;std::size_t... Ints&gt;(std::index_sequence&lt;Ints...&gt;) {\r\n        return std::array{(f(Ints))...};\r\n        };\r\n    return impl(std::make_index_sequence&lt;N&gt;{}); \r\n}\r\n\r\nauto func2() {\r\n    auto f = &#x5B;](size_t i){ return std::sin(i\/4.0*M_PI); };\r\n    constexpr auto arr = makeLookUpTable2&lt;4&gt;(f);\r\n    return arr;\r\n}\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nfunc2():\r\n        movq    %rdi, %rax\r\n        movq    $0x000000000, (%rdi)\r\n        movq    .LC1(%rip), %rdx\r\n        movq    %rdx, 8(%rdi)\r\n        movq    .LC2(%rip), %rcx\r\n        movq    %rcx, 16(%rdi)\r\n        movq    .LC3(%rip), %rsi\r\n        movq    %rsi, 24(%rdi)\r\n        ret\r\n.LC1:\r\n        .long   1719614412\r\n        .long   1072079006\r\n.LC2:\r\n        .long   0\r\n        .long   1072693248\r\n.LC3:\r\n        .long   1719614413\r\n        .long   1072079006\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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\u00e4nge hat und eine normale ausgeschriebene Schleife. Unsch\u00f6n ist, dass das Array erst deklariert und danach erst initialisiert wird. Also [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[17],"class_list":["post-3582","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-cpp"],"_links":{"self":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3582","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3582"}],"version-history":[{"count":5,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3582\/revisions"}],"predecessor-version":[{"id":3587,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3582\/revisions\/3587"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3582"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3582"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3582"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}