The Computer Language
24.11 Benchmarks Game

fannkuch-redux C++ g++ #6 program

source code

// The Computer Language Benchmarks Game
// https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
//
// Contributed by Andrei Simion (with patch from Vincent Yu)
// Based on "fannkuch-redux C++ g++ #5", contributed by Dave Compton,
// which in turn was based on the C program by Jeremy Zerfasm
// which in turn was based on the Ada program by Jonathan Parker and 
// Georg Bauhaus which in turn was based on code by Dave Fladebo, 
// Eckehard Berns, Heiner Marxen, Hongwei Xi, and The Anh Tran and 
// also the Java program by Oleg Mazurov.

#include <array>
#include <iostream>
#include <algorithm>
#include <immintrin.h>

using small_int_t = char;
using big_int_t   = int64_t;

constexpr small_int_t max_n = 16;
constexpr int max_blocks = 24;

struct Masks
{
    __m128i masks_reverse[16];
    __m128i masks_shift[16];
   
    Masks()
    {
        // first elements are never accessed
        masks_reverse[1] = _mm_setr_epi8(1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[2] = _mm_setr_epi8(2, 1, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[3] = _mm_setr_epi8(3, 2, 1, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[4] = _mm_setr_epi8(4, 3, 2, 1, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[5] = _mm_setr_epi8(5, 4, 3, 2, 1, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[6] = _mm_setr_epi8(6, 5, 4, 3, 2, 1, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[7] = _mm_setr_epi8(7, 6, 5, 4, 3, 2, 1, 0, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[8] = _mm_setr_epi8(8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 10, 11, 12, 13, 14, 15);
        masks_reverse[9] = _mm_setr_epi8(9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10, 11, 12, 13, 14, 15);
        masks_reverse[10] = _mm_setr_epi8(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 11, 12, 13, 14, 15);
        masks_reverse[11] = _mm_setr_epi8(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 12, 13, 14, 15);
        masks_reverse[12] = _mm_setr_epi8(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 13, 14, 15);
        masks_reverse[13] = _mm_setr_epi8(13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 14, 15);
        masks_reverse[14] = _mm_setr_epi8(14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15);
        masks_reverse[15] = _mm_setr_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);

        masks_shift[1] = _mm_setr_epi8(1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[2] = _mm_setr_epi8(1, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[3] = _mm_setr_epi8(1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[4] = _mm_setr_epi8(1, 2, 3, 4, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[5] = _mm_setr_epi8(1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[6] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[7] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[8] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 0, 9, 10, 11, 12, 13, 14, 15);
        masks_shift[9] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14, 15);
        masks_shift[10] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 11, 12, 13, 14, 15);
        masks_shift[11] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 12, 13, 14, 15);
        masks_shift[12] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 13, 14, 15);
        masks_shift[13] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 14, 15);
        masks_shift[14] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 15);
        masks_shift[15] = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0);
    }
};

std::array<big_int_t, max_n> compute_factorials(small_int_t n)
{
    std::array<big_int_t, max_n> factorials;

    factorials[0] = 1;
    for (small_int_t i = 1; i <= n; ++i)
        factorials[i] = factorials[i-1] * i;

    return factorials;
} 

std::array<int, 2> get_blocks_and_size(small_int_t n, 
                                       std::array<big_int_t, max_n>& factorials)
{
    int blocks = max_blocks;
    if (blocks > factorials[n])
        blocks = 1;
    int block_size = factorials[n] / blocks;
    
    return {blocks, block_size};
}

std::array<big_int_t, max_n> create_count(small_int_t n, big_int_t start,
                                          std::array<big_int_t, max_n>& factorials)
{
    std::array<big_int_t, max_n> count;
   
    for (small_int_t i = n - 1; i >= 0; --i) 
    {
        big_int_t d = start / factorials[i];
        start = start % factorials[i];
        count[i] = d;
    }

    return count;
}

__m128i create_current(small_int_t n, 
                              std::array<big_int_t, max_n>& count)
{
    // not a "hotspot", using intrinsics for rotations don't bring
    // much benefit here considering the increased complexity
    alignas(16) std::array<small_int_t, max_n> current_aux = 
	{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};  
    
    for (small_int_t i = n - 1; i >= 0; --i) 
    {
        std::rotate(current_aux.begin(), 
                    current_aux.begin() + count[i],
                    current_aux.begin() + i + 1);
    }
    __m128i current = _mm_load_si128((__m128i*)current_aux.data());
    return current;
}

inline __m128i increment_permutation(std::array<big_int_t, max_n>& count,
			          __m128i current, const Masks& masks)
{
    for (small_int_t i = 1; ; ++i) 
    {
        current = _mm_shuffle_epi8(current, masks.masks_shift[i]);  
        if (++count[i] <= i)
            break;
        count[i] = 0;
    }
    return current;
}

inline __m128i reverse(__m128i x, small_int_t idx, const Masks& masks)
{
    return _mm_shuffle_epi8(x, masks.masks_reverse[idx]);
}


int main(int argc, char **argv)
{   
    int n = atoi(argv[1]);
    auto factorials = compute_factorials(n);
    auto [blocks, block_size] = get_blocks_and_size(n, factorials);

    small_int_t max_flips = 0;
    big_int_t checksum  = 0;

    // iterate over each block.
    #pragma omp parallel for \
        reduction(max:max_flips) \
        reduction(+:checksum)
    for (big_int_t block_start = 0; 
            block_start < factorials[n];
            block_start += block_size) 
    {
        Masks masks;
        
        std::array<big_int_t, max_n> count = create_count(n, block_start, factorials);      

        __m128i current = create_current(n, count);
        __m128i current_start = current;	

        small_int_t first = _mm_extract_epi8(current, 0);

        // iterate over each permutation in the block.
        big_int_t crt_idx = block_start;
        big_int_t block_end = block_start + block_size;
	
        while (crt_idx < block_end) 
        { 
            if (first > 0)
            {   
                small_int_t flips = 0;
                while (first != 0) 
                {
                    // patch from Vincent Yu
                    auto next = reinterpret_cast<char(&)[16]>(current)[first];
                    current = reverse(current, first, masks);
                    first = next;
                    ++flips;
                } 
                
                checksum += (crt_idx % 2) == 0 ? flips : -flips;

                if (flips > max_flips)
                    max_flips = flips;
            }

            current = increment_permutation(count, current_start, masks);
            current_start = current;
            
            first = _mm_extract_epi8(current, 0);
            ++crt_idx;
        }
    }
    std::cout << checksum << "\nPfannkuchen(" << n << ") = " << (int)max_flips << "\n";
}
    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
g++ (Ubuntu 14.2.0-4ubuntu2) 14.2.0


 Tue, 22 Oct 2024 20:00:02 GMT

MAKE:
/usr/bin/g++ -c -pipe -O3 -fomit-frame-pointer -march=ivybridge  -std=c++17 -fopenmp fannkuchredux.gpp-6.c++ -o fannkuchredux.gpp-6.c++.o &&  \
        /usr/bin/g++ fannkuchredux.gpp-6.c++.o -o fannkuchredux.gpp-6.gpp_run -fopenmp 
In file included from /usr/include/c++/14/bits/stl_pair.h:61,
                 from /usr/include/c++/14/bits/stl_algobase.h:64,
                 from /usr/include/c++/14/array:43,
                 from fannkuchredux.gpp-6.c++:12:
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 32 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 32 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 33 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [1, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 33 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 34 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [2, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 34 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 35 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [3, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 35 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 36 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [4, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 36 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 37 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [5, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 37 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 38 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [6, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 38 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 39 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [7, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 39 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 40 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [8, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 40 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 41 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [9, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 41 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 42 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [10, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 42 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 43 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [11, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 43 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 44 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [12, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 44 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 45 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [13, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 45 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
In function ‘std::_Require<std::__not_<std::__is_tuple_like<_Tp> >, std::is_move_constructible<_Tp>, std::is_move_assignable<_Tp> > std::swap(_Tp&, _Tp&) [with _Tp = char]’,
    inlined from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:185:11,
    inlined from ‘_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = char*; _ForwardIterator2 = char*]’ at /usr/include/c++/14/bits/stl_algobase.h:215:16,
    inlined from ‘_RandomAccessIterator std::_V2::__rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1265:20,
    inlined from ‘_FIter std::_V2::rotate(_FIter, _FIter, _FIter) [with _FIter = char*]’ at /usr/include/c++/14/bits/stl_algo.h:1357:27,
    inlined from ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’ at fannkuchredux.gpp-6.c++:112:20:
/usr/include/c++/14/bits/move.h:222:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  222 |       __a = _GLIBCXX_MOVE(__b);
      |           ^
/usr/include/c++/14/array: In function ‘__m128i create_current(small_int_t, std::array<long int, 16>&)’:
/usr/include/c++/14/array:115:55: note: at offset 46 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
  115 |       typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
      |                                                       ^~~~~~~~
/usr/include/c++/14/array:115:55: note: at offset [14, 16] into destination object ‘std::array<char, 16>::_M_elems’ of size 16
/usr/include/c++/14/array:115:55: note: at offset 46 into destination object ‘std::array<char, 16>::_M_elems’ of size 16
rm fannkuchredux.gpp-6.c++

4.96s to complete and log all make actions

COMMAND LINE:
 ./fannkuchredux.gpp-6.gpp_run 12

PROGRAM OUTPUT:
3968050
Pfannkuchen(12) = 65