/////////////////////////////////////////////////////////////////////////////
// This C file has been created automatically. Do not edit!!!
/////////////////////////////////////////////////////////////////////////////



/** @file mat24_functions.c
 File ``mat24_functions.c`` contains the C implementation of the 
 functionality of Python module ``mmgroup.mat24``

 This covers the Golay code, its cocode, the Parker loop,
 the Mathieu group Mat24, and the group of standard automorphisms
 of the Parker loop.
*/


// This is a C implementation of the functionality of Python class
// Mat24 as described in the sequel. Note that all exported funtions
// in this module are prefixed with 'mat24_'

// %%PY_DOCSTR Mat24_doc
// The automatically generated file ``mat24_functions.c`` contains the C
// code for the functions exported by the python extension ``mmgroup.mat24``.
// 
// These functions are documented in file ``mat24_functions.c``. Here
// just give an overview of the functionality of that module.
// 
// File  ``mat24_functions.c`` has been generated from the source file
// ``mat24_functions.ske`` using the code generator in module
// ``mmgroup.generate_c``.
// 
// The functions in file ``mat24_functions.c`` perform basic computations
// in the Golay code, in its cocode, and in the Mathieu group ``Mat24``.
// They also deal with  Parker loop ``Pl`` and with its automorphism group
// ``AutPl``. A more comfortable python interface to these objects is
// provided by the python classes ``GCode``, ``Cocode``, ``PLoop``, and
// ``AutPL`` in module ``mmgroup``.
// 
// All C functions in file ``mat24_functions.c`` start with the prefix
// ``mat24_``. These functions are also called from C functions in other
// modules. Therefore we store the binary code for these functions in
// a shared library. For some of these functions there are also
// macros (defined with ``#define``), starting with ``mat24_def_``.
// 
// There is a one-to-one correspondence between the functions in
// ``mat24_functions.c`` and the function exported from the python
// extension ``mmgroup.mat24``, see subsection
// *Mapping C functions to python functions* for details.
// 
// The python class ``Mat24`` in module ``mmgroup.dev.mat24.mat24_ref``
// contains pure python implementations of most functions of the
// ``mmgroup.mat24`` extension as class methods. This class is used for
// testing and as a substitute for the ``mmgroup.mat24`` extension in
// an early stage of the build process.
// 
// In the following subsections the term *C functions* refers to the
// C functions in file ``mat24_functions.c``. In the documentation, the
// names of the C functions  are given without the ``mat24_`` prefix.
// The term *API reference* means the main document
// *The mmgroup API reference* of this project.
// 
// The Golay code ``C`` and its cocode ``C*``
// ..........................................
// 
// The Mathieu group ``Mat24`` operates as a permutation group on a set
// of 24 elements which we label with numbers 0,...,23 for use in Python
// and C. So it also operates on a vector space ``V = GF(2)**24``, with
// ``GF(2) = {0,1}``. Here ``**`` means exponentiation.
// 
// A vector ``v`` in a vector space over ``GF(2)`` is called a bit
// vector. We represent a bit vector as an integer, so that the
// ``i``-th  bit of ``v`` (with valence ``2**i``) is the ``i``-th
// component of ``v``.
// 
// The Golay code ``C`` ia a 12-dimensional subspace of ``V`` fixed by
// ``Mat24``. There are functions for checking and completing codewords
// and for getting the syndrome of a 24-bit vector.
// 
// We internally use a basis of ``V`` such that the first 12 basis
// vectors are a transversal of the Golay cocode and the last 12 basis
// vectors span the Golay code. These basis vectors are listed in the
// API reference.
// 
// We represent vectors in ``V``, ``C`` and ``C*`` and in the subset of
// octads of ``C`` as follows:
// 
// The 759 octads are numbered from 0 to 758. They do not form a vector
// space.
// The 2**12 Golay code words are represented as binary numbers 0 to 4095.
// The 2**12 cocode words are represented as binary numbers 0 to 4095.
// A more detailed description is given in the API reference.
// 
// As usual, binary numbers representing bit vectors are added with the
// XOR operation ``^``. Unused high bits in input bit vectors are ignored.
// 
// Functions changing an object from one representation ``xxx`` to another
// representation ``yyy`` are named ``xxx_to_yyy``, where ``xxx``,
// ``yyy`` is as follows::
// 
//   vect:      standard representation of a bit vector in V = GF(2)**24
//              coded as a 24-bit integer.
//   vintern:   internal representation a bit vector in V as a vector in
//              the basis given above, coded as 24-bit integer.
//   gcode:     representation of a Golay code word in the basis given
//              given above, coded as 12-bit integer.
//   octad:     representation as an octad numbered from 0 to 758
//              (in lexical order given by representation  'gcode')
//   cocode:    representation as a cocode word in the basis given above,
//              coded as 12-bit integer.
// 
// 
// All these representations are given as unsigned integers.
// 
// We implement the following conversion functions::
// 
//     vect_to_vintern, vintern_to_vect, vect_to_cocode,
//     vintern_to_vect, gcode_to_vect, cocode_to_vect.
// 
// Here irrelevant bits of the input are ignored. Function
// ``cocode_to_vect`` returns one of many possible solutions.
// 
// In the following functions the input is checked and the function
// fails in case of an error::
// 
//     vect_to_gcode, vect_to_octad, gcode_to_octad,
//     octad_to_vect, octad_to_gcode
// 
// In case of failure, these C functions return a special value as
// indicated in the documentation of the function in the .c file.
// The corresponding python functions raise ``ValueError`` in case
// of failure.
// 
// 
// Function ``syndrome()`` takes a vector ``v`` and calculates its
// syndrome, which is a vector of minimum weight equivalent to ``v``
// modulo the Golay code. Function ``cocode_syndrome()`` takes a
// ``cocode`` representation of a cocode word instead.
// 
// Function ``scalar_prod()`` returns the scalar product of a Golay code
// vector in ``gcode`` and a cocode vector in ``cocode`` representation.
// 
// 
// 
// 
// The Mathieu group Mat24
// .......................
// 
// This class also contains support for the Mathieu group ``Mat24``.
// An element of ``Mat24`` can be represented in one of the following ways::
// 
//   perm:    Representation as an array of length 24 encoding a
//            permutation of the integers 0,...,23 as a mapping.
// 
//   m24num:  Representation as an integer 0 <= i < 244823040. Here i
//            is the number of the permutation in lexicographic order.
//            So the identity permutation is coded as 0.
// 
//   matrix:  Representation as a 12 x 12 bit matrix acting on the Golay
//            code by right multiplication. This matrix acts on a Golay
//            code vectors (given in the 'gcode' representation) by
//            right multiplication.
//            Such a matrix is implemented as an array of integers with
//            each integer corresponding to a row vector of the matrix.
//            The purpose of this representation is to support
//            the Parker loop and its automorphism group. Therefore a
//            row vector is implemented as a 32-bit integer.
// 
// We implement the following conversion functions::
// 
//     m24num_to_perm, perm_to_m24num, perm_to_matrix, matrix_to_perm.
// 
// There is a function ``perm_check()`` for checking if an array of
// length 24 really represents an element of the Mathieu group ``Mat24``.
// All other function operating on ``Mat24`` in any way do not check if
// their inputs are really in ``Mat24``. They will output garbage on bad
// input, but they are not supposed to crash.
// 
// The easiest way to create a random element of ``Mat24`` is to create
// a random integer ``0 <= x < 244823040``, and to call function
// ``m24num_to_perm(x)``.
// 
// 
// Operation of the group ``Mat24`` on vectors
// ...........................................
// 
// Elements of ``Mat24`` operate from the right on vectors
// ``in V = GF(2)**24`` or on Golay code or cocode vectors.
// A function performing such an operation has the name::
// 
//     op_<vector>_<group>
// 
// where ``<vector>`` indicates the representation of the vector space
// and ``<group>`` indicates the representation of the group. We
// implement the functions::
// 
//     op_vect_perm, op_gcode_matrix, op_gcode_perm, op_cocode_perm.
// 
// E.g. function ``op_gcode_matrix`` operates on a Golay code word (in
// ``gcode`` representation) by right multiplying an element ``m``
// of ``Mat24`` with it. Here element ``m`` is a  12 times 12 matrix
// (in ``matrix`` representation).
// 
// 
// Group operation in the group ``Mat24``
// ......................................
// 
// Multiplication and inversion in the group ``Mat24`` is supported for
// the permutation representation ``perm``. Therefore we have functions::
// 
//    mul_perm, inv_perm
// 
// 
// 
// The Parker loop ``Pl``
// ......................
// 
// We support the Parker loop ``Pl`` and also its automorphism group
// ``AutPl``.
// 
// An element of ``Pl`` is a pair ``(v, s)``, with ``v`` a Golay code
// word and ``s`` a sign bit, as described in the API reference. We
// represent the element ``(v, s)`` as a  13-bit integer, with ``v``
// given by bits 0,...,11 (in ``gcode`` representation) and the sign
// ``s`` given by bit 12. We call this representation of the Parker
// loop the ``ploop`` representation. So we can convert and element
// of ``C`` in 'gcode' representation to an element of ``Pl`` in
// ``ploop`` representation by adjusting the sign in bit 12.
// 
// Function ``mul_ploop()`` returns the product of two elements of
// the Parker Loop. Function ``inv_ploop()`` returns the inverse of
// ab element of the Parker loop.
// 
// Let ``theta`` be the cocycle for the Parker loop defined in the
// API reference. For an element ``v1`` of of ``C`` or ``Pl`` in
// ``gcode`` or ``ploop`` representation, the function
// ``ploop_theta(v1)`` returns the value ``theta(v1)`` (which is
// in ``C*``) in ``cocode`` representation. Function
// ``ploop_cocode(v1, v2)`` returns the value of the coycle
// ``theta(v1, v2)``, which is 0 or 1.
// 
// 
// The group ``AutPl`` of standard automorphisms of the ``Pl``
// ...........................................................
// 
// 
// An automorphism of the Parker loop is implemented as an array ``a``
// of twelve 32-bit integers. The lowest 13 bits of ``a[i]`` encode
// the image of the i-th basis vector of the Parker loop. Here the
// basis of the Parker loop corresponds to the selected basis of the
// Golay code, and each basis vector has positive sign.
// 
// The bits ``13,...,24`` of the vectors ``a[i]`` encode a quadratic
// form which facilitates computations in ``AutPl``, as described
// in  section :ref:`implement-autpl-label` in the
// *Guide for developers*.
// 
// This representation of ``AutPl`` is called the ``autpl``
// representation. We only use the ``autpl`` representation for
// elements of ``AutPl``.
// 
// Function ``perm_to_autpl(c, p)`` computes an automorphism ``m``
// of the Parker loop created from an element ``p`` of ``Mat24``
// (given in ``perm`` representation) and a cocode element ``c``
// (given in ``cocode`` representation). If ``m`` is equal to
// the result of ``perm_to_autpl(c, p)``, then we can get back
// ``p`` and ``c`` be computing ``p = autpl_to_perm(m)`` and
// ``c = autpl_to_cocode(m)``.
// 
// Function ``cocode_to_autpl(c)`` is equivalent to function
// ``perm_to_autpl(c, p0)``,  where ``p0`` is the identity
// permutation. Note that::
// 
//    perm_to_autpl(c, p) = cocode_to_autpl(c) * perm_to_autpl(0, p).
// 
// Here ``perm_to_autpl(0, p)`` is equivalent to
// *standard representative* of ``p`` in ``AutPl``, and
// ``cocode_to_autpl(c)`` is a *diagonal automorphism*, as described
// in section *Automorphisms of the Parker loop* of the
// API reference.
// 
// Function ``op_ploop_autpl(v, m)`` applies Parker loop automorphism
// ``m`` to  element ``v`` of ``Pl`` and returns the result.
// 
// Function ``mul_autpl(m1, m2)`` computes the product ``m1 * m2`` of
// the Parker loop automorphisms ``m1`` and ``m2``. Function
// ``inv_autpl(m1)`` computes the inverse of the Parker loop
// automorphism ``m1``.
// 
// 
// Auxiliary functions
// ...................
// 
// Here is an overview of some auxiliary functions in this class.
// They are described in the corresponding function documentation:::
// 
//   bw24              bit weight of the lowest 24 bits of an integer
//   lsbit24           min(24, least significant bit pos.) for an integer
//   gcode_weight      weight of a Golay code word in 'gtype' representation
//   vect_to_bit_list  given a bit vector in V, it computes the lists of
//                     the positions of the 0 bits and of the 1 bits of v.
//   extract_b24       extract bits from bit vector using a 24-bit mask
//   spread_b24        spread bit vector according to a 24-bit mask
// 
// 
// Internal operation
// ..................
// 
// For switching from the standard representation to the internal
// representation we use three tables with ``2**8`` entries of ``24`` bit
// length. For switching back from internal to standard representation
// we use three other tables of the same format. There are also tables
// for computing the syndrome of a vector in ``V`` with respect to the
// Golay code. There is yet another table for the cocycle ``theta`` of
// the Parker loop.
// 
// 
// Abbreviations for functions and parameters in this class
// ........................................................
// 
// The following list of abbreviations used in names of functions
// allows to infer the action of most functions in this module::
// 
//     Abbreviation  Meaning                                   Data type
// 
//     assoc         associator (in Golay code or Parker loop)
//     autpl         automorphism of the Parker loop Pl        uint32_t[12]
//     bw24          bit weight of the lowest 24 bits of an int
//     cap           intersection (of Golay code elements)
//     cocode        element of Golay cocode C*                uint32_t
//     cocycle       cocycle:  Pl times Pl  ->  {0,1}
//     comm          commutator (in Golay code or Pl)
//     gcode         element of Golay code C                   uint32_t
//     inv           inversion (in Mat24, Pl, or AutPl)
//     lsbit24       least significant bit of an integer,
//                   counting bits 0,...,23 only
//     m24num        number of an element of Mat24             uint32_t
//     matrix        element of Mat24 as binary matrix
//                   acting on the Golay code C                uint32_t[12]
//     mul           multiplication (in Mat24, Pl, or AutPl)
//     net           Benes network for an element of Mat24     uint32_t[9]
//     octad         number of an octad, i.e. a Golay code
//                   element of weight 8                       uint32_t
//     op            op_<vector>_<operation> means:
//                   apply <operation> to <vector>
//     op_all        apply operation to all vectors
//     perm          element of Mat24 as a permutation         uint8_t[24]
//     ploop         element of the Parker loop Pl             uint32_t
//     pow           power operator (in Pl)
//     scalar_prod   scalar product (of Golay code and cocode)
//     suboctad      suboctad, see function suboctad_to_cocode
//     syndrome      syndrome (after decoding Golay code)      uint32_t
//     theta         cocycle theta: Pl -> C^* in Parker loop
//     to            <x>_to_<y> means: return representation <y>
//                   of an object given in representation <x>
//     vect          vector in V = GF(2)**24                   uint32_t
//     vintern       vector in V, in internal representation   uint32_t
// 
// 
// Conventions for parameters in C functions
// .........................................
// 
// Parameters of functions are either integers or arrays of integers.
// Here all integer types are unsigned and of fixed length, such as
// ``uint8_t``, ``uint16_t`` or ``uint32_t``.
// 
// The type of a parameter is given by a single letter in the name
// of the parameter::
// 
//     Name  Meaning                                           Type
//     a     array specified in documentation of function      unspecified
//     c     Golay cocode element, represented as 'cocode'     uint32_t
//     m     permutation in Mat24 or automorphism of Pl
//           represented as a bit matrix                       uint32_t[12]
//     p     permutation in Mat24 represented as 'perm'        uint8_t[24]
//     u_<x> unsigned integer, e.g.                            unspecified
//            u_exp:   integer denoting an exponent
//            u_m24:   number of a permutation in Mat24
//            u_octad: number of octad, 0 < u_octad < 259
//            u_width: integer denoting a bit width
//     v     vector in V, Golay code C or Parker loop Pl
//           represented as vect, vintern, gcode or ploop      uint32_t
// 
// Integer input parameters have name ``u_<x>``, e.g. ``u_m24, u_exp``.
// An integer computed by a function is returned as return value.
// Input array parameters have a digit as a suffix, e.g.: ``v1, v2, m1``.
// Output array parameters have the suffix ``_out``, e.g.: ``p_out``.
// Input/output array parameters  have the suffix ``_io``, e.g.: ``m_io``.
// 
// 
// Mapping C functions to python functions
// .......................................
// 
// 
// All C functions in module ``mat24_functions`` are documented.
// This documentation is not repeated for the corresponding python
// functions in module ``mmgroup.mat24``.
// 
// The rules for converting a C function to a python function are
// as follows:
// 
//  * To obtain the name of the python function, strip off the
//    prefix ``mat24_`` from the name of a C functions.
// 
//  * To obtain the tuple of input parameters for the python function,
//    take the tuple of parameters of the C function and drop are
//    parameters with suffix ``_out``.
// 
//    In the corresponding python function, an iterable object may
//    be passed where the C function expects a pointer to an integer.
//    The minimum length of that iterable object is either clear from
//    the context or documented in the C function.
// 
//  * To obtain the return value of the python function, check if
//    the C function has any parameters with suffix ``_out``. Then
//    the sequence of returned objects is the sequence of these
//    parameters, possibly preceded by the return value if the
//    C function returns an integer value.
// 
//    As usual in python, a sequence of length 1 is returned as a
//    single object, and a sequence of length >= 1 is returned as
//    a tuple.
// 
//    A parameter with suffix ``_out`` is returned as a list of
//    integers.
// 
//  * A C function may fail under certain circumstances.
// 
//    A failure of a function is indicated in the return value
//    of the function. Details are given in the documentation of
//    the function. The corresponding python function raises
//    ValueError if the C function fails.
// 
//  * The python function drops the return value of the C function
//    from the sequence of returned python objects in certain cases.
// 
//    If the documentation of the C function contains the phrase
//    'Returns 0 in case of success and (anything else) in case
//    of failure' then the return value is just a status
//    indicator and hence dropped by the python function.
// 
//    If the documentation of the C function contains a phrase
//    like 'Returns the length of the list ``xxx_out``' then the
//    python function adjusts the length of that returned list
//    appropriately and drops the return value.
// 
//  * Parameters with suffix ``_io`` refer to pointers in the C
//    function and hence to iterables in the corresponding
//    python function. Here the sufix ``_io`` means that
//    the function may modify that iterable object.


// %%PY_DOCSTR  Mat24_doc_basis
// We list the basis vectors of the Golay code and of its cocode.
// 
// Basis vectors have indices 0,...,11. Each basis vector is displayed
// as a hexadecimal number with bit i (of valence 2**i) corresponding
// to component i of the basis vector in GF(2)^24 for i = 0,...,23.
// Golay cocode vectors are to be understood modulo the Golay code.
// 
// Golay cocode basis
//     000110 001010 010010 100010 000a00 000c00
//     0000a0 0000c0 00000a 00000c 111111 000001
// Golay code basis
//     fff0f0 ff0ff0 f0fff0 0ffff0 cccc00 aaaa00
//     6ac0c0 c6a0a0 a6c00c 6ca00a 11111e ffffff


/*************************************************************************
** External references 
*************************************************************************/




#include <stdint.h>
// #include <stdio.h>
#include <string.h>
#include "mat24_functions.h"


// %%EXPORT_KWD MAT24_API







// %%GEN h
// %%GEN ch

/// @cond DO_NOT_DOCUMENT 

// %%GEN c

// %%EXPORT_TABLE p
MAT24_API
const uint8_t MAT24_LSBIT_TABLE[32] = { 
// %%TABLE Mat24_lsbit_table, uint8
0x18,0x00,0x18,0x01,0x18,0x0d,0x17,0x02,
0x18,0x15,0x13,0x0e,0x18,0x10,0x03,0x07,
0x18,0x18,0x0c,0x16,0x14,0x12,0x0f,0x06,
0x18,0x0b,0x11,0x05,0x0a,0x04,0x09,0x08
};

// %%GEN ch

/// @endcond  


// %%GEN h
// %%GEN ch
#ifdef __cplusplus
extern "C" {
#endif
// %%GEN c


/*************************************************************************
*** Some general bit operations
*************************************************************************/





/**
 @brief Return position of least significant bit of an integer.

 The function returns the minimum of the number 24 and the position of the
 least significant bit of `v1`. It uses a De Bruijn sequence.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_lsbit24(uint32_t v1)
{
    // This is a modification of
    // http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
    // which returns 24 if v1 & 0xffffff is zero.
    // return MAT24_LSBIT_TABLE[(((v1 & -v1) * 0x077CB531L) >> 26) & 0x1f];
    return MAT24_LSBIT_TABLE[(0x077cb531UL *  \
            ((v1) & (0-(v1))) >> 26) & 0x1f];
}



/**
 @brief Returns the bit weight of the lowest 24 bits of ``v1``.      
*/ 
// %%EXPORT p
MAT24_API
uint32_t mat24_bw24(uint32_t v1)
{
   v1 = (v1 & 0x555555) + ((v1 & 0xaaaaaa) >> 1); 
   v1 = (v1 & 0x333333) + ((v1 & 0xcccccc) >> 2);
   v1 = (v1 + (v1 >> 4)) & 0xf0f0f;
   return (v1 + (v1 >> 8) + (v1 >> 16)) & 0x1f; 
}    



/*************************************************************************
*** Conversion between bit vectors of GF(2)**24
*************************************************************************/

/**
 @brief Stores the positions of 1-bits of a bit vector to an array.
 
 Let ``w`` be the bit weight of the bit vector ``v1 & 0xffffff``, 
 i.e. number of bits of ``v1``  at positions ``< 24`` equal  to one. 
 Then the ordered bit positions where the corresponding bit of ``v1`` 
 is 1 are stored in ``a_out[0],...,a_out[w-1]``. 

 Then ``(v1 & 0xffffff)`` has ``24 - w`` zero bits. The 
 ordered  list of the positions of these zero bits is stored in 
``a_out[w],...,a_out[23]``. 
 
 The function returns the bit weight ``w``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_vect_to_bit_list(uint32_t v1, uint8_t *a_out)
{
    uint_fast32_t w, j, o;

    // put w = bit_weight(v1 & 0xffffff)
    w = (v1 & 0x555555) + ((v1 & 0xaaaaaa) >> 1);
    w = (w & 0x333333) + ((w & 0xcccccc) >> 2);
    w = (w + (w >> 4)) & 0xf0f0f;
    w = (w + (w >> 8) + (w >> 16)) & 0x1f; 
  
    // Separate bits:
    // i is the position and  o  is the value of the current bit of
    // the input vector v being processed (0 coded as 0, 1 coded as 8).
    // j & 0x1f is the position of the next index of the output vector 
    // where to write the position i in case o = 0.
    // (j >> 8) & 0x1f is the position of the next index of the output 
    // vector where to write the position i in case o != 0.
    v1 <<= 3;  // bit 0 of v1 is now at bit position 3
    j = w;    // start writing to pos. 0 if o = 0, to pos. w if o != 0
    // %%FOR i in range(24)
        o = (v1 >> 0) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 0;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 1) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 1;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 2) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 2;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 3) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 3;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 4) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 4;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 5) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 5;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 6) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 6;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 7) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 7;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 8) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 8;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 9) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 9;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 10) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 10;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 11) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 11;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 12) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 12;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 13) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 13;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 14) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 14;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 15) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 15;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 16) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 16;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 17) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 17;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 18) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 18;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 19) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 19;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 20) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 20;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 21) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 21;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 22) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 22;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
        o = (v1 >> 23) & 8;        // o = value of current bit of v1
        a_out[(j >> o) & 0x1f] = 23;  // write index i to the
                                     // appropriate output position
        j += 1 << o;                 // update both output positions
    // %%END FOR 
    return w;
}



/**
 @brief Stores the positions of 1-bits of a bit vector to an array.
 
 Let ``w`` be the minimum of the input ``u_len`` and the bit weight 
 of the bit vector ``v1 & 0xffffff``, i.e. number of bits of ``v1``
 at positions ``< 24`` equal  to one. 
 Then the first ``w`` bit positions where the corresponding bit 
 of ``v1`` is 1 are stored in ``a_out[0],...,a_out[w-1]`` in natural 
 order. The function returns ``w``.
 
 For small values ``w`` this function is faster than 
 function ``mat24_vect_to_bit_list``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_vect_to_list(uint32_t v1, uint32_t u_len, uint8_t *a_out)
{
    uint_fast32_t i, j;
   
    for (i = 0; i < u_len; ++i) {
        j = mat24_def_lsbit24(v1);
        if (j >= 24) return i;
        a_out[i] = (uint8_t)j;
        v1 ^= 1UL << j;
    }
    return u_len;
}



/**
 @brief Extract the bits of 24-bit vector ``v1`` given by the mask ``u_mask``
 
 If ``u_mask`` has bits equal to one at positions ``i_0, i_1, ..., i_k``
 (in ascending order) then the bit of ``v1`` at position ``i_j`` is copied 
 to the bit at position ``j`` of the return value for ``j = 0,...,k``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_extract_b24(uint32_t v1, uint32_t u_mask)
{
    uint_fast32_t res = 0, sh = 0;
    v1 &= u_mask;
    // %%FOR i in range(24)
        res |= ((v1 >> 0) & 1) << sh;
        sh += (u_mask >> 0) & 1;
        res |= ((v1 >> 1) & 1) << sh;
        sh += (u_mask >> 1) & 1;
        res |= ((v1 >> 2) & 1) << sh;
        sh += (u_mask >> 2) & 1;
        res |= ((v1 >> 3) & 1) << sh;
        sh += (u_mask >> 3) & 1;
        res |= ((v1 >> 4) & 1) << sh;
        sh += (u_mask >> 4) & 1;
        res |= ((v1 >> 5) & 1) << sh;
        sh += (u_mask >> 5) & 1;
        res |= ((v1 >> 6) & 1) << sh;
        sh += (u_mask >> 6) & 1;
        res |= ((v1 >> 7) & 1) << sh;
        sh += (u_mask >> 7) & 1;
        res |= ((v1 >> 8) & 1) << sh;
        sh += (u_mask >> 8) & 1;
        res |= ((v1 >> 9) & 1) << sh;
        sh += (u_mask >> 9) & 1;
        res |= ((v1 >> 10) & 1) << sh;
        sh += (u_mask >> 10) & 1;
        res |= ((v1 >> 11) & 1) << sh;
        sh += (u_mask >> 11) & 1;
        res |= ((v1 >> 12) & 1) << sh;
        sh += (u_mask >> 12) & 1;
        res |= ((v1 >> 13) & 1) << sh;
        sh += (u_mask >> 13) & 1;
        res |= ((v1 >> 14) & 1) << sh;
        sh += (u_mask >> 14) & 1;
        res |= ((v1 >> 15) & 1) << sh;
        sh += (u_mask >> 15) & 1;
        res |= ((v1 >> 16) & 1) << sh;
        sh += (u_mask >> 16) & 1;
        res |= ((v1 >> 17) & 1) << sh;
        sh += (u_mask >> 17) & 1;
        res |= ((v1 >> 18) & 1) << sh;
        sh += (u_mask >> 18) & 1;
        res |= ((v1 >> 19) & 1) << sh;
        sh += (u_mask >> 19) & 1;
        res |= ((v1 >> 20) & 1) << sh;
        sh += (u_mask >> 20) & 1;
        res |= ((v1 >> 21) & 1) << sh;
        sh += (u_mask >> 21) & 1;
        res |= ((v1 >> 22) & 1) << sh;
        sh += (u_mask >> 22) & 1;
        res |= ((v1 >> 23) & 1) << sh;
        sh += (u_mask >> 23) & 1;
    // %%END FOR 
    return res;
}

/**
 @brief Spread bits of 24-bit vector ``v1`` according to the mask ``u_mask``
 
 If ``u_mask`` has bits equal to one at positions ``i_0, i_1, ..., i_k``
 (in ascending order) then the bit of ``v1`` at position ``i`` is copied 
 to the bit at position ``i_j`` of the return value for ``j = 0,...,k``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_spread_b24(uint32_t v1, uint32_t u_mask)
{
    uint_fast32_t res = 0, sh = 0;
    // %%FOR i in range(24)
        res |= (((v1 >> sh) & 1) << 0) & u_mask;
        sh += (u_mask >> 0) & 1;
        res |= (((v1 >> sh) & 1) << 1) & u_mask;
        sh += (u_mask >> 1) & 1;
        res |= (((v1 >> sh) & 1) << 2) & u_mask;
        sh += (u_mask >> 2) & 1;
        res |= (((v1 >> sh) & 1) << 3) & u_mask;
        sh += (u_mask >> 3) & 1;
        res |= (((v1 >> sh) & 1) << 4) & u_mask;
        sh += (u_mask >> 4) & 1;
        res |= (((v1 >> sh) & 1) << 5) & u_mask;
        sh += (u_mask >> 5) & 1;
        res |= (((v1 >> sh) & 1) << 6) & u_mask;
        sh += (u_mask >> 6) & 1;
        res |= (((v1 >> sh) & 1) << 7) & u_mask;
        sh += (u_mask >> 7) & 1;
        res |= (((v1 >> sh) & 1) << 8) & u_mask;
        sh += (u_mask >> 8) & 1;
        res |= (((v1 >> sh) & 1) << 9) & u_mask;
        sh += (u_mask >> 9) & 1;
        res |= (((v1 >> sh) & 1) << 10) & u_mask;
        sh += (u_mask >> 10) & 1;
        res |= (((v1 >> sh) & 1) << 11) & u_mask;
        sh += (u_mask >> 11) & 1;
        res |= (((v1 >> sh) & 1) << 12) & u_mask;
        sh += (u_mask >> 12) & 1;
        res |= (((v1 >> sh) & 1) << 13) & u_mask;
        sh += (u_mask >> 13) & 1;
        res |= (((v1 >> sh) & 1) << 14) & u_mask;
        sh += (u_mask >> 14) & 1;
        res |= (((v1 >> sh) & 1) << 15) & u_mask;
        sh += (u_mask >> 15) & 1;
        res |= (((v1 >> sh) & 1) << 16) & u_mask;
        sh += (u_mask >> 16) & 1;
        res |= (((v1 >> sh) & 1) << 17) & u_mask;
        sh += (u_mask >> 17) & 1;
        res |= (((v1 >> sh) & 1) << 18) & u_mask;
        sh += (u_mask >> 18) & 1;
        res |= (((v1 >> sh) & 1) << 19) & u_mask;
        sh += (u_mask >> 19) & 1;
        res |= (((v1 >> sh) & 1) << 20) & u_mask;
        sh += (u_mask >> 20) & 1;
        res |= (((v1 >> sh) & 1) << 21) & u_mask;
        sh += (u_mask >> 21) & 1;
        res |= (((v1 >> sh) & 1) << 22) & u_mask;
        sh += (u_mask >> 22) & 1;
        res |= (((v1 >> sh) & 1) << 23) & u_mask;
        sh += (u_mask >> 23) & 1;
    // %%END FOR 
    return res;
}


/*************************************************************************
*** Conversion between representations of GF(2)**24, Golay code, etc.
*************************************************************************/


/// @cond DO_NOT_DOCUMENT 

// %%USE_TABLE
static const uint32_t MAT24_ENC_TABLE0[256] = {
// %%TABLE Mat24_enc_table0, uint32
0x00000000UL,0x00000800UL,0x00400e00UL,0x00400600UL,
0x00400d00UL,0x00400500UL,0x00000300UL,0x00000b00UL,
0x00400f00UL,0x00400700UL,0x00000100UL,0x00000900UL,
0x00000200UL,0x00000a00UL,0x00400c00UL,0x00400400UL,
0x00000c0fUL,0x0000040fUL,0x0040020fUL,0x00400a0fUL,
0x0040010fUL,0x0040090fUL,0x00000f0fUL,0x0000070fUL,
0x0040030fUL,0x00400b0fUL,0x00000d0fUL,0x0000050fUL,
0x00000e0fUL,0x0000060fUL,0x0040000fUL,0x0040080fUL,
0x00c0f88fUL,0x00c0f08fUL,0x0080f68fUL,0x0080fe8fUL,
0x0080f58fUL,0x0080fd8fUL,0x00c0fb8fUL,0x00c0f38fUL,
0x0080f78fUL,0x0080ff8fUL,0x00c0f98fUL,0x00c0f18fUL,
0x00c0fa8fUL,0x00c0f28fUL,0x0080f48fUL,0x0080fc8fUL,
0x00c0f480UL,0x00c0fc80UL,0x0080fa80UL,0x0080f280UL,
0x0080f980UL,0x0080f180UL,0x00c0f780UL,0x00c0ff80UL,
0x0080fb80UL,0x0080f380UL,0x00c0f580UL,0x00c0fd80UL,
0x00c0f680UL,0x00c0fe80UL,0x0080f880UL,0x0080f080UL,
0x00c0f84fUL,0x00c0f04fUL,0x0080f64fUL,0x0080fe4fUL,
0x0080f54fUL,0x0080fd4fUL,0x00c0fb4fUL,0x00c0f34fUL,
0x0080f74fUL,0x0080ff4fUL,0x00c0f94fUL,0x00c0f14fUL,
0x00c0fa4fUL,0x00c0f24fUL,0x0080f44fUL,0x0080fc4fUL,
0x00c0f440UL,0x00c0fc40UL,0x0080fa40UL,0x0080f240UL,
0x0080f940UL,0x0080f140UL,0x00c0f740UL,0x00c0ff40UL,
0x0080fb40UL,0x0080f340UL,0x00c0f540UL,0x00c0fd40UL,
0x00c0f640UL,0x00c0fe40UL,0x0080f840UL,0x0080f040UL,
0x000000c0UL,0x000008c0UL,0x00400ec0UL,0x004006c0UL,
0x00400dc0UL,0x004005c0UL,0x000003c0UL,0x00000bc0UL,
0x00400fc0UL,0x004007c0UL,0x000001c0UL,0x000009c0UL,
0x000002c0UL,0x00000ac0UL,0x00400cc0UL,0x004004c0UL,
0x00000ccfUL,0x000004cfUL,0x004002cfUL,0x00400acfUL,
0x004001cfUL,0x004009cfUL,0x00000fcfUL,0x000007cfUL,
0x004003cfUL,0x00400bcfUL,0x00000dcfUL,0x000005cfUL,
0x00000ecfUL,0x000006cfUL,0x004000cfUL,0x004008cfUL,
0x00c0f8cfUL,0x00c0f0cfUL,0x0080f6cfUL,0x0080fecfUL,
0x0080f5cfUL,0x0080fdcfUL,0x00c0fbcfUL,0x00c0f3cfUL,
0x0080f7cfUL,0x0080ffcfUL,0x00c0f9cfUL,0x00c0f1cfUL,
0x00c0facfUL,0x00c0f2cfUL,0x0080f4cfUL,0x0080fccfUL,
0x00c0f4c0UL,0x00c0fcc0UL,0x0080fac0UL,0x0080f2c0UL,
0x0080f9c0UL,0x0080f1c0UL,0x00c0f7c0UL,0x00c0ffc0UL,
0x0080fbc0UL,0x0080f3c0UL,0x00c0f5c0UL,0x00c0fdc0UL,
0x00c0f6c0UL,0x00c0fec0UL,0x0080f8c0UL,0x0080f0c0UL,
0x00000040UL,0x00000840UL,0x00400e40UL,0x00400640UL,
0x00400d40UL,0x00400540UL,0x00000340UL,0x00000b40UL,
0x00400f40UL,0x00400740UL,0x00000140UL,0x00000940UL,
0x00000240UL,0x00000a40UL,0x00400c40UL,0x00400440UL,
0x00000c4fUL,0x0000044fUL,0x0040024fUL,0x00400a4fUL,
0x0040014fUL,0x0040094fUL,0x00000f4fUL,0x0000074fUL,
0x0040034fUL,0x00400b4fUL,0x00000d4fUL,0x0000054fUL,
0x00000e4fUL,0x0000064fUL,0x0040004fUL,0x0040084fUL,
0x00000080UL,0x00000880UL,0x00400e80UL,0x00400680UL,
0x00400d80UL,0x00400580UL,0x00000380UL,0x00000b80UL,
0x00400f80UL,0x00400780UL,0x00000180UL,0x00000980UL,
0x00000280UL,0x00000a80UL,0x00400c80UL,0x00400480UL,
0x00000c8fUL,0x0000048fUL,0x0040028fUL,0x00400a8fUL,
0x0040018fUL,0x0040098fUL,0x00000f8fUL,0x0000078fUL,
0x0040038fUL,0x00400b8fUL,0x00000d8fUL,0x0000058fUL,
0x00000e8fUL,0x0000068fUL,0x0040008fUL,0x0040088fUL,
0x00c0f80fUL,0x00c0f00fUL,0x0080f60fUL,0x0080fe0fUL,
0x0080f50fUL,0x0080fd0fUL,0x00c0fb0fUL,0x00c0f30fUL,
0x0080f70fUL,0x0080ff0fUL,0x00c0f90fUL,0x00c0f10fUL,
0x00c0fa0fUL,0x00c0f20fUL,0x0080f40fUL,0x0080fc0fUL,
0x00c0f400UL,0x00c0fc00UL,0x0080fa00UL,0x0080f200UL,
0x0080f900UL,0x0080f100UL,0x00c0f700UL,0x00c0ff00UL,
0x0080fb00UL,0x0080f300UL,0x00c0f500UL,0x00c0fd00UL,
0x00c0f600UL,0x00c0fe00UL,0x0080f800UL,0x0080f000UL
};

// %%USE_TABLE
static const uint32_t MAT24_ENC_TABLE1[256] = {
// %%TABLE Mat24_enc_table1, uint32
0x00000000UL,0x00000c0eUL,0x00c0182eUL,0x00c01420UL,
0x00c0181eUL,0x00c01410UL,0x00000030UL,0x00000c3eUL,
0x00c0183eUL,0x00c01430UL,0x00000010UL,0x00000c1eUL,
0x00000020UL,0x00000c2eUL,0x00c0180eUL,0x00c01400UL,
0x00000c0dUL,0x00000003UL,0x00c01423UL,0x00c0182dUL,
0x00c01413UL,0x00c0181dUL,0x00000c3dUL,0x00000033UL,
0x00c01433UL,0x00c0183dUL,0x00000c1dUL,0x00000013UL,
0x00000c2dUL,0x00000023UL,0x00c01403UL,0x00c0180dUL,
0x00d52aadUL,0x00d526a3UL,0x00153283UL,0x00153e8dUL,
0x001532b3UL,0x00153ebdUL,0x00d52a9dUL,0x00d52693UL,
0x00153293UL,0x00153e9dUL,0x00d52abdUL,0x00d526b3UL,
0x00d52a8dUL,0x00d52683UL,0x001532a3UL,0x00153eadUL,
0x00d526a0UL,0x00d52aaeUL,0x00153e8eUL,0x00153280UL,
0x00153ebeUL,0x001532b0UL,0x00d52690UL,0x00d52a9eUL,
0x00153e9eUL,0x00153290UL,0x00d526b0UL,0x00d52abeUL,
0x00d52680UL,0x00d52a8eUL,0x00153eaeUL,0x001532a0UL,
0x00ea295dUL,0x00ea2553UL,0x002a3173UL,0x002a3d7dUL,
0x002a3143UL,0x002a3d4dUL,0x00ea296dUL,0x00ea2563UL,
0x002a3163UL,0x002a3d6dUL,0x00ea294dUL,0x00ea2543UL,
0x00ea297dUL,0x00ea2573UL,0x002a3153UL,0x002a3d5dUL,
0x00ea2550UL,0x00ea295eUL,0x002a3d7eUL,0x002a3170UL,
0x002a3d4eUL,0x002a3140UL,0x00ea2560UL,0x00ea296eUL,
0x002a3d6eUL,0x002a3160UL,0x00ea2540UL,0x00ea294eUL,
0x00ea2570UL,0x00ea297eUL,0x002a3d5eUL,0x002a3150UL,
0x003f03f0UL,0x003f0ffeUL,0x00ff1bdeUL,0x00ff17d0UL,
0x00ff1beeUL,0x00ff17e0UL,0x003f03c0UL,0x003f0fceUL,
0x00ff1bceUL,0x00ff17c0UL,0x003f03e0UL,0x003f0feeUL,
0x003f03d0UL,0x003f0fdeUL,0x00ff1bfeUL,0x00ff17f0UL,
0x003f0ffdUL,0x003f03f3UL,0x00ff17d3UL,0x00ff1bddUL,
0x00ff17e3UL,0x00ff1bedUL,0x003f0fcdUL,0x003f03c3UL,
0x00ff17c3UL,0x00ff1bcdUL,0x003f0fedUL,0x003f03e3UL,
0x003f0fddUL,0x003f03d3UL,0x00ff17f3UL,0x00ff1bfdUL,
0x00ff2bfdUL,0x00ff27f3UL,0x003f33d3UL,0x003f3fddUL,
0x003f33e3UL,0x003f3fedUL,0x00ff2bcdUL,0x00ff27c3UL,
0x003f33c3UL,0x003f3fcdUL,0x00ff2bedUL,0x00ff27e3UL,
0x00ff2bddUL,0x00ff27d3UL,0x003f33f3UL,0x003f3ffdUL,
0x00ff27f0UL,0x00ff2bfeUL,0x003f3fdeUL,0x003f33d0UL,
0x003f3feeUL,0x003f33e0UL,0x00ff27c0UL,0x00ff2bceUL,
0x003f3fceUL,0x003f33c0UL,0x00ff27e0UL,0x00ff2beeUL,
0x00ff27d0UL,0x00ff2bdeUL,0x003f3ffeUL,0x003f33f0UL,
0x002a0150UL,0x002a0d5eUL,0x00ea197eUL,0x00ea1570UL,
0x00ea194eUL,0x00ea1540UL,0x002a0160UL,0x002a0d6eUL,
0x00ea196eUL,0x00ea1560UL,0x002a0140UL,0x002a0d4eUL,
0x002a0170UL,0x002a0d7eUL,0x00ea195eUL,0x00ea1550UL,
0x002a0d5dUL,0x002a0153UL,0x00ea1573UL,0x00ea197dUL,
0x00ea1543UL,0x00ea194dUL,0x002a0d6dUL,0x002a0163UL,
0x00ea1563UL,0x00ea196dUL,0x002a0d4dUL,0x002a0143UL,
0x002a0d7dUL,0x002a0173UL,0x00ea1553UL,0x00ea195dUL,
0x001502a0UL,0x00150eaeUL,0x00d51a8eUL,0x00d51680UL,
0x00d51abeUL,0x00d516b0UL,0x00150290UL,0x00150e9eUL,
0x00d51a9eUL,0x00d51690UL,0x001502b0UL,0x00150ebeUL,
0x00150280UL,0x00150e8eUL,0x00d51aaeUL,0x00d516a0UL,
0x00150eadUL,0x001502a3UL,0x00d51683UL,0x00d51a8dUL,
0x00d516b3UL,0x00d51abdUL,0x00150e9dUL,0x00150293UL,
0x00d51693UL,0x00d51a9dUL,0x00150ebdUL,0x001502b3UL,
0x00150e8dUL,0x00150283UL,0x00d516a3UL,0x00d51aadUL,
0x00c0280dUL,0x00c02403UL,0x00003023UL,0x00003c2dUL,
0x00003013UL,0x00003c1dUL,0x00c0283dUL,0x00c02433UL,
0x00003033UL,0x00003c3dUL,0x00c0281dUL,0x00c02413UL,
0x00c0282dUL,0x00c02423UL,0x00003003UL,0x00003c0dUL,
0x00c02400UL,0x00c0280eUL,0x00003c2eUL,0x00003020UL,
0x00003c1eUL,0x00003010UL,0x00c02430UL,0x00c0283eUL,
0x00003c3eUL,0x00003030UL,0x00c02410UL,0x00c0281eUL,
0x00c02420UL,0x00c0282eUL,0x00003c0eUL,0x00003000UL
};

// %%USE_TABLE
static const uint32_t MAT24_ENC_TABLE2[256] = {
// %%TABLE Mat24_enc_table2, uint32
0x00000000UL,0x00000c0bUL,0x00ed49ebUL,0x00ed45e0UL,
0x00f64b9bUL,0x00f64790UL,0x001b0270UL,0x001b0e7bUL,
0x00db4a7bUL,0x00db4670UL,0x00360390UL,0x00360f9bUL,
0x002d01e0UL,0x002d0debUL,0x00c0480bUL,0x00c04400UL,
0x00000c07UL,0x0000000cUL,0x00ed45ecUL,0x00ed49e7UL,
0x00f6479cUL,0x00f64b97UL,0x001b0e77UL,0x001b027cUL,
0x00db467cUL,0x00db4a77UL,0x00360f97UL,0x0036039cUL,
0x002d0de7UL,0x002d01ecUL,0x00c0440cUL,0x00c04807UL,
0x00f98b67UL,0x00f9876cUL,0x0014c28cUL,0x0014ce87UL,
0x000fc0fcUL,0x000fccf7UL,0x00e28917UL,0x00e2851cUL,
0x0022c11cUL,0x0022cd17UL,0x00cf88f7UL,0x00cf84fcUL,
0x00d48a87UL,0x00d4868cUL,0x0039c36cUL,0x0039cf67UL,
0x00f98760UL,0x00f98b6bUL,0x0014ce8bUL,0x0014c280UL,
0x000fccfbUL,0x000fc0f0UL,0x00e28510UL,0x00e2891bUL,
0x0022cd1bUL,0x0022c110UL,0x00cf84f0UL,0x00cf88fbUL,
0x00d48680UL,0x00d48a8bUL,0x0039cf6bUL,0x0039c360UL,
0x00de8ad7UL,0x00de86dcUL,0x0033c33cUL,0x0033cf37UL,
0x0028c14cUL,0x0028cd47UL,0x00c588a7UL,0x00c584acUL,
0x0005c0acUL,0x0005cca7UL,0x00e88947UL,0x00e8854cUL,
0x00f38b37UL,0x00f3873cUL,0x001ec2dcUL,0x001eced7UL,
0x00de86d0UL,0x00de8adbUL,0x0033cf3bUL,0x0033c330UL,
0x0028cd4bUL,0x0028c140UL,0x00c584a0UL,0x00c588abUL,
0x0005ccabUL,0x0005c0a0UL,0x00e88540UL,0x00e8894bUL,
0x00f38730UL,0x00f38b3bUL,0x001ecedbUL,0x001ec2d0UL,
0x002701b0UL,0x00270dbbUL,0x00ca485bUL,0x00ca4450UL,
0x00d14a2bUL,0x00d14620UL,0x003c03c0UL,0x003c0fcbUL,
0x00fc4bcbUL,0x00fc47c0UL,0x00110220UL,0x00110e2bUL,
0x000a0050UL,0x000a0c5bUL,0x00e749bbUL,0x00e745b0UL,
0x00270db7UL,0x002701bcUL,0x00ca445cUL,0x00ca4857UL,
0x00d1462cUL,0x00d14a27UL,0x003c0fc7UL,0x003c03ccUL,
0x00fc47ccUL,0x00fc4bc7UL,0x00110e27UL,0x0011022cUL,
0x000a0c57UL,0x000a005cUL,0x00e745bcUL,0x00e749b7UL,
0x00e789b7UL,0x00e785bcUL,0x000ac05cUL,0x000acc57UL,
0x0011c22cUL,0x0011ce27UL,0x00fc8bc7UL,0x00fc87ccUL,
0x003cc3ccUL,0x003ccfc7UL,0x00d18a27UL,0x00d1862cUL,
0x00ca8857UL,0x00ca845cUL,0x0027c1bcUL,0x0027cdb7UL,
0x00e785b0UL,0x00e789bbUL,0x000acc5bUL,0x000ac050UL,
0x0011ce2bUL,0x0011c220UL,0x00fc87c0UL,0x00fc8bcbUL,
0x003ccfcbUL,0x003cc3c0UL,0x00d18620UL,0x00d18a2bUL,
0x00ca8450UL,0x00ca885bUL,0x0027cdbbUL,0x0027c1b0UL,
0x001e02d0UL,0x001e0edbUL,0x00f34b3bUL,0x00f34730UL,
0x00e8494bUL,0x00e84540UL,0x000500a0UL,0x00050cabUL,
0x00c548abUL,0x00c544a0UL,0x00280140UL,0x00280d4bUL,
0x00330330UL,0x00330f3bUL,0x00de4adbUL,0x00de46d0UL,
0x001e0ed7UL,0x001e02dcUL,0x00f3473cUL,0x00f34b37UL,
0x00e8454cUL,0x00e84947UL,0x00050ca7UL,0x000500acUL,
0x00c544acUL,0x00c548a7UL,0x00280d47UL,0x0028014cUL,
0x00330f37UL,0x0033033cUL,0x00de46dcUL,0x00de4ad7UL,
0x00390360UL,0x00390f6bUL,0x00d44a8bUL,0x00d44680UL,
0x00cf48fbUL,0x00cf44f0UL,0x00220110UL,0x00220d1bUL,
0x00e2491bUL,0x00e24510UL,0x000f00f0UL,0x000f0cfbUL,
0x00140280UL,0x00140e8bUL,0x00f94b6bUL,0x00f94760UL,
0x00390f67UL,0x0039036cUL,0x00d4468cUL,0x00d44a87UL,
0x00cf44fcUL,0x00cf48f7UL,0x00220d17UL,0x0022011cUL,
0x00e2451cUL,0x00e24917UL,0x000f0cf7UL,0x000f00fcUL,
0x00140e87UL,0x0014028cUL,0x00f9476cUL,0x00f94b67UL,
0x00c08807UL,0x00c0840cUL,0x002dc1ecUL,0x002dcde7UL,
0x0036c39cUL,0x0036cf97UL,0x00db8a77UL,0x00db867cUL,
0x001bc27cUL,0x001bce77UL,0x00f68b97UL,0x00f6879cUL,
0x00ed89e7UL,0x00ed85ecUL,0x0000c00cUL,0x0000cc07UL,
0x00c08400UL,0x00c0880bUL,0x002dcdebUL,0x002dc1e0UL,
0x0036cf9bUL,0x0036c390UL,0x00db8670UL,0x00db8a7bUL,
0x001bce7bUL,0x001bc270UL,0x00f68790UL,0x00f68b9bUL,
0x00ed85e0UL,0x00ed89ebUL,0x0000cc0bUL,0x0000c000UL
};

// %%EXPORT_TABLE p
MAT24_API
const uint32_t MAT24_DEC_TABLE0[256] = {
// %%TABLE Mat24_dec_table0, uint32
0x00000000UL,0x00000110UL,0x00001010UL,0x00001100UL,
0x00010010UL,0x00010100UL,0x00011000UL,0x00011110UL,
0x00100010UL,0x00100100UL,0x00101000UL,0x00101110UL,
0x00110000UL,0x00110110UL,0x00111010UL,0x00111100UL,
0x00000a00UL,0x00000b10UL,0x00001a10UL,0x00001b00UL,
0x00010a10UL,0x00010b00UL,0x00011a00UL,0x00011b10UL,
0x00100a10UL,0x00100b00UL,0x00101a00UL,0x00101b10UL,
0x00110a00UL,0x00110b10UL,0x00111a10UL,0x00111b00UL,
0x00000c00UL,0x00000d10UL,0x00001c10UL,0x00001d00UL,
0x00010c10UL,0x00010d00UL,0x00011c00UL,0x00011d10UL,
0x00100c10UL,0x00100d00UL,0x00101c00UL,0x00101d10UL,
0x00110c00UL,0x00110d10UL,0x00111c10UL,0x00111d00UL,
0x00000600UL,0x00000710UL,0x00001610UL,0x00001700UL,
0x00010610UL,0x00010700UL,0x00011600UL,0x00011710UL,
0x00100610UL,0x00100700UL,0x00101600UL,0x00101710UL,
0x00110600UL,0x00110710UL,0x00111610UL,0x00111700UL,
0x000000a0UL,0x000001b0UL,0x000010b0UL,0x000011a0UL,
0x000100b0UL,0x000101a0UL,0x000110a0UL,0x000111b0UL,
0x001000b0UL,0x001001a0UL,0x001010a0UL,0x001011b0UL,
0x001100a0UL,0x001101b0UL,0x001110b0UL,0x001111a0UL,
0x00000aa0UL,0x00000bb0UL,0x00001ab0UL,0x00001ba0UL,
0x00010ab0UL,0x00010ba0UL,0x00011aa0UL,0x00011bb0UL,
0x00100ab0UL,0x00100ba0UL,0x00101aa0UL,0x00101bb0UL,
0x00110aa0UL,0x00110bb0UL,0x00111ab0UL,0x00111ba0UL,
0x00000ca0UL,0x00000db0UL,0x00001cb0UL,0x00001da0UL,
0x00010cb0UL,0x00010da0UL,0x00011ca0UL,0x00011db0UL,
0x00100cb0UL,0x00100da0UL,0x00101ca0UL,0x00101db0UL,
0x00110ca0UL,0x00110db0UL,0x00111cb0UL,0x00111da0UL,
0x000006a0UL,0x000007b0UL,0x000016b0UL,0x000017a0UL,
0x000106b0UL,0x000107a0UL,0x000116a0UL,0x000117b0UL,
0x001006b0UL,0x001007a0UL,0x001016a0UL,0x001017b0UL,
0x001106a0UL,0x001107b0UL,0x001116b0UL,0x001117a0UL,
0x000000c0UL,0x000001d0UL,0x000010d0UL,0x000011c0UL,
0x000100d0UL,0x000101c0UL,0x000110c0UL,0x000111d0UL,
0x001000d0UL,0x001001c0UL,0x001010c0UL,0x001011d0UL,
0x001100c0UL,0x001101d0UL,0x001110d0UL,0x001111c0UL,
0x00000ac0UL,0x00000bd0UL,0x00001ad0UL,0x00001bc0UL,
0x00010ad0UL,0x00010bc0UL,0x00011ac0UL,0x00011bd0UL,
0x00100ad0UL,0x00100bc0UL,0x00101ac0UL,0x00101bd0UL,
0x00110ac0UL,0x00110bd0UL,0x00111ad0UL,0x00111bc0UL,
0x00000cc0UL,0x00000dd0UL,0x00001cd0UL,0x00001dc0UL,
0x00010cd0UL,0x00010dc0UL,0x00011cc0UL,0x00011dd0UL,
0x00100cd0UL,0x00100dc0UL,0x00101cc0UL,0x00101dd0UL,
0x00110cc0UL,0x00110dd0UL,0x00111cd0UL,0x00111dc0UL,
0x000006c0UL,0x000007d0UL,0x000016d0UL,0x000017c0UL,
0x000106d0UL,0x000107c0UL,0x000116c0UL,0x000117d0UL,
0x001006d0UL,0x001007c0UL,0x001016c0UL,0x001017d0UL,
0x001106c0UL,0x001107d0UL,0x001116d0UL,0x001117c0UL,
0x00000060UL,0x00000170UL,0x00001070UL,0x00001160UL,
0x00010070UL,0x00010160UL,0x00011060UL,0x00011170UL,
0x00100070UL,0x00100160UL,0x00101060UL,0x00101170UL,
0x00110060UL,0x00110170UL,0x00111070UL,0x00111160UL,
0x00000a60UL,0x00000b70UL,0x00001a70UL,0x00001b60UL,
0x00010a70UL,0x00010b60UL,0x00011a60UL,0x00011b70UL,
0x00100a70UL,0x00100b60UL,0x00101a60UL,0x00101b70UL,
0x00110a60UL,0x00110b70UL,0x00111a70UL,0x00111b60UL,
0x00000c60UL,0x00000d70UL,0x00001c70UL,0x00001d60UL,
0x00010c70UL,0x00010d60UL,0x00011c60UL,0x00011d70UL,
0x00100c70UL,0x00100d60UL,0x00101c60UL,0x00101d70UL,
0x00110c60UL,0x00110d70UL,0x00111c70UL,0x00111d60UL,
0x00000660UL,0x00000770UL,0x00001670UL,0x00001760UL,
0x00010670UL,0x00010760UL,0x00011660UL,0x00011770UL,
0x00100670UL,0x00100760UL,0x00101660UL,0x00101770UL,
0x00110660UL,0x00110770UL,0x00111670UL,0x00111760UL
};

// %%EXPORT_TABLE p
MAT24_API
const uint32_t MAT24_DEC_TABLE1[256] = {
// %%TABLE Mat24_dec_table1, uint32
0x00000000UL,0x0000000aUL,0x0000000cUL,0x00000006UL,
0x00111111UL,0x0011111bUL,0x0011111dUL,0x00111117UL,
0x00000001UL,0x0000000bUL,0x0000000dUL,0x00000007UL,
0x00111110UL,0x0011111aUL,0x0011111cUL,0x00111116UL,
0x00fff0f0UL,0x00fff0faUL,0x00fff0fcUL,0x00fff0f6UL,
0x00eee1e1UL,0x00eee1ebUL,0x00eee1edUL,0x00eee1e7UL,
0x00fff0f1UL,0x00fff0fbUL,0x00fff0fdUL,0x00fff0f7UL,
0x00eee1e0UL,0x00eee1eaUL,0x00eee1ecUL,0x00eee1e6UL,
0x00ff0ff0UL,0x00ff0ffaUL,0x00ff0ffcUL,0x00ff0ff6UL,
0x00ee1ee1UL,0x00ee1eebUL,0x00ee1eedUL,0x00ee1ee7UL,
0x00ff0ff1UL,0x00ff0ffbUL,0x00ff0ffdUL,0x00ff0ff7UL,
0x00ee1ee0UL,0x00ee1eeaUL,0x00ee1eecUL,0x00ee1ee6UL,
0x0000ff00UL,0x0000ff0aUL,0x0000ff0cUL,0x0000ff06UL,
0x0011ee11UL,0x0011ee1bUL,0x0011ee1dUL,0x0011ee17UL,
0x0000ff01UL,0x0000ff0bUL,0x0000ff0dUL,0x0000ff07UL,
0x0011ee10UL,0x0011ee1aUL,0x0011ee1cUL,0x0011ee16UL,
0x00f0fff0UL,0x00f0fffaUL,0x00f0fffcUL,0x00f0fff6UL,
0x00e1eee1UL,0x00e1eeebUL,0x00e1eeedUL,0x00e1eee7UL,
0x00f0fff1UL,0x00f0fffbUL,0x00f0fffdUL,0x00f0fff7UL,
0x00e1eee0UL,0x00e1eeeaUL,0x00e1eeecUL,0x00e1eee6UL,
0x000f0f00UL,0x000f0f0aUL,0x000f0f0cUL,0x000f0f06UL,
0x001e1e11UL,0x001e1e1bUL,0x001e1e1dUL,0x001e1e17UL,
0x000f0f01UL,0x000f0f0bUL,0x000f0f0dUL,0x000f0f07UL,
0x001e1e10UL,0x001e1e1aUL,0x001e1e1cUL,0x001e1e16UL,
0x000ff000UL,0x000ff00aUL,0x000ff00cUL,0x000ff006UL,
0x001ee111UL,0x001ee11bUL,0x001ee11dUL,0x001ee117UL,
0x000ff001UL,0x000ff00bUL,0x000ff00dUL,0x000ff007UL,
0x001ee110UL,0x001ee11aUL,0x001ee11cUL,0x001ee116UL,
0x00f000f0UL,0x00f000faUL,0x00f000fcUL,0x00f000f6UL,
0x00e111e1UL,0x00e111ebUL,0x00e111edUL,0x00e111e7UL,
0x00f000f1UL,0x00f000fbUL,0x00f000fdUL,0x00f000f7UL,
0x00e111e0UL,0x00e111eaUL,0x00e111ecUL,0x00e111e6UL,
0x000ffff0UL,0x000ffffaUL,0x000ffffcUL,0x000ffff6UL,
0x001eeee1UL,0x001eeeebUL,0x001eeeedUL,0x001eeee7UL,
0x000ffff1UL,0x000ffffbUL,0x000ffffdUL,0x000ffff7UL,
0x001eeee0UL,0x001eeeeaUL,0x001eeeecUL,0x001eeee6UL,
0x00f00f00UL,0x00f00f0aUL,0x00f00f0cUL,0x00f00f06UL,
0x00e11e11UL,0x00e11e1bUL,0x00e11e1dUL,0x00e11e17UL,
0x00f00f01UL,0x00f00f0bUL,0x00f00f0dUL,0x00f00f07UL,
0x00e11e10UL,0x00e11e1aUL,0x00e11e1cUL,0x00e11e16UL,
0x00f0f000UL,0x00f0f00aUL,0x00f0f00cUL,0x00f0f006UL,
0x00e1e111UL,0x00e1e11bUL,0x00e1e11dUL,0x00e1e117UL,
0x00f0f001UL,0x00f0f00bUL,0x00f0f00dUL,0x00f0f007UL,
0x00e1e110UL,0x00e1e11aUL,0x00e1e11cUL,0x00e1e116UL,
0x000f00f0UL,0x000f00faUL,0x000f00fcUL,0x000f00f6UL,
0x001e11e1UL,0x001e11ebUL,0x001e11edUL,0x001e11e7UL,
0x000f00f1UL,0x000f00fbUL,0x000f00fdUL,0x000f00f7UL,
0x001e11e0UL,0x001e11eaUL,0x001e11ecUL,0x001e11e6UL,
0x00ff0000UL,0x00ff000aUL,0x00ff000cUL,0x00ff0006UL,
0x00ee1111UL,0x00ee111bUL,0x00ee111dUL,0x00ee1117UL,
0x00ff0001UL,0x00ff000bUL,0x00ff000dUL,0x00ff0007UL,
0x00ee1110UL,0x00ee111aUL,0x00ee111cUL,0x00ee1116UL,
0x0000f0f0UL,0x0000f0faUL,0x0000f0fcUL,0x0000f0f6UL,
0x0011e1e1UL,0x0011e1ebUL,0x0011e1edUL,0x0011e1e7UL,
0x0000f0f1UL,0x0000f0fbUL,0x0000f0fdUL,0x0000f0f7UL,
0x0011e1e0UL,0x0011e1eaUL,0x0011e1ecUL,0x0011e1e6UL,
0x00000ff0UL,0x00000ffaUL,0x00000ffcUL,0x00000ff6UL,
0x00111ee1UL,0x00111eebUL,0x00111eedUL,0x00111ee7UL,
0x00000ff1UL,0x00000ffbUL,0x00000ffdUL,0x00000ff7UL,
0x00111ee0UL,0x00111eeaUL,0x00111eecUL,0x00111ee6UL,
0x00ffff00UL,0x00ffff0aUL,0x00ffff0cUL,0x00ffff06UL,
0x00eeee11UL,0x00eeee1bUL,0x00eeee1dUL,0x00eeee17UL,
0x00ffff01UL,0x00ffff0bUL,0x00ffff0dUL,0x00ffff07UL,
0x00eeee10UL,0x00eeee1aUL,0x00eeee1cUL,0x00eeee16UL
};

// %%EXPORT_TABLE p
MAT24_API
const uint32_t MAT24_DEC_TABLE2[256] = {
// %%TABLE Mat24_dec_table2, uint32
0x00000000UL,0x00cccc00UL,0x00aaaa00UL,0x00666600UL,
0x006ac0c0UL,0x00a60cc0UL,0x00c06ac0UL,0x000ca6c0UL,
0x00c6a0a0UL,0x000a6ca0UL,0x006c0aa0UL,0x00a0c6a0UL,
0x00ac6060UL,0x0060ac60UL,0x0006ca60UL,0x00ca0660UL,
0x00a6c00cUL,0x006a0c0cUL,0x000c6a0cUL,0x00c0a60cUL,
0x00cc00ccUL,0x0000ccccUL,0x0066aaccUL,0x00aa66ccUL,
0x006060acUL,0x00acacacUL,0x00cacaacUL,0x000606acUL,
0x000aa06cUL,0x00c66c6cUL,0x00a00a6cUL,0x006cc66cUL,
0x006ca00aUL,0x00a06c0aUL,0x00c60a0aUL,0x000ac60aUL,
0x000660caUL,0x00caaccaUL,0x00accacaUL,0x006006caUL,
0x00aa00aaUL,0x0066ccaaUL,0x0000aaaaUL,0x00cc66aaUL,
0x00c0c06aUL,0x000c0c6aUL,0x006a6a6aUL,0x00a6a66aUL,
0x00ca6006UL,0x0006ac06UL,0x0060ca06UL,0x00ac0606UL,
0x00a0a0c6UL,0x006c6cc6UL,0x000a0ac6UL,0x00c6c6c6UL,
0x000cc0a6UL,0x00c00ca6UL,0x00a66aa6UL,0x006aa6a6UL,
0x00660066UL,0x00aacc66UL,0x00ccaa66UL,0x00006666UL,
0x0011111eUL,0x00dddd1eUL,0x00bbbb1eUL,0x0077771eUL,
0x007bd1deUL,0x00b71ddeUL,0x00d17bdeUL,0x001db7deUL,
0x00d7b1beUL,0x001b7dbeUL,0x007d1bbeUL,0x00b1d7beUL,
0x00bd717eUL,0x0071bd7eUL,0x0017db7eUL,0x00db177eUL,
0x00b7d112UL,0x007b1d12UL,0x001d7b12UL,0x00d1b712UL,
0x00dd11d2UL,0x0011ddd2UL,0x0077bbd2UL,0x00bb77d2UL,
0x007171b2UL,0x00bdbdb2UL,0x00dbdbb2UL,0x001717b2UL,
0x001bb172UL,0x00d77d72UL,0x00b11b72UL,0x007dd772UL,
0x007db114UL,0x00b17d14UL,0x00d71b14UL,0x001bd714UL,
0x001771d4UL,0x00dbbdd4UL,0x00bddbd4UL,0x007117d4UL,
0x00bb11b4UL,0x0077ddb4UL,0x0011bbb4UL,0x00dd77b4UL,
0x00d1d174UL,0x001d1d74UL,0x007b7b74UL,0x00b7b774UL,
0x00db7118UL,0x0017bd18UL,0x0071db18UL,0x00bd1718UL,
0x00b1b1d8UL,0x007d7dd8UL,0x001b1bd8UL,0x00d7d7d8UL,
0x001dd1b8UL,0x00d11db8UL,0x00b77bb8UL,0x007bb7b8UL,
0x00771178UL,0x00bbdd78UL,0x00ddbb78UL,0x00117778UL,
0x00ffffffUL,0x003333ffUL,0x005555ffUL,0x009999ffUL,
0x00953f3fUL,0x0059f33fUL,0x003f953fUL,0x00f3593fUL,
0x00395f5fUL,0x00f5935fUL,0x0093f55fUL,0x005f395fUL,
0x00539f9fUL,0x009f539fUL,0x00f9359fUL,0x0035f99fUL,
0x00593ff3UL,0x0095f3f3UL,0x00f395f3UL,0x003f59f3UL,
0x0033ff33UL,0x00ff3333UL,0x00995533UL,0x00559933UL,
0x009f9f53UL,0x00535353UL,0x00353553UL,0x00f9f953UL,
0x00f55f93UL,0x00399393UL,0x005ff593UL,0x00933993UL,
0x00935ff5UL,0x005f93f5UL,0x0039f5f5UL,0x00f539f5UL,
0x00f99f35UL,0x00355335UL,0x00533535UL,0x009ff935UL,
0x0055ff55UL,0x00993355UL,0x00ff5555UL,0x00339955UL,
0x003f3f95UL,0x00f3f395UL,0x00959595UL,0x00595995UL,
0x00359ff9UL,0x00f953f9UL,0x009f35f9UL,0x0053f9f9UL,
0x005f5f39UL,0x00939339UL,0x00f5f539UL,0x00393939UL,
0x00f33f59UL,0x003ff359UL,0x00599559UL,0x00955959UL,
0x0099ff99UL,0x00553399UL,0x00335599UL,0x00ff9999UL,
0x00eeeee1UL,0x002222e1UL,0x004444e1UL,0x008888e1UL,
0x00842e21UL,0x0048e221UL,0x002e8421UL,0x00e24821UL,
0x00284e41UL,0x00e48241UL,0x0082e441UL,0x004e2841UL,
0x00428e81UL,0x008e4281UL,0x00e82481UL,0x0024e881UL,
0x00482eedUL,0x0084e2edUL,0x00e284edUL,0x002e48edUL,
0x0022ee2dUL,0x00ee222dUL,0x0088442dUL,0x0044882dUL,
0x008e8e4dUL,0x0042424dUL,0x0024244dUL,0x00e8e84dUL,
0x00e44e8dUL,0x0028828dUL,0x004ee48dUL,0x0082288dUL,
0x00824eebUL,0x004e82ebUL,0x0028e4ebUL,0x00e428ebUL,
0x00e88e2bUL,0x0024422bUL,0x0042242bUL,0x008ee82bUL,
0x0044ee4bUL,0x0088224bUL,0x00ee444bUL,0x0022884bUL,
0x002e2e8bUL,0x00e2e28bUL,0x0084848bUL,0x0048488bUL,
0x00248ee7UL,0x00e842e7UL,0x008e24e7UL,0x0042e8e7UL,
0x004e4e27UL,0x00828227UL,0x00e4e427UL,0x00282827UL,
0x00e22e47UL,0x002ee247UL,0x00488447UL,0x00844847UL,
0x0088ee87UL,0x00442287UL,0x00224487UL,0x00ee8887UL
};



// The following table MAT24_BASIS contains the used basis of the 
// Golay cocode (12 bit vectors of type uint32_t) followed by the 
// used basis of the Golay code (12 bit vectors).

// %%EXPORT_TABLE p
MAT24_API
const uint32_t MAT24_BASIS[24] = { 
// %%TABLE Mat24_basis, uint32
0x00000110UL,0x00001010UL,0x00010010UL,0x00100010UL,
0x00000a00UL,0x00000c00UL,0x000000a0UL,0x000000c0UL,
0x0000000aUL,0x0000000cUL,0x00111111UL,0x00000001UL,
0x00fff0f0UL,0x00ff0ff0UL,0x00f0fff0UL,0x000ffff0UL,
0x00cccc00UL,0x00aaaa00UL,0x006ac0c0UL,0x00c6a0a0UL,
0x00a6c00cUL,0x006ca00aUL,0x0011111eUL,0x00ffffffUL
};

// %%EXPORT_TABLE p
MAT24_API
const uint32_t MAT24_RECIP_BASIS[24+8] = { 
// %%TABLE Mat24_recip_basis, uint32
0x00000800UL,0x00400e00UL,0x00400d00UL,0x00400f00UL,
0x00000c0fUL,0x00c0f88fUL,0x00c0f84fUL,0x00c0f8cfUL,
0x00000c0eUL,0x00c0182eUL,0x00c0181eUL,0x00c0183eUL,
0x00000c0dUL,0x00d52aadUL,0x00ea295dUL,0x00ff2bfdUL,
0x00000c0bUL,0x00ed49ebUL,0x00f64b9bUL,0x00db4a7bUL,
0x00000c07UL,0x00f98b67UL,0x00de8ad7UL,0x00e789b7UL,
0x00000000UL,0x00000000UL,0x00000000UL,0x00000000UL,
0x00000000UL,0x00000000UL,0x00000000UL,0x00000000UL
};

// %%EXPORT_TABLE p
MAT24_API
const uint16_t MAT24_SYNDROME_TABLE[0x800] = { 
// %%TABLE Mat24_syndrome_table, uint16
0x6300,0xa080,0xb080,0xb100,0xc080,0xc100,0xc180,0x5ed5,
0xd080,0xd100,0xd180,0x4e51,0xd200,0x3dcd,0x2d49,0x1cc5,
0xad20,0x5a4e,0x520a,0x5e26,0x518a,0x55e5,0x5144,0x5148,
0x418a,0x4da7,0x4144,0x4148,0x3144,0x3148,0xe30a,0x2904,
0xad40,0x562d,0x5209,0x5a65,0x5189,0x5dc7,0x5124,0x5128,
0x4189,0x49e6,0x4124,0x4128,0x3124,0x3128,0xe309,0x2504,
0xa920,0x5e6f,0x520b,0x5647,0x518b,0x59a6,0x5164,0x5168,
0x418b,0x45c5,0x4164,0x4168,0x3164,0x3168,0xe30b,0x2d04,
0x9ca0,0x566e,0x5e2a,0x5206,0x59ab,0x5186,0x5106,0x50c4,
0x49e9,0x4186,0x4106,0x40c4,0x3106,0x30c4,0x20c4,0xe306,
0x3982,0xa8c0,0x3882,0x3902,0x59a9,0x55e7,0x41c2,0x5e72,
0x49eb,0x4da5,0x51c2,0x5ab1,0xde20,0x3861,0x28e5,0x2d26,
0x5683,0xa4c0,0x5e2b,0x5a67,0x59aa,0x5dc5,0xc9e0,0x5441,
0x5483,0x5503,0x5583,0x49cd,0x5603,0x4e2f,0x24e5,0x2d46,
0x4e01,0xacc0,0x5e29,0x5645,0x4c81,0x4d01,0x4d81,0x59ee,
0x49ea,0x45c7,0xd9a0,0x4c62,0x5261,0x5ead,0x2ce5,0x2926,
0x9cc0,0x5e4d,0x5a69,0x5205,0x55ea,0x5185,0x5105,0x50a4,
0x45cb,0x4185,0x4105,0x40a4,0x3105,0x30a4,0x20a4,0xe305,
0x4a03,0xa8a0,0x5a6b,0x5e27,0x4883,0x4903,0x4983,0x55cd,
0x45c9,0x4da6,0xd5e0,0x4841,0x5243,0x5ecf,0x28e6,0x2d25,
0x3581,0xa4a0,0x3481,0x3501,0x55eb,0x5dc6,0x41a1,0x5a51,
0x45ca,0x49e7,0x51a1,0x5eb3,0xda60,0x3462,0x24e6,0x2d45,
0x5e82,0xaca0,0x5a6a,0x5646,0x55e9,0x59a7,0xc5c0,0x5c61,
0x5c82,0x5d02,0x5d82,0x45ed,0x5e02,0x4e4e,0x2ce6,0x2925,
0x98a0,0x5a2f,0x564b,0x5207,0x5dc9,0x5187,0x5107,0x50e4,
0x4daa,0x4187,0x4107,0x40e4,0x3107,0x30e4,0x20e4,0xe307,
0x5a81,0xa8e0,0x5649,0x5e25,0x5dcb,0x55e6,0xcda0,0x5862,
0x5881,0x5901,0x5981,0x4dee,0x5a01,0x4a2d,0x28c5,0x2d27,
0x4602,0xa4e0,0x564a,0x5a66,0x4482,0x4502,0x4582,0x5ded,
0x4dab,0x49e5,0xddc0,0x4461,0x5222,0x5aae,0x24c5,0x2d47,
0x3d83,0xace0,0x3c83,0x3d03,0x5dca,0x59a5,0x41e3,0x5671,
0x4da9,0x45c6,0x51e3,0x5ed2,0xd640,0x3c41,0x2cc5,0x2927,
0x8c20,0x5e2e,0x566a,0x5a46,0x59e9,0x55a7,0x5d65,0xd040,
0x49ab,0x4de5,0x4527,0xc040,0x3946,0xb040,0xa040,0x9040,
0x2902,0x2882,0xb8c0,0x3142,0x59eb,0x4142,0x5d25,0x5651,
0x49a9,0x5142,0x4567,0x5ed3,0xd660,0x38e5,0x2861,0x3da6,
0x2502,0x2482,0x566b,0x3122,0xc4e0,0x4122,0x5d45,0x59cd,
0x49aa,0x5122,0xd9e0,0x44c5,0x3966,0x5eaf,0x2461,0x4e47,
0x2d02,0x2c82,0x5669,0x3162,0x59ea,0x4162,0xc9a0,0x5ce6,
0xdca0,0x5162,0x4547,0x49ee,0x3926,0x4e2d,0x2c61,0x5aa5,
0x1882,0x20c2,0x30c2,0xb940,0x40c2,0x55a5,0x5d67,0x5a71,
0x50c2,0x4de7,0x4525,0x5eb2,0xda40,0x3969,0x3daa,0x1861,
0xbda0,0x520e,0x5a4a,0x5666,0x51c8,0x51c4,0x5d27,0x51cc,
0x41c8,0x41c4,0x4565,0x41cc,0x3904,0xe30e,0x3988,0x3984,
0x5681,0x5e6d,0x5a49,0xb960,0xc4a0,0x59e6,0x5d47,0x5462,
0x5481,0x5501,0x5581,0x44e6,0x5601,0x3949,0x3dab,0x4e45,
0x4e03,0x562f,0x5a4b,0xb920,0x4c83,0x4d03,0x4d83,0x5cc5,
0xdce0,0x49a6,0x4545,0x4c41,0x5263,0x396a,0x3da9,0x5aa7,
0x1482,0x20a2,0x30a2,0x5a47,0x40a2,0x55a6,0xcde0,0x5d49,
0x50a2,0xdd60,0x4526,0x4dcd,0x3947,0x4a2f,0x5aab,0x1461,
0x4a01,0x5a2d,0xb8e0,0x5665,0x4881,0x4901,0x4981,0x5d6a,
0x4dea,0xdd20,0x4566,0x4862,0x5241,0x38c5,0x5aa9,0x3da7,
0x3583,0x564e,0x3483,0x3503,0xc4c0,0x59e5,0x41a3,0x5d69,
0x4de9,0xdd40,0x51a3,0x44e5,0x3967,0x3441,0x5aaa,0x4e46,
0xdaa0,0x5e0c,0x5e08,0x5e04,0x5d88,0x5d84,0x5d04,0xe317,
0x4deb,0x49a5,0x4546,0x5e90,0x3927,0x5e8c,0x5e88,0x5e84,
0x1c82,0x20e2,0x30e2,0x5a45,0x40e2,0xc520,0x5d66,0x55ee,
0x50e2,0x4de6,0xd5a0,0x456a,0x3945,0x5ecd,0x4e49,0x1c61,
0x5a83,0x5e4f,0xb8a0,0x5667,0x55aa,0xc560,0x5d26,0x5841,
0x5883,0x5903,0x5983,0x4549,0x5a03,0x38e6,0x4e4b,0x3da5,
0xce40,0x522c,0x5228,0x5224,0x55a9,0x59e7,0x5d46,0x5230,
0x4588,0x4584,0x4504,0xe311,0x3965,0x460c,0x4608,0x4604,
0x3d81,0x5a6e,0x3c81,0x3d01,0x55ab,0xc540,0x41e1,0x5ce5,
0xdcc0,0x49a7,0x51e1,0x4569,0x3925,0x3c62,0x4e4a,0x5aa6,
0x8c40,0x5a6d,0x5e49,0x5625,0x55cb,0x5de6,0x5947,0xd020,
0x45ea,0x49c7,0x4d66,0xc020,0x3525,0xb020,0xa020,0x9020,
0x2901,0x2881,0x5e4b,0x3141,0x55c9,0x4141,0xc5e0,0x58c5,
0xd8e0,0x5141,0x4d26,0x45cd,0x3565,0x4e4f,0x2862,0x5ea7,
0x2501,0x2481,0xb4a0,0x3121,0x55ca,0x4121,0x5967,0x5e71,
0x45eb,0x5121,0x4d46,0x5ab2,0xde40,0x34e6,0x2462,0x3dc5,
0x2d01,0x2c81,0x5e4a,0x3161,0xccc0,0x4161,0x5927,0x55ed,
0x45e9,0x5161,0xd5c0,0x4ce5,0x3545,0x5ece,0x2c62,0x4a26,
0x1881,0x20c1,0x30c1,0x5627,0x40c1,0xcd60,0x5945,0x5dcd,
0x50c1,0x49c5,0xdde0,0x4d49,0x3527,0x5aaf,0x4a2b,0x1862,
0x3983,0x564d,0x3883,0x3903,0x5dea,0xcd20,0x41c3,0x58e6,
0xd8a0,0x45e6,0x51c3,0x4d6a,0x3567,0x3841,0x4a29,0x5ea5,
0x5682,0x5a2e,0xb4e0,0x5e46,0x5de9,0xcd40,0x5965,0x5461,
0x5482,0x5502,0x5582,0x4d69,0x5602,0x34c5,0x4a2a,0x3dc7,
0xca20,0x526c,0x5268,0x5264,0x5deb,0x55c6,0x5925,0x5270,
0x4d88,0x4d84,0x4d04,0xe313,0x3547,0x4e0c,0x4e08,0x4e04,
0x1481,0x20a1,0x30a1,0xb520,0x40a1,0x5de7,0x5946,0x5672,
0x50a1,0x49c6,0x4d67,0x5ed1,0xd620,0x356a,0x3dc9,0x1462,
0x4a02,0x5e6e,0x562a,0xb560,0x4882,0x4902,0x4982,0x58e5,
0xd8c0,0x45e5,0x4d27,0x4861,0x5242,0x3549,0x3dcb,0x5ea6,
0xbdc0,0x520d,0x5629,0x5e45,0x51a8,0x51a4,0x5966,0x51ac,
0x41a8,0x41a4,0x4d47,0x41ac,0x3504,0xe30d,0x3588,0x3584,
0x5e83,0x5a4f,0x562b,0xb540,0xcce0,0x55c5,0x5926,0x5c41,
0x5c83,0x5d03,0x5d83,0x4cc5,0x5e03,0x3569,0x3dca,0x4a27,
0x1c81,0x20e1,0x30e1,0x5626,0x40e1,0x5de5,0xc9c0,0x5969,
0x50e1,0xd940,0x4d65,0x49ed,0x3526,0x4e2e,0x5eaa,0x1c62,
0xdea0,0x5a0c,0x5a08,0x5a04,0x5988,0x5984,0x5904,0xe316,
0x49ca,0x45e7,0x4d25,0x5a90,0x3566,0x5a8c,0x5a88,0x5a84,
0x4603,0x566f,0xb4c0,0x5e47,0x4483,0x4503,0x4583,0x5949,
0x49c9,0xd960,0x4d45,0x4441,0x5223,0x34e5,0x5eab,0x3dc6,
0x3d82,0x5e2d,0x3c82,0x3d02,0xcca0,0x55c7,0x41e2,0x596a,
0x49cb,0xd920,0x51e2,0x4ce6,0x3546,0x3c61,0x5ea9,0x4a25,
0x8820,0x564f,0x5a2b,0x5e67,0x5daa,0x59c5,0x5526,0xd060,
0x4dc9,0x45a6,0x4945,0xc060,0x3d67,0xb060,0xa060,0x9060,
0x2903,0x2883,0x5a29,0x3143,0xc8a0,0x4143,0x5566,0x5dee,
0x4dcb,0x5143,0xdda0,0x48e6,0x3d27,0x5aad,0x2841,0x4e25,
0x2503,0x2483,0x5a2a,0x3123,0x5dab,0x4123,0xcdc0,0x54e5,
0xd4c0,0x5123,0x4965,0x4ded,0x3d47,0x4a2e,0x2441,0x5ec6,
0x2d03,0x2c83,0xbce0,0x3163,0x5da9,0x4163,0x5546,0x5a72,
0x4dca,0x5163,0x4925,0x5eb1,0xda20,0x3cc5,0x2c41,0x39a7,
0x1883,0x20c3,0x30c3,0x5e65,0x40c3,0x59c7,0xc5a0,0x556a,
0x50c3,0xd520,0x4947,0x45ee,0x3d65,0x4e4d,0x5ec9,0x1841,
0x3981,0x5a6f,0x3881,0x3901,0xc8e0,0x5da6,0x41c1,0x5549,
0x45aa,0xd560,0x51c1,0x48c5,0x3d25,0x3862,0x5ecb,0x4e27,
0xdec0,0x560c,0x5608,0x5604,0x5588,0x5584,0x5504,0xe315,
0x45a9,0x4dc6,0x4967,0x5690,0x3d45,0x568c,0x5688,0x5684,
0x4e02,0x5e4e,0xbca0,0x5a26,0x4c82,0x4d02,0x4d82,0x5569,
0x45ab,0xd540,0x4927,0x4c61,0x5262,0x3ce6,0x5eca,0x39a5,
0x1483,0x20a3,0x30a3,0x5e66,0x40a3,0xc940,0x5527,0x59ed,
0x50a3,0x45a7,0xd9c0,0x4969,0x3d66,0x5eae,0x4e2a,0x1441,
0xce20,0x524c,0x5248,0x5244,0x59ca,0x5da5,0x5567,0x5250,
0x4988,0x4984,0x4904,0xe312,0x3d26,0x4a0c,0x4a08,0x4a04,
0x3582,0x5e2f,0x3482,0x3502,0x59c9,0xc960,0x41a2,0x54c5,
0xd4e0,0x4dc5,0x51a2,0x4949,0x3d46,0x3461,0x4e2b,0x5ec7,
0x5e81,0x566d,0xbcc0,0x5a25,0x59cb,0xc920,0x5547,0x5c62,
0x5c81,0x5d01,0x5d81,0x496a,0x5e01,0x3ce5,0x4e29,0x39a6,
0x1c83,0x20e3,0x30e3,0xbd60,0x40e3,0x59c6,0x5525,0x5e51,
0x50e3,0x45a5,0x4946,0x5ab3,0xde60,0x3d49,0x39ab,0x1c41,
0x5a82,0x562e,0x5e6a,0xbd20,0xc8c0,0x5da7,0x5565,0x5861,
0x5882,0x5902,0x5982,0x48e5,0x5a02,0x3d6a,0x39a9,0x4e26,
0x4601,0x5a4d,0x5e69,0xbd40,0x4481,0x4501,0x4581,0x54e6,
0xd4a0,0x4dc7,0x4966,0x4462,0x5221,0x3d69,0x39aa,0x5ec5,
0xb9a0,0x520f,0x5e6b,0x5a27,0x51e8,0x51e4,0x5545,0x51ec,
0x41e8,0x41e4,0x4926,0x41ec,0x3d04,0xe30f,0x3d88,0x3d84,
0x0c41,0x520c,0x5208,0x5204,0x5188,0x5184,0x5104,0xe314,
0x4188,0x4184,0x4104,0xe310,0x3104,0xe30c,0xe308,0xe304,
0xa900,0xa880,0x38c2,0xb140,0x48a3,0xc140,0x45e1,0x5169,
0x58e1,0xd140,0x5da3,0x4169,0x5662,0x3169,0x2d28,0x2d24,
0xa500,0xa480,0x34a1,0xb120,0x44e2,0xc120,0x4dc3,0x516a,
0x54c3,0xd120,0x59e2,0x416a,0x5e41,0x316a,0x2d48,0x2d44,
0xad00,0xac80,0x3ce3,0xb160,0x4cc1,0xc160,0x49a2,0x5149,
0x5ca2,0xd160,0x55c1,0x4149,0x5a23,0x3149,0x2928,0x2924,
0x9880,0xa0c0,0xb0c0,0x3942,0xc0c0,0x4d61,0x45a3,0x50e5,
0xd0c0,0x5523,0x5de1,0x40e5,0x5a42,0x30e5,0x20e5,0x1ca4,
0x3da2,0x5e2c,0x5e28,0x5e24,0x48e3,0x4d21,0x5146,0x5e30,
0x58a1,0x5563,0x4146,0x5e91,0x3146,0xb840,0x28c4,0x2906,
0x5ec3,0x524f,0x34e1,0x3962,0x44a2,0x4d41,0x5126,0xd460,
0x49e8,0x49e4,0x4126,0x49ec,0x3126,0x4a0f,0x24c4,0x2506,
0x4a21,0x5a0d,0x3ca3,0x3922,0x59a8,0x59a4,0x5166,0x59ac,
0x5ce2,0x5543,0x4166,0xcc20,0x3166,0x5a8d,0x2cc4,0x2d06,
0x9480,0xa0a0,0xb0a0,0x3521,0xc0a0,0x4943,0x4de2,0x50e6,
0xd0a0,0x5d62,0x59c3,0x40e6,0x5621,0x30e6,0x20e6,0x1cc4,
0x4e23,0x560f,0x38e2,0x3561,0x55e8,0x55e4,0x5145,0x55ec,
0x58c1,0x5d22,0x4145,0xc860,0x3145,0x568f,0x28a4,0x2905,
0x3dc1,0x5a6c,0x5a68,0x5a64,0x44c2,0x4963,0x5125,0x5a70,
0x54e3,0x5d42,0x4125,0x5a93,0x3125,0xb420,0x24a4,0x2505,
0x5aa2,0x522e,0x3cc3,0x3541,0x4ce1,0x4923,0x5165,0xdc40,
0x45c8,0x45c4,0x4165,0x45cc,0x3165,0x460e,0x2ca4,0x2d05,
0x9c80,0xa0e0,0xb0e0,0x3d63,0xc0e0,0x4522,0x49c1,0x50c5,
0xd0e0,0x5941,0x55a2,0x40c5,0x5e63,0x30c5,0x20c5,0x18a4,
0x5ea1,0x526d,0x38a2,0x3d23,0x48c3,0x4562,0x5147,0xd820,
0x4da8,0x4da4,0x4147,0x4dac,0x3147,0x4e0d,0x28e4,0x2907,
0x4e42,0x5e0e,0x34c1,0x3d43,0x5dc8,0x5dc4,0x5127,0x5dcc,
0x54a3,0x5961,0x4127,0xc440,0x3127,0x5e8e,0x24e4,0x2507,
0x39a3,0x564c,0x5648,0x5644,0x4ca1,0x4542,0x5167,0x5650,
0x5cc2,0x5921,0x4167,0x5692,0x3167,0xbc60,0x2ce4,0x2d07,
0xe302,0x2082,0x3082,0x3102,0x4082,0x4102,0x4182,0x5061,
0x5082,0x5102,0x5182,0x4061,0x5202,0x3061,0x2061,0x1061,
0x2d22,0x566c,0x5668,0x5664,0x48a1,0x51c6,0x45e3,0x5670,
0x58e3,0x41c6,0x5da1,0x5693,0x3906,0x38c4,0xa840,0x3986,
0x2d42,0x5a0f,0x34a3,0x5227,0x59e8,0x59e4,0x4dc1,0x59ec,
0x54c1,0x4587,0x4507,0x44e4,0x5e43,0x5a8f,0xa440,0x4607,
0x2922,0x524d,0x3ce1,0x5e05,0x4cc3,0x5d85,0x5d05,0x5ca4,
0x49a8,0x49a4,0x55c3,0x49ac,0x5a21,0x4a0d,0xac40,0x5e85,
0x1ca2,0x5a4c,0x5a48,0x5a44,0x51ca,0x4d63,0x45a1,0x5a50,
0x41ca,0x5521,0x5de3,0x5a92,0x3944,0x3948,0x398a,0x9840,
0xb980,0x28c2,0xb880,0xb900,0x48e1,0x4d23,0xc1c0,0x51ed,
0x58a3,0x5561,0xd1c0,0x41ed,0x5e22,0x3dac,0x3da8,0x3da4,
0x5ec1,0x24c2,0x34e3,0x5225,0x51cb,0x4d43,0x49e2,0xd420,
0x41cb,0x4585,0x4505,0x44a4,0x3964,0x3968,0x398b,0x4605,
0x4a23,0x2cc2,0x3ca1,0x5e07,0x51c9,0x5d87,0x5d07,0x5ce4,
0x41c9,0x5541,0x59a2,0xcc60,0x3924,0x3928,0x3989,0x5e87,
0x1cc2,0x526f,0x5e0b,0x3523,0x5d8b,0x4941,0x5d64,0x5d68,
0x4de8,0x4de4,0x59c1,0x4dec,0x5623,0x4e0f,0x5e8b,0x9440,
0x4e21,0x28a2,0x5e09,0x3563,0x5d89,0x51c7,0x5d24,0x5d28,
0x58c3,0x41c7,0x55e2,0xc820,0x3907,0x38e4,0x5e89,0x3987,
0x3dc3,0x24a2,0x5e0a,0x5226,0x5d8a,0x4961,0x5d44,0x5d48,
0x54e1,0x4586,0x4506,0x44c4,0x5a62,0xb460,0x5e8a,0x4606,
0xde80,0x2ca2,0x3cc1,0x3543,0x4ce3,0x4921,0x45c2,0x5ab4,
0xdc80,0xdd00,0xdd80,0x5ab0,0xde00,0x5aac,0x5aa8,0x5aa4,
0x18a2,0x560d,0x5229,0x3d61,0x55a8,0x55a4,0x49c3,0x55ac,
0x4589,0x5943,0x4524,0x4528,0x5e61,0x568d,0x4609,0x9c40,
0x5ea3,0x28e2,0x522b,0x3d21,0x48c1,0x51c5,0x4da2,0xd860,
0x458b,0x41c5,0x4564,0x4568,0x3905,0x38a4,0x460b,0x3985,
0xc600,0x24e2,0x34c3,0x3d41,0xc480,0xc500,0xc580,0x5272,
0x54a1,0x5963,0x5dc2,0x4e50,0xd220,0x4e4c,0x4e48,0x4e44,
0x39a1,0x2ce2,0x522a,0x5e06,0x4ca3,0x5d86,0x5d06,0x5cc4,
0x458a,0x5923,0x4544,0x4548,0x5642,0xbc20,0x460a,0x5e86,
0xe301,0x2081,0x3081,0x3101,0x4081,0x4101,0x4181,0x5062,
0x5081,0x5101,0x5181,0x4062,0x5201,0x3062,0x2062,0x1062,
0x2d21,0x522f,0x38c3,0x5a07,0x48a2,0x5987,0x5907,0x58e4,
0x45e8,0x45e4,0x5da2,0x45ec,0x5663,0x460f,0xa820,0x5a87,
0x2d41,0x5e4c,0x5e48,0x5e44,0x44e3,0x51a5,0x4dc2,0x5e50,
0x54c2,0x41a5,0x59e3,0x5e92,0x3505,0x34a4,0xa420,0x3585,
0x2921,0x560e,0x3ce2,0x5266,0x55c8,0x55c4,0x49a3,0x55cc,
0x5ca3,0x4d86,0x4d06,0x4cc4,0x5a22,0x568e,0xac20,0x4e06,
0x1ca1,0x5e0f,0x526b,0x3943,0x5de8,0x5de4,0x45a2,0x5dec,
0x4d8b,0x5522,0x4d64,0x4d68,0x5a43,0x5e8f,0x4e0b,0x9820,
0x3da3,0x28c1,0x5269,0x5a05,0x48e2,0x5985,0x5905,0x58a4,
0x4d89,0x5562,0x4d24,0x4d28,0x5e21,0xb860,0x4e09,0x5a85,
0x5ec2,0x24c1,0x526a,0x3963,0x44a3,0x51a7,0x49e1,0xd440,
0x4d8a,0x41a7,0x4d44,0x4d48,0x3507,0x34e4,0x4e0a,0x3587,
0xce00,0x2cc1,0x3ca2,0x3923,0xcc80,0xcd00,0xcd80,0x5251,
0x5ce3,0x5542,0x59a1,0x4a30,0xd260,0x4a2c,0x4a28,0x4a24,
0x1cc1,0x562c,0x5628,0x5624,0x51a9,0x4942,0x4de3,0x5630,
0x41a9,0x5d63,0x59c2,0x5691,0x3524,0x3528,0x3589,0x9420,
0x4e22,0x28a1,0x38e3,0x5a06,0x51ab,0x5986,0x5906,0x58c4,
0x41ab,0x5d23,0x55e1,0xc840,0x3564,0x3568,0x358b,0x5a86,
0xb580,0x24a1,0xb480,0xb500,0x44c3,0x4962,0xc1a0,0x51ee,
0x54e2,0x5d43,0xd1a0,0x41ee,0x5a61,0x3dcc,0x3dc8,0x3dc4,
0x5aa3,0x2ca1,0x3cc2,0x5267,0x51aa,0x4922,0x45c1,0xdc60,
0x41aa,0x4d87,0x4d07,0x4ce4,0x3544,0x3548,0x358a,0x4e07,
0x18a1,0x524e,0x5a0a,0x3d62,0x598a,0x4523,0x5944,0x5948,
0x49c8,0x49c4,0x55a3,0x49cc,0x5e62,0x4a0e,0x5a8a,0x9c20,
0xda80,0x28e1,0x38a3,0x3d22,0x48c2,0x4563,0x4da1,0x5eb4,
0xd880,0xd900,0xd980,0x5eb0,0xda00,0x5eac,0x5ea8,0x5ea4,
0x4e43,0x24e1,0x5a0b,0x3d42,0x598b,0x51a6,0x5964,0x5968,
0x54a2,0x41a6,0x5dc1,0xc460,0x3506,0x34c4,0x5a8b,0x3586,
0x39a2,0x2ce1,0x5a09,0x5265,0x5989,0x4543,0x5924,0x5928,
0x5cc3,0x4d85,0x4d05,0x4ca4,0x5641,0xbc40,0x5a89,0x4e05,
0xe303,0x2083,0x3083,0x3103,0x4083,0x4103,0x4183,0x5041,
0x5083,0x5103,0x5183,0x4041,0x5203,0x3041,0x2041,0x1041,
0x2d23,0x5e0d,0x38c1,0x5245,0x5da8,0x5da4,0x45e2,0x5dac,
0x58e2,0x4985,0x4905,0x48a4,0x5661,0x5e8d,0xa860,0x4a05,
0x2d43,0x526e,0x34a2,0x5606,0x44e1,0x5586,0x5506,0x54c4,
0x4dc8,0x4dc4,0x59e1,0x4dcc,0x5e42,0x4e0e,0xa460,0x5686,
0x2923,0x5a2c,0x5a28,0x5a24,0x4cc2,0x51e7,0x49a1,0x5a30,
0x5ca1,0x41e7,0x55c2,0x5a91,0x3d07,0x3ce4,0xac60,0x3d87,
0x1ca3,0x522d,0x5609,0x3941,0x5589,0x4d62,0x5524,0x5528,
0x45a8,0x45a4,0x5de2,0x45ac,0x5a41,0x460d,0x5689,0x9860,
0x3da1,0x28c3,0x560b,0x5247,0x558b,0x4d22,0x5564,0x5568,
0x58a2,0x4987,0x4907,0x48e4,0x5e23,0xb820,0x568b,0x4a07,
0xd680,0x24c3,0x34e2,0x3961,0x44a1,0x4d42,0x49e3,0x5ed4,
0xd480,0xd500,0xd580,0x5ed0,0xd600,0x5ecc,0x5ec8,0x5ec4,
0x4a22,0x2cc3,0x560a,0x3921,0x558a,0x51e5,0x5544,0x5548,
0x5ce1,0x41e5,0x59a3,0xcc40,0x3d05,0x3ca4,0x568a,0x3d85,
0x1cc3,0x5a0e,0x524a,0x3522,0x59c8,0x59c4,0x4de1,0x59cc,
0x498a,0x5d61,0x4944,0x4948,0x5622,0x5a8e,0x4a0a,0x9460,
0xca00,0x28a3,0x38e1,0x3562,0xc880,0xc900,0xc980,0x5271,
0x58c2,0x5d21,0x55e3,0x4e30,0xd240,0x4e2c,0x4e28,0x4e24,
0x3dc2,0x24a3,0x524b,0x5607,0x44c1,0x5587,0x5507,0x54e4,
0x498b,0x5d41,0x4964,0x4968,0x5a63,0xb440,0x4a0b,0x5687,
0x5aa1,0x2ca3,0x5249,0x3542,0x4ce2,0x51e6,0x45c3,0xdc20,
0x4989,0x41e6,0x4924,0x4928,0x3d06,0x3cc4,0x4a09,0x3d86,
0x18a3,0x5e6c,0x5e68,0x5e64,0x51eb,0x4521,0x49c2,0x5e70,
0x41eb,0x5942,0x55a1,0x5e93,0x3d64,0x3d68,0x3d8b,0x9c60,
0x5ea2,0x28e3,0x38a1,0x5246,0x51e9,0x4561,0x4da3,0xd840,
0x41e9,0x4986,0x4906,0x48c4,0x3d24,0x3d28,0x3d89,0x4a06,
0x4e41,0x24e3,0x34c2,0x5605,0x51ea,0x5585,0x5505,0x54a4,
0x41ea,0x5962,0x5dc3,0xc420,0x3d44,0x3d48,0x3d8a,0x5685,
0xbd80,0x2ce3,0xbc80,0xbd00,0x4ca2,0x4541,0xc1e0,0x51cd,
0x5cc1,0x5922,0xd1e0,0x41cd,0x5643,0x39ac,0x39a8,0x39a4
};

/// @endcond 




/**
  @brief Table for converting ``octad`` to ``gcode`` representation

  The public macro ``mat24_def_octad_to_gcode`` uses this table
*/
// %%EXPORT_TABLE p
MAT24_API
const uint16_t MAT24_OCT_DEC_TABLE[759] = { 
// %%TABLE Mat24_oct_dec_table, uint16
0x0801,0x0802,0x0003,0x0804,0x0005,0x0006,0x0007,0x0808,
0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x080f,0x0010,
0x0013,0x0015,0x0016,0x0019,0x001a,0x001c,0x001f,0x0020,
0x0023,0x0025,0x0026,0x0029,0x002a,0x002c,0x002f,0x0030,
0x0033,0x0035,0x0036,0x0039,0x003a,0x003c,0x003f,0x0040,
0x0041,0x0046,0x0047,0x004a,0x004b,0x004c,0x004d,0x0050,
0x0052,0x0055,0x0057,0x0059,0x005b,0x005c,0x005e,0x0060,
0x0063,0x0064,0x0067,0x0069,0x006a,0x006d,0x006e,0x0070,
0x0073,0x0075,0x0076,0x0078,0x007b,0x007d,0x007e,0x0080,
0x0081,0x0086,0x0087,0x008a,0x008b,0x008c,0x008d,0x0090,
0x0093,0x0095,0x0096,0x0098,0x009b,0x009d,0x009e,0x00a0,
0x00a2,0x00a5,0x00a7,0x00a9,0x00ab,0x00ac,0x00ae,0x00b0,
0x00b3,0x00b4,0x00b7,0x00b9,0x00ba,0x00bd,0x00be,0x00c0,
0x00c1,0x00c6,0x00c7,0x00ca,0x00cb,0x00cc,0x00cd,0x00d0,
0x00d3,0x00d4,0x00d7,0x00d9,0x00da,0x00dd,0x00de,0x00e0,
0x00e3,0x00e5,0x00e6,0x00e8,0x00eb,0x00ed,0x00ee,0x00f0,
0x00f2,0x00f5,0x00f7,0x00f9,0x00fb,0x00fc,0x00fe,0x0100,
0x0902,0x0904,0x0106,0x0908,0x010a,0x010c,0x090e,0x0110,
0x0911,0x0914,0x0115,0x0918,0x0119,0x011c,0x091d,0x0120,
0x0921,0x0922,0x0123,0x0924,0x0125,0x0126,0x0927,0x0130,
0x0931,0x0932,0x0133,0x0938,0x0139,0x013a,0x093b,0x0140,
0x0943,0x0944,0x0147,0x0948,0x014b,0x014c,0x094f,0x0150,
0x0951,0x0952,0x0153,0x095c,0x015d,0x015e,0x095f,0x0180,
0x0982,0x0985,0x0187,0x0988,0x018a,0x018d,0x098f,0x01b0,
0x09b1,0x09b4,0x01b5,0x09ba,0x01bb,0x01be,0x09bf,0x01c0,
0x09c2,0x09c4,0x01c6,0x09c9,0x01cb,0x01cd,0x09cf,0x01e0,
0x09e1,0x09e6,0x01e7,0x09e8,0x01e9,0x01ee,0x09ef,0x0200,
0x0a02,0x0a04,0x0206,0x0a08,0x020a,0x020c,0x0a0e,0x0210,
0x0a11,0x0a12,0x0213,0x0a18,0x0219,0x021a,0x0a1b,0x0220,
0x0a21,0x0a24,0x0225,0x0a28,0x0229,0x022c,0x0a2d,0x0230,
0x0a31,0x0a32,0x0233,0x0a34,0x0235,0x0236,0x0a37,0x0240,
0x0a42,0x0a44,0x0246,0x0a49,0x024b,0x024d,0x0a4f,0x0270,
0x0a71,0x0a76,0x0277,0x0a78,0x0279,0x027e,0x0a7f,0x0280,
0x0a83,0x0a84,0x0287,0x0a88,0x028b,0x028c,0x0a8f,0x02a0,
0x0aa1,0x0aa2,0x02a3,0x0aac,0x02ad,0x02ae,0x0aaf,0x02c0,
0x0ac2,0x0ac5,0x02c7,0x0ac8,0x02ca,0x02cd,0x0acf,0x02d0,
0x0ad1,0x0ad4,0x02d5,0x0ada,0x02db,0x02de,0x0adf,0x0300,
0x0b02,0x0b04,0x0306,0x0b08,0x030a,0x030c,0x0b0e,0x0310,
0x0b11,0x0b12,0x0313,0x0b14,0x0315,0x0316,0x0b17,0x0320,
0x0b21,0x0b22,0x0323,0x0b28,0x0329,0x032a,0x0b2b,0x0330,
0x0b31,0x0b34,0x0335,0x0b38,0x0339,0x033c,0x0b3d,0x0340,
0x0b42,0x0b45,0x0347,0x0b48,0x034a,0x034d,0x0b4f,0x0360,
0x0b61,0x0b64,0x0365,0x0b6a,0x036b,0x036e,0x0b6f,0x0380,
0x0b82,0x0b84,0x0386,0x0b89,0x038b,0x038d,0x0b8f,0x0390,
0x0b91,0x0b96,0x0397,0x0b98,0x0399,0x039e,0x0b9f,0x03c0,
0x0bc3,0x0bc4,0x03c7,0x0bc8,0x03cb,0x03cc,0x0bcf,0x03f0,
0x0bf1,0x0bf2,0x03f3,0x0bfc,0x03fd,0x03fe,0x0bff,0x0400,
0x0c01,0x0c02,0x0c04,0x0c08,0x0c0f,0x0c10,0x0c17,0x0c1b,
0x0c1d,0x0c1e,0x041f,0x0c20,0x0c27,0x0c2b,0x0c2d,0x0c2e,
0x042f,0x0c30,0x0c37,0x0c3b,0x0c3d,0x0c3e,0x043f,0x0c40,
0x0441,0x0c43,0x0c45,0x0c49,0x0c4e,0x0c50,0x0452,0x0c53,
0x0c56,0x0c5a,0x0c5d,0x0c60,0x0464,0x0c65,0x0c66,0x0c6b,
0x0c6c,0x0c70,0x0c77,0x0478,0x0c79,0x0c7a,0x0c7c,0x0c80,
0x0481,0x0c83,0x0c85,0x0c89,0x0c8e,0x0c90,0x0c97,0x0498,
0x0c99,0x0c9a,0x0c9c,0x0ca0,0x04a2,0x0ca3,0x0ca6,0x0caa,
0x0cad,0x0cb0,0x04b4,0x0cb5,0x0cb6,0x0cbb,0x0cbc,0x0cc0,
0x04c1,0x0cc3,0x0cc5,0x0cc9,0x0cce,0x0cd0,0x04d4,0x0cd5,
0x0cd6,0x0cdb,0x0cdc,0x0ce0,0x0ce7,0x04e8,0x0ce9,0x0cea,
0x0cec,0x0cf0,0x04f2,0x0cf3,0x0cf6,0x0cfa,0x0cfd,0x0501,
0x0506,0x050a,0x050c,0x0d0e,0x050f,0x0512,0x0515,0x0519,
0x051c,0x0d1d,0x051f,0x0523,0x0525,0x0526,0x0d27,0x0528,
0x052f,0x0533,0x0534,0x0539,0x053a,0x0d3b,0x053f,0x0541,
0x0542,0x0d43,0x0547,0x054b,0x054c,0x0553,0x0554,0x0558,
0x0d5c,0x055d,0x055e,0x0d60,0x0561,0x0562,0x0564,0x0568,
0x056f,0x0d70,0x0571,0x0572,0x0574,0x0578,0x057f,0x0581,
0x0584,0x0d85,0x0587,0x058a,0x058d,0x0d90,0x0591,0x0592,
0x0594,0x0598,0x059f,0x0da0,0x05a1,0x05a2,0x05a4,0x05a8,
0x05af,0x05b2,0x05b5,0x05b8,0x0dba,0x05bb,0x05be,0x05c1,
0x05c6,0x05c8,0x0dc9,0x05cb,0x05cd,0x0dd0,0x05d1,0x05d2,
0x05d4,0x05d8,0x05df,0x05e2,0x05e4,0x0de6,0x05e7,0x05e9,
0x05ee,0x0df0,0x05f1,0x05f2,0x05f4,0x05f8,0x05ff,0x0601,
0x0606,0x060a,0x060c,0x0e0e,0x060f,0x0613,0x0614,0x0619,
0x061a,0x0e1b,0x061f,0x0622,0x0625,0x0629,0x062c,0x0e2d,
0x062f,0x0633,0x0635,0x0636,0x0e37,0x0638,0x063f,0x0641,
0x0646,0x0648,0x0e49,0x064b,0x064d,0x0e50,0x0651,0x0652,
0x0654,0x0658,0x065f,0x0e60,0x0661,0x0662,0x0664,0x0668,
0x066f,0x0672,0x0674,0x0e76,0x0677,0x0679,0x067e,0x0681,
0x0682,0x0e83,0x0687,0x068b,0x068c,0x0e90,0x0691,0x0692,
0x0694,0x0698,0x069f,0x06a3,0x06a4,0x06a8,0x0eac,0x06ad,
0x06ae,0x0eb0,0x06b1,0x06b2,0x06b4,0x06b8,0x06bf,0x06c1,
0x06c4,0x0ec5,0x06c7,0x06ca,0x06cd,0x06d2,0x06d5,0x06d8,
0x0eda,0x06db,0x06de,0x0ee0,0x06e1,0x06e2,0x06e4,0x06e8,
0x06ef,0x0ef0,0x06f1,0x06f2,0x06f4,0x06f8,0x06ff,0x0701,
0x0706,0x070a,0x070c,0x0f0e,0x070f,0x0713,0x0715,0x0716,
0x0f17,0x0718,0x071f,0x0723,0x0724,0x0729,0x072a,0x0f2b,
0x072f,0x0732,0x0735,0x0739,0x073c,0x0f3d,0x073f,0x0741,
0x0744,0x0f45,0x0747,0x074a,0x074d,0x0f50,0x0751,0x0752,
0x0754,0x0758,0x075f,0x0762,0x0765,0x0768,0x0f6a,0x076b,
0x076e,0x0f70,0x0771,0x0772,0x0774,0x0778,0x077f,0x0781,
0x0786,0x0788,0x0f89,0x078b,0x078d,0x0792,0x0794,0x0f96,
0x0797,0x0799,0x079e,0x0fa0,0x07a1,0x07a2,0x07a4,0x07a8,
0x07af,0x0fb0,0x07b1,0x07b2,0x07b4,0x07b8,0x07bf,0x07c1,
0x07c2,0x0fc3,0x07c7,0x07cb,0x07cc,0x0fd0,0x07d1,0x07d2,
0x07d4,0x07d8,0x07df,0x0fe0,0x07e1,0x07e2,0x07e4,0x07e8,
0x07ef,0x07f3,0x07f4,0x07f8,0x0ffc,0x07fd,0x07fe
};

/**
 @brief Table for converting ``gcode`` to ``octad`` representation

 The public macro ``mat24_def_gcode_to_octad`` uses this table
*/
// %%EXPORT_TABLE p
MAT24_API
const uint8_t MAT24_OCT_ENC_TABLE[2048] = { 
// %%TABLE Mat24_oct_enc_table, uint8
0xff,0x17,0x19,0x1a,0x1d,0x1e,0x20,0x22,
0x1f,0x20,0x22,0x24,0x26,0x28,0x2a,0x2d,
0x28,0xff,0xff,0x2a,0xff,0x2c,0x2e,0xff,
0xff,0x2a,0x2c,0xff,0x2e,0xff,0xff,0x30,
0x2c,0xff,0xff,0x2e,0xff,0x30,0x32,0xff,
0xff,0x2e,0x30,0xff,0x32,0xff,0xff,0x34,
0x30,0xff,0xff,0x32,0xff,0x34,0x36,0xff,
0xff,0x32,0x34,0xff,0x36,0xff,0xff,0x38,
0x34,0x36,0xff,0xff,0xff,0xff,0x38,0x3a,
0xff,0xff,0x36,0x38,0x3a,0x3c,0xff,0xff,
0x38,0xff,0x3a,0xff,0xff,0x3c,0xff,0x3e,
0xff,0x3a,0xff,0x3c,0x3e,0xff,0x40,0xff,
0x3c,0xff,0xff,0x3e,0x40,0xff,0xff,0x42,
0xff,0x3e,0x40,0xff,0xff,0x42,0x44,0xff,
0x40,0xff,0xff,0x42,0xff,0x44,0x46,0xff,
0x42,0xff,0xff,0x44,0xff,0x46,0x48,0xff,
0x44,0x46,0xff,0xff,0xff,0xff,0x48,0x4a,
0xff,0xff,0x46,0x48,0x4a,0x4c,0xff,0xff,
0x48,0xff,0xff,0x4a,0xff,0x4c,0x4e,0xff,
0x4a,0xff,0xff,0x4c,0xff,0x4e,0x50,0xff,
0x4c,0xff,0x4e,0xff,0xff,0x50,0xff,0x52,
0xff,0x4e,0xff,0x50,0x52,0xff,0x54,0xff,
0x50,0xff,0xff,0x52,0x54,0xff,0xff,0x56,
0xff,0x52,0x54,0xff,0xff,0x56,0x58,0xff,
0x54,0x56,0xff,0xff,0xff,0xff,0x58,0x5a,
0xff,0xff,0x56,0x58,0x5a,0x5c,0xff,0xff,
0x58,0xff,0xff,0x5a,0x5c,0xff,0xff,0x5e,
0xff,0x5a,0x5c,0xff,0xff,0x5e,0x60,0xff,
0x5c,0xff,0xff,0x5e,0xff,0x60,0x62,0xff,
0x5e,0xff,0xff,0x60,0xff,0x62,0x64,0xff,
0x60,0xff,0x62,0xff,0xff,0x64,0xff,0x66,
0xff,0x62,0xff,0x64,0x66,0xff,0x68,0xff,
0x64,0xff,0x67,0xff,0x69,0xff,0x6a,0xff,
0x67,0xff,0x68,0xff,0x6a,0xff,0x6d,0xff,
0x68,0x6b,0xff,0xff,0x6d,0x6e,0xff,0xff,
0x6b,0x6c,0xff,0xff,0x6e,0x71,0xff,0xff,
0x6c,0x6f,0x71,0x72,0x75,0x76,0x78,0x7b,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x70,0x73,0x75,0x76,0xff,0xff,0xff,0xff,
0x73,0x74,0x76,0x79,0xff,0xff,0xff,0xff,
0x74,0xff,0xff,0x77,0x79,0xff,0xff,0x7a,
0x77,0xff,0xff,0x78,0x7a,0xff,0xff,0x7d,
0x78,0x7b,0x7d,0x7e,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x7b,0x7c,0x7e,0x81,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x64,0xff,0x67,0xff,0xff,0x69,0xff,0x6a,
0x67,0xff,0x68,0xff,0xff,0x6a,0xff,0x6d,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x50,0x53,0xff,0xff,0x55,0x56,0xff,0xff,
0xff,0xff,0x53,0x54,0xff,0xff,0x56,0x59,
0x54,0xff,0x57,0xff,0x59,0xff,0x5a,0xff,
0xff,0x57,0xff,0x58,0xff,0x5a,0xff,0x5d,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x4c,0x4f,0xff,0xff,0xff,0xff,0x51,0x52,
0x4f,0x50,0xff,0xff,0xff,0xff,0x52,0x55,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x44,0xff,0x47,0xff,0x49,0xff,0x4a,0xff,
0x47,0xff,0x48,0xff,0x4a,0xff,0x4d,0xff,
0x48,0x4b,0x4d,0x4e,0xff,0xff,0xff,0xff,
0x4b,0x4c,0x4e,0x51,0xff,0xff,0xff,0xff,
0x4c,0x4f,0xff,0xff,0x51,0x52,0xff,0xff,
0x4f,0x50,0xff,0xff,0x52,0x55,0xff,0xff,
0x50,0x53,0x55,0x56,0x59,0x5a,0x5c,0x5f,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x54,0xff,0x57,0xff,0x59,0xff,0x5a,0xff,
0xff,0x57,0xff,0x58,0xff,0x5a,0xff,0x5d,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x40,0x43,0xff,0xff,0xff,0xff,0x45,0x46,
0x43,0x44,0xff,0xff,0xff,0xff,0x46,0x49,
0x44,0xff,0xff,0x47,0x49,0xff,0xff,0x4a,
0x47,0xff,0xff,0x48,0x4a,0xff,0xff,0x4d,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x3c,0x3f,0x41,0x42,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x3f,0x40,0x42,0x45,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x34,0xff,0x37,0xff,0xff,0x39,0xff,0x3a,
0x37,0xff,0x38,0xff,0xff,0x3a,0xff,0x3d,
0x38,0x3b,0xff,0xff,0x3d,0x3e,0xff,0xff,
0xff,0xff,0x3b,0x3c,0xff,0xff,0x3e,0x41,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x24,0xff,0x27,0xff,0x29,0xff,0x2a,0xff,
0x27,0xff,0x28,0xff,0x2a,0xff,0x2d,0xff,
0x28,0x2b,0x2d,0x2e,0x31,0x32,0x34,0x37,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x2c,0x2f,0x31,0x32,0xff,0xff,0xff,0xff,
0x2f,0x30,0x32,0x35,0xff,0xff,0xff,0xff,
0x30,0x33,0xff,0xff,0x35,0x36,0xff,0xff,
0x33,0x34,0xff,0xff,0x36,0x39,0xff,0xff,
0x34,0xff,0x37,0xff,0xff,0x39,0xff,0x3a,
0x37,0xff,0x38,0xff,0xff,0x3a,0xff,0x3d,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x2c,0x2f,0xff,0xff,0x31,0x32,0xff,0xff,
0xff,0xff,0x2f,0x30,0xff,0xff,0x32,0x35,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x24,0xff,0x27,0xff,0x29,0xff,0x2a,0xff,
0xff,0x27,0xff,0x28,0xff,0x2a,0xff,0x2d,
0x28,0x2b,0xff,0xff,0xff,0xff,0x2d,0x2e,
0x2b,0x2c,0xff,0xff,0xff,0xff,0x2e,0x31,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x14,0xff,0xff,0x17,0x19,0xff,0xff,0x1a,
0x17,0xff,0xff,0x18,0x1a,0xff,0xff,0x1d,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,0x03,0x05,0x06,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x03,0x04,0x06,0x09,
0x04,0x07,0x09,0xff,0x0b,0xff,0xff,0xff,
0x07,0xff,0xff,0xff,0xff,0xff,0xff,0x09,
0x05,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
0xff,0xff,0xff,0x03,0xff,0x05,0x07,0x08,
0x05,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
0xff,0xff,0xff,0x03,0xff,0x05,0x07,0x08,
0x05,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
0xff,0xff,0xff,0x03,0xff,0x05,0x07,0x08,
0x05,0x06,0xff,0x09,0xff,0x0b,0xff,0xff,
0xff,0x07,0xff,0xff,0xff,0xff,0x09,0xff,
0x05,0xff,0x06,0x09,0xff,0xff,0x0b,0xff,
0xff,0xff,0x07,0xff,0xff,0x09,0xff,0xff,
0x05,0xff,0xff,0xff,0x06,0x09,0x0b,0xff,
0xff,0xff,0xff,0x07,0x09,0xff,0xff,0xff,
0x05,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
0x02,0x05,0x07,0xff,0x09,0xff,0xff,0xff,
0x05,0x06,0xff,0x09,0xff,0x0b,0xff,0xff,
0xff,0x07,0xff,0xff,0xff,0xff,0x09,0xff,
0x05,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
0x02,0x05,0x07,0xff,0x09,0xff,0xff,0xff,
0x05,0xff,0x06,0x09,0xff,0xff,0x0b,0xff,
0xff,0xff,0x07,0xff,0xff,0x09,0xff,0xff,
0x05,0xff,0xff,0xff,0x06,0x09,0x0b,0xff,
0xff,0xff,0xff,0x07,0x09,0xff,0xff,0xff,
0x05,0x06,0xff,0x09,0xff,0x0b,0xff,0xff,
0xff,0x07,0xff,0xff,0xff,0xff,0x09,0xff,
0x05,0xff,0xff,0xff,0x06,0x09,0x0b,0xff,
0xff,0xff,0xff,0x07,0x09,0xff,0xff,0xff,
0x05,0xff,0xff,0xff,0xff,0xff,0xff,0x07,
0x02,0x05,0x07,0xff,0x09,0xff,0xff,0xff,
0x05,0xff,0x06,0x09,0xff,0xff,0x0b,0xff,
0xff,0xff,0x07,0xff,0xff,0x09,0xff,0xff,
0xff,0x04,0xff,0xff,0xff,0xff,0x06,0xff,
0xff,0xff,0x02,0xff,0x04,0xff,0x07,0x08,
0xff,0xff,0x04,0xff,0xff,0x06,0xff,0xff,
0xff,0x02,0xff,0xff,0x04,0x07,0xff,0x08,
0xff,0xff,0xff,0x04,0xff,0x06,0x08,0x0b,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0xff,0x04,0x06,0xff,0xff,0xff,
0xff,0x02,0x04,0x07,0xff,0xff,0xff,0x08,
0xff,0x04,0x06,0x09,0xff,0xff,0xff,0x0a,
0xff,0xff,0xff,0x06,0x08,0xff,0xff,0xff,
0xff,0xff,0xff,0x04,0x06,0xff,0xff,0xff,
0x02,0xff,0xff,0xff,0x05,0x06,0x08,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0x04,0xff,0xff,0x06,0x09,0xff,0x0a,
0xff,0xff,0x06,0xff,0xff,0x08,0xff,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0x04,0xff,0xff,0x06,0xff,0xff,
0x02,0xff,0x05,0x06,0xff,0xff,0x08,0xff,
0xff,0x04,0xff,0xff,0xff,0xff,0x06,0xff,
0x02,0x05,0xff,0x06,0xff,0x08,0xff,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0x04,0xff,0x06,0xff,0x09,0x0a,
0xff,0x06,0xff,0xff,0xff,0xff,0x08,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0x04,0xff,0xff,0xff,0xff,0x06,0xff,
0xff,0xff,0x02,0xff,0x04,0xff,0x07,0x08,
0xff,0xff,0xff,0x04,0x06,0xff,0xff,0xff,
0xff,0x02,0x04,0x07,0xff,0xff,0xff,0x08,
0xff,0xff,0x04,0xff,0xff,0x06,0xff,0xff,
0xff,0x02,0xff,0xff,0x04,0x07,0xff,0x08,
0xff,0xff,0xff,0x04,0xff,0x06,0x08,0x0b,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0x04,0xff,0xff,0xff,0xff,0x06,0xff,
0x02,0x05,0xff,0x06,0xff,0x08,0xff,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0x04,0xff,0x06,0xff,0x09,0x0a,
0xff,0x06,0xff,0xff,0xff,0xff,0x08,0xff,
0xff,0x04,0x06,0x09,0xff,0xff,0xff,0x0a,
0xff,0xff,0xff,0x06,0x08,0xff,0xff,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0xff,0x04,0x06,0xff,0xff,0xff,
0x02,0xff,0xff,0xff,0x05,0x06,0x08,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0x04,0xff,0xff,0x06,0x09,0xff,0x0a,
0xff,0xff,0x06,0xff,0xff,0x08,0xff,0xff,
0xff,0xff,0x04,0xff,0xff,0x06,0xff,0xff,
0x02,0xff,0x05,0x06,0xff,0xff,0x08,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0x04,0xff,0xff,0xff,0xff,0x06,0xff,
0xff,0xff,0x02,0xff,0x04,0xff,0x07,0x08,
0xff,0xff,0xff,0x04,0xff,0x06,0x08,0x0b,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0xff,0x04,0x06,0xff,0xff,0xff,
0xff,0x02,0x04,0x07,0xff,0xff,0xff,0x08,
0xff,0xff,0x04,0xff,0xff,0x06,0xff,0xff,
0xff,0x02,0xff,0xff,0x04,0x07,0xff,0x08,
0xff,0x04,0xff,0xff,0x06,0x09,0xff,0x0a,
0xff,0xff,0x06,0xff,0xff,0x08,0xff,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0x04,0xff,0xff,0x06,0xff,0xff,
0x02,0xff,0x05,0x06,0xff,0xff,0x08,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0x04,0xff,0xff,0xff,0xff,0x06,0xff,
0x02,0x05,0xff,0x06,0xff,0x08,0xff,0xff,
0xff,0xff,0x04,0xff,0x06,0xff,0x09,0x0a,
0xff,0x06,0xff,0xff,0xff,0xff,0x08,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0x04,0x06,0x09,0xff,0xff,0xff,0x0a,
0xff,0xff,0xff,0x06,0x08,0xff,0xff,0xff,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0x05,0x06,0x08,0xff,0x0a,0xff,0xff,0xff,
0x06,0xff,0xff,0xff,0xff,0xff,0xff,0x08,
0xff,0xff,0xff,0x04,0x06,0xff,0xff,0xff,
0x02,0xff,0xff,0xff,0x05,0x06,0x08,0xff
};


/** 
 @brief Table containing data about the Golay code.

 For ``0 <= d < 0x800`` entry ``d``  contains the following
 information the code word ``d``, with ``d`` in ``gcode``
 representation.

   Bit 11,...,0:   ``mat24_ploop_theta(d)``

   Bit 14,...,12:  Bit weight of code word ``d`` in ``GF(2)**24`` divided by 4

   Bit 15:         reserved

 We have ``d**2 = (-1)**<Bit 12 of entry d>`` for ``d`` in the Parker loop.
*/
// %%EXPORT_TABLE
MAT24_API
const uint16_t MAT24_THETA_TABLE[] = { 
// %%TABLE Mat24_theta_table, uint16
0x0000,0x400e,0x400d,0x2403,0x400b,0x2405,0x2406,0x2408,
0x4007,0x2409,0x240a,0x2404,0x240c,0x2402,0x2401,0x400f,
0x200f,0x3021,0x32a2,0x268c,0x31e4,0x25ca,0x2749,0x3767,
0x3368,0x2746,0x25c5,0x35eb,0x2683,0x36ad,0x342e,0x2000,
0x200f,0x3011,0x3152,0x254c,0x3394,0x278a,0x26c9,0x36d7,
0x32d8,0x26c6,0x2785,0x379b,0x2543,0x355d,0x341e,0x2000,
0x200f,0x3031,0x33f2,0x27cc,0x3274,0x264a,0x2589,0x35b7,
0x31b8,0x2586,0x2645,0x367b,0x27c3,0x37fd,0x343e,0x2000,
0x200e,0x2000,0x32a3,0x36ad,0x3395,0x379b,0x2538,0x2536,
0x31b9,0x35b7,0x2714,0x271a,0x2622,0x262c,0x348f,0x3081,
0x220d,0x3223,0x2200,0x362e,0x3076,0x2458,0x347b,0x2455,
0x30da,0x24f4,0x34d7,0x24f9,0x26a1,0x368f,0x26ac,0x3282,
0x230b,0x3315,0x30f6,0x24e8,0x2300,0x371e,0x34fd,0x24e3,
0x306c,0x2472,0x2791,0x378f,0x3467,0x2479,0x279a,0x3384,
0x2107,0x3139,0x305a,0x2464,0x30ec,0x24d2,0x25b1,0x358f,
0x2100,0x353e,0x345d,0x2463,0x34eb,0x24d5,0x25b6,0x3188,
0x200e,0x2000,0x3153,0x355d,0x3275,0x367b,0x2728,0x2726,
0x3369,0x3767,0x2634,0x263a,0x2512,0x251c,0x344f,0x3041,
0x2307,0x3329,0x30fa,0x24d4,0x309c,0x24b2,0x2761,0x374f,
0x2300,0x372e,0x34fd,0x24d3,0x349b,0x24b5,0x2766,0x3348,
0x210d,0x3113,0x2100,0x351e,0x30e6,0x24f8,0x34eb,0x24f5,
0x30ba,0x24a4,0x34b7,0x24a9,0x2551,0x354f,0x255c,0x3142,
0x220b,0x3235,0x30a6,0x2498,0x2200,0x363e,0x34ad,0x2493,
0x30dc,0x24e2,0x2671,0x364f,0x34d7,0x24e9,0x267a,0x3244,
0x200e,0x2000,0x33f3,0x37fd,0x31e5,0x35eb,0x2618,0x2616,
0x32d9,0x36d7,0x2524,0x252a,0x2732,0x273c,0x34cf,0x30c1,
0x210b,0x3125,0x3056,0x2478,0x2100,0x352e,0x345d,0x2473,
0x30bc,0x2492,0x25e1,0x35cf,0x34b7,0x2499,0x25ea,0x31c4,
0x2207,0x3219,0x30aa,0x24b4,0x307c,0x2462,0x26d1,0x36cf,
0x2200,0x361e,0x34ad,0x24b3,0x347b,0x2465,0x26d6,0x32c8,
0x230d,0x3333,0x2300,0x373e,0x3096,0x24a8,0x349b,0x24a5,
0x306a,0x2454,0x3467,0x2459,0x27f1,0x37cf,0x27fc,0x33c2,
0x2401,0x360f,0x44ac,0x32a2,0x447a,0x3274,0x20d7,0x32d9,
0x44d6,0x32d8,0x207b,0x3275,0x20ad,0x32a3,0x4000,0x360e,
0x2482,0x46ac,0x368f,0x30a1,0x4519,0x2337,0x3314,0x313a,
0x4735,0x211b,0x3138,0x3316,0x22ae,0x4080,0x30a3,0x368d,
0x24c8,0x46d6,0x4535,0x232b,0x4723,0x213d,0x22de,0x40c0,
0x36cf,0x30d1,0x3332,0x312c,0x3124,0x333a,0x30d9,0x36c7,
0x2444,0x467a,0x4719,0x2127,0x364f,0x3071,0x3112,0x332c,
0x4523,0x231d,0x227e,0x4040,0x3328,0x3116,0x3075,0x364b,
0x2423,0x362d,0x362e,0x4020,0x47c8,0x31c6,0x31c5,0x23cb,
0x4544,0x334a,0x3349,0x2147,0x22af,0x30a1,0x30a2,0x46ac,
0x26ac,0x4482,0x4601,0x202f,0x34a7,0x3289,0x300a,0x3224,
0x34ab,0x3285,0x3006,0x3228,0x42a0,0x208e,0x220d,0x4423,
0x37e0,0x35fe,0x34bd,0x32a3,0x379b,0x3185,0x30c6,0x32d8,
0x3457,0x3249,0x330a,0x3114,0x302c,0x3232,0x3371,0x356f,
0x3560,0x375e,0x349d,0x32a3,0x34fb,0x32c5,0x3106,0x3338,
0x35b7,0x3389,0x304a,0x3274,0x302c,0x3212,0x31d1,0x37ef,
0x2435,0x363b,0x45c8,0x33c6,0x363e,0x4030,0x33c3,0x21cd,
0x4782,0x318c,0x227f,0x3071,0x3189,0x2387,0x3074,0x467a,
0x37b0,0x359e,0x34ed,0x32c3,0x345b,0x3275,0x3306,0x3128,
0x3767,0x3149,0x303a,0x3214,0x308c,0x32a2,0x33d1,0x35ff,
0x35f0,0x37ee,0x355d,0x3343,0x346b,0x3275,0x30c6,0x32d8,
0x3497,0x3289,0x303a,0x3224,0x310c,0x3312,0x31a1,0x37bf,
0x267a,0x4444,0x3477,0x3249,0x4601,0x203f,0x300c,0x3232,
0x347d,0x3243,0x4270,0x204e,0x3006,0x3238,0x220b,0x4435,
0x2419,0x3617,0x4744,0x314a,0x4582,0x338c,0x22df,0x30d1,
0x361e,0x4010,0x3143,0x234d,0x3385,0x218b,0x30d8,0x46d6,
0x3590,0x37be,0x346d,0x3243,0x35eb,0x33c5,0x3016,0x3238,
0x34f7,0x32d9,0x310a,0x3324,0x308c,0x32a2,0x3171,0x375f,
0x26d6,0x44c8,0x34db,0x32c5,0x34dd,0x32c3,0x42d0,0x20ce,
0x4601,0x201f,0x300c,0x3212,0x300a,0x3214,0x2207,0x4419,
0x3750,0x356e,0x37fd,0x31c3,0x34bb,0x3285,0x3016,0x3228,
0x34e7,0x32d9,0x304a,0x3274,0x330c,0x3132,0x33a1,0x359f,
0x2401,0x350f,0x445c,0x3152,0x44ea,0x31e4,0x20b7,0x31b9,
0x44b6,0x31b8,0x20eb,0x31e5,0x205d,0x3153,0x4000,0x350e,
0x24c4,0x45ea,0x4639,0x2317,0x35cf,0x30e1,0x3332,0x321c,
0x4713,0x223d,0x21ee,0x40c0,0x3218,0x3336,0x30e5,0x35cb,
0x2442,0x455c,0x354f,0x3051,0x4739,0x2227,0x3234,0x332a,
0x4625,0x233b,0x3328,0x3236,0x215e,0x4040,0x3053,0x354d,
0x2488,0x45b6,0x4725,0x221b,0x4613,0x232d,0x21be,0x4080,
0x358f,0x30b1,0x3222,0x331c,0x3314,0x322a,0x30b9,0x3587,
0x2439,0x3537,0x46c4,0x33ca,0x4742,0x324c,0x21bf,0x30b1,
0x353e,0x4030,0x33c3,0x22cd,0x3245,0x234b,0x30b8,0x45b6,
0x36f0,0x37de,0x36ad,0x3383,0x346b,0x3145,0x3036,0x3118,
0x3497,0x31b9,0x30ca,0x31e4,0x320c,0x3322,0x3251,0x377f,
0x3770,0x366e,0x34dd,0x31c3,0x379b,0x3285,0x3036,0x3128,
0x34a7,0x31b9,0x330a,0x3214,0x304c,0x3152,0x33e1,0x36ff,
0x25b6,0x4488,0x34bb,0x3185,0x34bd,0x3183,0x41b0,0x208e,
0x4501,0x203f,0x300c,0x3132,0x300a,0x3134,0x2107,0x4439,
0x2413,0x351d,0x351e,0x4010,0x4688,0x3386,0x3385,0x228b,
0x47c4,0x32ca,0x32c9,0x23c7,0x215f,0x3051,0x3052,0x455c,
0x37d0,0x36fe,0x347d,0x3153,0x34ab,0x3185,0x3306,0x3228,
0x3767,0x3249,0x30ca,0x31e4,0x301c,0x3132,0x33b1,0x369f,
0x255c,0x4442,0x4501,0x201f,0x3457,0x3149,0x300a,0x3114,
0x345b,0x3145,0x3006,0x3118,0x4150,0x204e,0x210d,0x4413,
0x3690,0x37ae,0x346d,0x3153,0x367b,0x3345,0x3086,0x31b8,
0x34f7,0x31c9,0x320a,0x3334,0x301c,0x3122,0x32e1,0x37df,
0x2425,0x352b,0x4788,0x3286,0x352e,0x4020,0x3283,0x238d,
0x4642,0x334c,0x21ef,0x30e1,0x3349,0x2247,0x30e4,0x45ea,
0x25ea,0x44c4,0x34e7,0x31c9,0x4501,0x202f,0x300c,0x3122,
0x34ed,0x31c3,0x41e0,0x20ce,0x3006,0x3128,0x210b,0x4425,
0x3660,0x377e,0x349d,0x3183,0x34fb,0x31e5,0x3206,0x3318,
0x36d7,0x33c9,0x302a,0x3134,0x304c,0x3152,0x32b1,0x37af,
0x37a0,0x369e,0x37fd,0x32c3,0x34db,0x31e5,0x3086,0x31b8,
0x3477,0x3149,0x302a,0x3114,0x330c,0x3232,0x3351,0x366f,
0x2401,0x370f,0x44fc,0x33f2,0x449a,0x3394,0x2067,0x3369,
0x4466,0x3368,0x209b,0x3395,0x20fd,0x33f3,0x4000,0x370e,
0x2448,0x4766,0x4615,0x213b,0x4533,0x221d,0x236e,0x4040,
0x374f,0x3061,0x3112,0x323c,0x3234,0x311a,0x3069,0x3747,
0x2484,0x479a,0x4529,0x2237,0x378f,0x3091,0x3222,0x313c,
0x4633,0x212d,0x239e,0x4080,0x3138,0x3226,0x3095,0x378b,
0x24c2,0x47fc,0x37cf,0x30f1,0x4629,0x2117,0x3124,0x321a,
0x4515,0x222b,0x3218,0x3126,0x23fe,0x40c0,0x30f3,0x37cd,
0x2415,0x371b,0x4648,0x3146,0x371e,0x4010,0x3143,0x224d,
0x45c2,0x32cc,0x239f,0x3091,0x32c9,0x21c7,0x3094,0x479a,
0x3650,0x357e,0x36ad,0x3183,0x34bb,0x3395,0x3046,0x3368,
0x34e7,0x33c9,0x301a,0x3334,0x320c,0x3122,0x32f1,0x35df,
0x279a,0x4484,0x3497,0x3389,0x4701,0x201f,0x300c,0x3312,
0x349d,0x3383,0x4390,0x208e,0x3006,0x3318,0x230b,0x4415,
0x35d0,0x36ee,0x347d,0x3343,0x34ab,0x3395,0x3106,0x3238,
0x35b7,0x3289,0x301a,0x3324,0x30cc,0x33f2,0x3161,0x365f,
0x2429,0x3727,0x4584,0x328a,0x46c2,0x31cc,0x236f,0x3061,
0x372e,0x4020,0x3283,0x218d,0x31c5,0x22cb,0x3068,0x4766,
0x2766,0x4448,0x346b,0x3345,0x346d,0x3343,0x4360,0x204e,
0x4701,0x202f,0x300c,0x3322,0x300a,0x3324,0x2307,0x4429,
0x35a0,0x36be,0x355d,0x3243,0x34db,0x33c5,0x3026,0x3338,
0x3477,0x3369,0x308a,0x3394,0x310c,0x3212,0x31f1,0x36ef,
0x36e0,0x35de,0x34bd,0x3383,0x367b,0x3145,0x3026,0x3318,
0x3457,0x3369,0x320a,0x3134,0x30cc,0x33f2,0x3291,0x35af,
0x2433,0x373d,0x373e,0x4030,0x4548,0x3246,0x3245,0x214b,
0x4684,0x318a,0x3189,0x2287,0x23ff,0x30f1,0x30f2,0x47fc,
0x3570,0x365e,0x34dd,0x33f3,0x35eb,0x32c5,0x3046,0x3368,
0x34a7,0x3389,0x310a,0x3224,0x303c,0x3312,0x3191,0x36bf,
0x36b0,0x35ae,0x34ed,0x33f3,0x345b,0x3345,0x3206,0x3118,
0x36d7,0x31c9,0x308a,0x3394,0x303c,0x3322,0x3261,0x357f,
0x27fc,0x44c2,0x4701,0x203f,0x34f7,0x33c9,0x300a,0x3334,
0x34fb,0x33c5,0x3006,0x3338,0x43f0,0x20ce,0x230d,0x4433,
0x2000,0x4000,0x4000,0x3400,0x4000,0x3400,0x3400,0x3400,
0x4000,0x3400,0x3400,0x3400,0x3400,0x3400,0x3400,0x4000,
0x400f,0x302f,0x32af,0x368f,0x31ef,0x35cf,0x374f,0x476f,
0x336f,0x374f,0x35cf,0x45ef,0x368f,0x46af,0x442f,0x200f,
0x400f,0x301f,0x315f,0x354f,0x339f,0x378f,0x36cf,0x46df,
0x32df,0x36cf,0x378f,0x479f,0x354f,0x455f,0x441f,0x200f,
0x400f,0x303f,0x33ff,0x37cf,0x327f,0x364f,0x358f,0x45bf,
0x31bf,0x358f,0x364f,0x467f,0x37cf,0x47ff,0x443f,0x200f,
0x400e,0x200e,0x32ae,0x46ae,0x339e,0x479e,0x353e,0x353e,
0x31be,0x45be,0x371e,0x371e,0x362e,0x362e,0x448e,0x308e,
0x420d,0x322d,0x220d,0x462d,0x307d,0x345d,0x447d,0x345d,
0x30dd,0x34fd,0x44dd,0x34fd,0x36ad,0x468d,0x36ad,0x328d,
0x430b,0x331b,0x30fb,0x34eb,0x230b,0x471b,0x44fb,0x34eb,
0x306b,0x347b,0x379b,0x478b,0x446b,0x347b,0x379b,0x338b,
0x4107,0x3137,0x3057,0x3467,0x30e7,0x34d7,0x35b7,0x4587,
0x2107,0x4537,0x4457,0x3467,0x44e7,0x34d7,0x35b7,0x3187,
0x400e,0x200e,0x315e,0x455e,0x327e,0x467e,0x372e,0x372e,
0x336e,0x476e,0x363e,0x363e,0x351e,0x351e,0x444e,0x304e,
0x4307,0x3327,0x30f7,0x34d7,0x3097,0x34b7,0x3767,0x4747,
0x2307,0x4727,0x44f7,0x34d7,0x4497,0x34b7,0x3767,0x3347,
0x410d,0x311d,0x210d,0x451d,0x30ed,0x34fd,0x44ed,0x34fd,
0x30bd,0x34ad,0x44bd,0x34ad,0x355d,0x454d,0x355d,0x314d,
0x420b,0x323b,0x30ab,0x349b,0x220b,0x463b,0x44ab,0x349b,
0x30db,0x34eb,0x367b,0x464b,0x44db,0x34eb,0x367b,0x324b,
0x400e,0x200e,0x33fe,0x47fe,0x31ee,0x45ee,0x361e,0x361e,
0x32de,0x46de,0x352e,0x352e,0x373e,0x373e,0x44ce,0x30ce,
0x410b,0x312b,0x305b,0x347b,0x210b,0x452b,0x445b,0x347b,
0x30bb,0x349b,0x35eb,0x45cb,0x44bb,0x349b,0x35eb,0x31cb,
0x4207,0x3217,0x30a7,0x34b7,0x3077,0x3467,0x36d7,0x46c7,
0x2207,0x4617,0x44a7,0x34b7,0x4477,0x3467,0x36d7,0x32c7,
0x430d,0x333d,0x230d,0x473d,0x309d,0x34ad,0x449d,0x34ad,
0x306d,0x345d,0x446d,0x345d,0x37fd,0x47cd,0x37fd,0x33cd,
0x3601,0x2401,0x36a1,0x30a1,0x3671,0x3071,0x22d1,0x30d1,
0x36d1,0x30d1,0x2271,0x3071,0x22a1,0x30a1,0x4201,0x2401,
0x3682,0x34a2,0x2482,0x32a2,0x3712,0x2132,0x3112,0x3332,
0x3532,0x2312,0x3332,0x3112,0x20a2,0x4282,0x32a2,0x2482,
0x36c8,0x34d8,0x3738,0x2128,0x3528,0x2338,0x20d8,0x42c8,
0x24c8,0x32d8,0x3138,0x3328,0x3328,0x3138,0x32d8,0x24c8,
0x3644,0x3474,0x3514,0x2324,0x2444,0x3274,0x3314,0x3124,
0x3724,0x2114,0x2074,0x4244,0x3124,0x3314,0x3274,0x2444,
0x3623,0x2423,0x2423,0x4223,0x35c3,0x33c3,0x33c3,0x21c3,
0x3743,0x3143,0x3143,0x2343,0x20a3,0x32a3,0x32a3,0x34a3,
0x34ac,0x368c,0x340c,0x222c,0x26ac,0x308c,0x320c,0x302c,
0x26ac,0x308c,0x320c,0x302c,0x40ac,0x228c,0x200c,0x362c,
0x45e0,0x27f0,0x26b0,0x30a0,0x2590,0x3380,0x32c0,0x30d0,
0x2650,0x3040,0x3100,0x3310,0x3220,0x3030,0x3170,0x2760,
0x4760,0x2550,0x2690,0x30a0,0x26f0,0x30c0,0x3300,0x3130,
0x27b0,0x3180,0x3240,0x3070,0x3220,0x3010,0x33d0,0x25e0,
0x3635,0x2435,0x37c5,0x31c5,0x2435,0x4235,0x31c5,0x23c5,
0x3585,0x3385,0x2075,0x3275,0x3385,0x2185,0x3275,0x3475,
0x45b0,0x2790,0x26e0,0x30c0,0x2650,0x3070,0x3100,0x3320,
0x2560,0x3340,0x3230,0x3010,0x3280,0x30a0,0x31d0,0x27f0,
0x47f0,0x25e0,0x2750,0x3140,0x2660,0x3070,0x32c0,0x30d0,
0x2690,0x3080,0x3230,0x3020,0x3300,0x3110,0x33a0,0x25b0,
0x347a,0x364a,0x267a,0x304a,0x340a,0x223a,0x320a,0x303a,
0x267a,0x304a,0x407a,0x224a,0x320a,0x303a,0x200a,0x363a,
0x3619,0x2419,0x3549,0x3349,0x3789,0x3189,0x20d9,0x32d9,
0x2419,0x4219,0x3349,0x2149,0x3189,0x2389,0x32d9,0x34d9,
0x4790,0x25b0,0x2660,0x3040,0x27e0,0x31c0,0x3210,0x3030,
0x26f0,0x30d0,0x3300,0x3120,0x3280,0x30a0,0x3370,0x2550,
0x34d6,0x36c6,0x26d6,0x30c6,0x26d6,0x30c6,0x40d6,0x22c6,
0x3406,0x2216,0x3206,0x3016,0x3206,0x3016,0x2006,0x3616,
0x4550,0x2760,0x25f0,0x33c0,0x26b0,0x3080,0x3210,0x3020,
0x26e0,0x30d0,0x3240,0x3070,0x3100,0x3330,0x31a0,0x2790,
0x3501,0x2401,0x3551,0x3051,0x35e1,0x30e1,0x21b1,0x30b1,
0x35b1,0x30b1,0x21e1,0x30e1,0x2151,0x3051,0x4101,0x2401,
0x35c4,0x34e4,0x3734,0x2214,0x24c4,0x31e4,0x3234,0x3314,
0x3614,0x2334,0x20e4,0x41c4,0x3314,0x3234,0x31e4,0x24c4,
0x3542,0x3452,0x2442,0x3152,0x3632,0x2322,0x3332,0x3222,
0x3722,0x2232,0x3222,0x3332,0x2052,0x4142,0x3152,0x2442,
0x3588,0x34b8,0x3628,0x2318,0x3718,0x2228,0x20b8,0x4188,
0x2488,0x31b8,0x3328,0x3218,0x3218,0x3328,0x31b8,0x2488,
0x3539,0x2439,0x37c9,0x32c9,0x3649,0x3349,0x20b9,0x31b9,
0x2439,0x4139,0x32c9,0x23c9,0x3349,0x2249,0x31b9,0x34b9,
0x47f0,0x26d0,0x27a0,0x3280,0x2560,0x3040,0x3130,0x3010,
0x2590,0x30b0,0x31c0,0x30e0,0x3300,0x3220,0x3350,0x2670,
0x4670,0x2760,0x25d0,0x30c0,0x2690,0x3380,0x3130,0x3020,
0x25a0,0x30b0,0x3200,0x3310,0x3140,0x3050,0x32e0,0x27f0,
0x34b6,0x3586,0x25b6,0x3086,0x25b6,0x3086,0x40b6,0x2186,
0x3406,0x2136,0x3106,0x3036,0x3106,0x3036,0x2006,0x3536,
0x3513,0x2413,0x2413,0x4113,0x3783,0x3283,0x3283,0x2383,
0x36c3,0x33c3,0x33c3,0x22c3,0x2053,0x3153,0x3153,0x3453,
0x46d0,0x27f0,0x2570,0x3050,0x25a0,0x3080,0x3200,0x3320,
0x2660,0x3340,0x31c0,0x30e0,0x3110,0x3030,0x32b0,0x2790,
0x345c,0x354c,0x340c,0x211c,0x255c,0x304c,0x310c,0x301c,
0x255c,0x304c,0x310c,0x301c,0x405c,0x214c,0x200c,0x351c,
0x4790,0x26a0,0x2560,0x3050,0x2770,0x3240,0x3180,0x30b0,
0x25f0,0x30c0,0x3300,0x3230,0x3110,0x3020,0x33e0,0x26d0,
0x3525,0x2425,0x3685,0x3385,0x2425,0x4125,0x3385,0x2285,
0x3745,0x3245,0x20e5,0x31e5,0x3245,0x2345,0x31e5,0x34e5,
0x34ea,0x35ca,0x25ea,0x30ca,0x340a,0x212a,0x310a,0x302a,
0x25ea,0x30ca,0x40ea,0x21ca,0x310a,0x302a,0x200a,0x352a,
0x4760,0x2670,0x2590,0x3080,0x25f0,0x30e0,0x3300,0x3210,
0x27d0,0x32c0,0x3120,0x3030,0x3140,0x3050,0x33b0,0x26a0,
0x46a0,0x2790,0x26f0,0x33c0,0x25d0,0x30e0,0x3180,0x30b0,
0x2570,0x3040,0x3120,0x3010,0x3200,0x3330,0x3250,0x2760,
0x3701,0x2401,0x37f1,0x30f1,0x3791,0x3091,0x2361,0x3061,
0x3761,0x3061,0x2391,0x3091,0x23f1,0x30f1,0x4301,0x2401,
0x3748,0x3468,0x3518,0x2238,0x3638,0x2118,0x2068,0x4348,
0x2448,0x3368,0x3218,0x3138,0x3138,0x3218,0x3368,0x2448,
0x3784,0x3494,0x3624,0x2134,0x2484,0x3394,0x3124,0x3234,
0x3534,0x2224,0x2094,0x4384,0x3234,0x3124,0x3394,0x2484,
0x37c2,0x34f2,0x24c2,0x33f2,0x3522,0x2212,0x3222,0x3112,
0x3612,0x2122,0x3112,0x3222,0x20f2,0x43c2,0x33f2,0x24c2,
0x3715,0x2415,0x3545,0x3245,0x2415,0x4315,0x3245,0x2145,
0x36c5,0x31c5,0x2095,0x3395,0x31c5,0x22c5,0x3395,0x3495,
0x4550,0x2670,0x25a0,0x3280,0x27b0,0x3090,0x3340,0x3060,
0x27e0,0x30c0,0x3310,0x3030,0x3100,0x3220,0x31f0,0x26d0,
0x349a,0x378a,0x279a,0x308a,0x340a,0x231a,0x330a,0x301a,
0x279a,0x308a,0x409a,0x238a,0x330a,0x301a,0x200a,0x371a,
0x46d0,0x25e0,0x2770,0x3040,0x27a0,0x3090,0x3200,0x3130,
0x26b0,0x3180,0x3310,0x3020,0x33c0,0x30f0,0x3260,0x2550,
0x3729,0x2429,0x3689,0x3189,0x35c9,0x32c9,0x2069,0x3369,
0x2429,0x4329,0x3189,0x2289,0x32c9,0x21c9,0x3369,0x3469,
0x3466,0x3746,0x2766,0x3046,0x2766,0x3046,0x4066,0x2346,
0x3406,0x2326,0x3306,0x3026,0x3306,0x3026,0x2006,0x3726,
0x46a0,0x25b0,0x2650,0x3140,0x27d0,0x30c0,0x3320,0x3030,
0x2770,0x3060,0x3380,0x3090,0x3200,0x3110,0x32f0,0x25e0,
0x45e0,0x26d0,0x27b0,0x3080,0x2570,0x3240,0x3320,0x3010,
0x2750,0x3060,0x3100,0x3230,0x33c0,0x30f0,0x3190,0x26a0,
0x3733,0x2433,0x2433,0x4333,0x3643,0x3143,0x3143,0x2243,
0x3583,0x3283,0x3283,0x2183,0x20f3,0x33f3,0x33f3,0x34f3,
0x4670,0x2550,0x27d0,0x30f0,0x26e0,0x31c0,0x3340,0x3060,
0x27a0,0x3080,0x3200,0x3120,0x3330,0x3010,0x3290,0x25b0,
0x45b0,0x26a0,0x27e0,0x30f0,0x2750,0x3040,0x3100,0x3210,
0x25d0,0x32c0,0x3380,0x3090,0x3330,0x3020,0x3160,0x2670,
0x34fc,0x37cc,0x340c,0x233c,0x27fc,0x30cc,0x330c,0x303c,
0x27fc,0x30cc,0x330c,0x303c,0x40fc,0x23cc,0x200c,0x373c
};


/** 
  @brief Convert bit vector ``v1`` in ``GF(2)^24`` from ``vector``
  to ``vintern`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_vect_to_vintern(uint32_t v1)
{
    return  MAT24_ENC_TABLE0[v1 & 0xff]
          ^ MAT24_ENC_TABLE1[(v1 >> 8) & 0xff]
          ^ MAT24_ENC_TABLE2[(v1 >> 16) & 0xff];
}


/** 
  @brief Convert bit vector ``v1`` in ``GF(2)^24`` from ``vintern``
  to ``vector`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_vintern_to_vect(uint32_t v1)
{
    return  MAT24_DEC_TABLE0[v1 & 0xff]
           ^ MAT24_DEC_TABLE1[(v1 >> 8) & 0xff]
           ^ MAT24_DEC_TABLE2[(v1 >> 16) & 0xff];
}

/** 
  @brief Return Golay cocode element corresponding to a bit vector
  in ``GF(2)^24``.

  This amounts to reducing the vector ``v1`` (given in ``vector``
  representation) modulo the Golay code. 
  The function returns the cocode element corresponding to ``v1``
  in ``cocode`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_vect_to_cocode(uint32_t v1)
{
    return  (MAT24_ENC_TABLE0[v1 & 0xff]
          ^ MAT24_ENC_TABLE1[(v1 >> 8) & 0xff]
          ^ MAT24_ENC_TABLE2[(v1 >> 16) & 0xff]) & 0xfff;
}

/** 
  @brief Convert Golay code element number ``v1`` to a vector in ``GF(2)^24``

  Input ``v1`` is a Golay code element in ``gcode`` representation. 
  The function returns the bit vector corresponding to ``v1``
  in ``vector`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_gcode_to_vect(uint32_t v1)
{
    return  MAT24_DEC_TABLE1[(v1 << 4) & 0xf0]
          ^ MAT24_DEC_TABLE2[(v1 >> 4) & 0xff];
}

/** 
  @brief Return a vector in ``GF(2)^24`` corresponding to cocode element

  Here ``c1`` is the number of a cocode element in ``cocode`` 
  representation. One of ``2**12`` possible preimages of ``c1`` in
  ``GF(2)^24``  is returned in ``vector`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_cocode_to_vect(uint32_t c1)
{
    return mat24_vintern_to_vect(c1);
}

/** 
  @brief Return a vector in ``GF(2)^24`` as a Golay code element.

  If the vector ``v1`` (given in ``vector`` representation) is in
  the Golay code then the function returns the number of that
  Golay code word. Thus the return value is in ``gcode``
  representation.

  If ``v1`` is not in the Golay code then the function
  returns ``(uint32_t)(-1)``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_vect_to_gcode(uint32_t v1)
{
    uint_fast32_t  cn =  mat24_vect_to_vintern(v1);
    return cn & 0xfff ? (uint32_t)(-1)   : cn >> 12;
}



/** 
  @brief Return a Golay code vector as an octad.

  If ``u_strict`` is even then the function acts as follows:

  If the Golay code vector ``v1`` (given in ``gcode`` representation) 
  is  an octad or a complement of an octad then the function returns 
  the number of that octad. Thus the return value is in ``octad``
  representation. Then we have ``0 <= octad(v1, strict) < 759``.

  If ``v1`` is not a (possibly complemented) octad then the 
  function returns ``(uint32_t)(-1)``.

  If ``u_strict`` is odd then the function returns ``(uint32_t)(-1)`` 
  also in case of a complemented octad ``v1``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_gcode_to_octad(uint32_t v1, uint32_t u_strict)
{
    uint_fast32_t y;
    u_strict = (u_strict & 1) + 0x100;
    v1 &= 0xfff;
    y = MAT24_OCT_ENC_TABLE[v1 & 0x7ff];
    if (((y ^ ((v1 >> 11) & 1)) + 2) & u_strict) return  (uint32_t)(-1);
    return (y >> 1) + 3 * ((v1 & 0x7ff) >> 3) - 11;
}


/** 
  @brief Return a vector in ``GF(2)^24`` as an octad.

  If ``u_strict`` is even then the function acts as follows:

  If the vector ``v1`` (given in ``vector`` representation) is 
  an octad or a complement of an octad then the function returns 
  the number of that octad. Thus the return value is in ``octad``
  representation. Then we have `` 0 <= octad(v1, strict) < 759``.

  If ``v1`` is not a (possibly complemented) octad then the 
  function returns ``(uint32_t)(-1)``.

  If ``u_strict`` is odd then the function returns ``(uint32_t)(-1)`` 
  also in case of a complemented octad ``v1``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_vect_to_octad(uint32_t v1, uint32_t u_strict)
{
    uint_fast32_t y, err;
    u_strict = (u_strict & 1) + 0x100;
    err = MAT24_ENC_TABLE0[v1 & 0xff]
             ^ MAT24_ENC_TABLE1[(v1 >> 8) & 0xff]
             ^ MAT24_ENC_TABLE2[(v1 >> 16) & 0xff];
    v1 = err >> 12;
    err &= 0xfff;
    y = MAT24_OCT_ENC_TABLE[v1 & 0x7ff];
    err |=  (((y ^ ((v1 >> 11) & 1)) + 2) & u_strict);
    if (err) return  (uint32_t)(-1);
    return (y >> 1) + 3 * ((v1 & 0x7ff) >> 3) - 11;
}


/** 
  @brief Convert an octad to a Golay code vector.

  Given an octad ``u_octad`` (in ``octad`` representation), the
  function returns the number of the corresponding Golay code
  number in ``gcode`` representation. 

  There are  759 octads. The  function returns ``(uint32_t)(-1)``
  in case  ``u_octad >= 759``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_octad_to_gcode(uint32_t u_octad)
{   
    return u_octad < 759 ? MAT24_OCT_DEC_TABLE[u_octad] & 0xfff 
                         : (uint32_t)(-1);
}


/** 
  @brief Convert an octad to a bit vector in ``GF(2)^24``.

  Given an octad ``u_octad`` (in ``octad`` representation), the
  function returns bit vector corresponding to that octad
  in ``vector`` representation. 

  There are  759 octads. The  function returns ``(uint32_t)(-1)``
  in case  ``u_octad >= 759``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_octad_to_vect(uint32_t u_octad)
{
    uint_fast32_t u;
    if (u_octad >= 759) return (uint32_t)(-1);
    u = MAT24_OCT_DEC_TABLE[u_octad] & 0xfff;
    return  MAT24_DEC_TABLE1[(u << 4) & 0xf0]
          ^ MAT24_DEC_TABLE2[(u >> 4) & 0xff];
}


/*************************************************************************
*** Golay code syndomes and weights
*************************************************************************/

/** 
  @brief Return Golay code syndrome of cocode element  ``c1``.

  Here ``c1`` is a cocode element in ``cocode``  representation. 
  mat24_cocode_syndrome(c1, u_tetrad) is equivalent to 
  mat24_syndrome(mat24_cocode_to_vect(c1), u_tetrad).

  The function returns a Golay code syndrome as described in the 
  documentation of function  mat24_syndrome().   
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_cocode_syndrome(uint32_t c1, uint32_t u_tetrad)
{
        uint_fast32_t  y, syn, bad; 
        if (u_tetrad > 24) return (uint32_t)(-1L);
        bad = (u_tetrad + 8) >> 5;       // bad = (u_tetrad >= 24)
        u_tetrad -= bad;                 // change 24 to 23
        y = 0 - (((c1 >> 11) + 1) & 1);  // y = 0 if c1 is odd else -1
        bad &= y;                        // bad  &= (weight(c1) even)
        c1 ^= MAT24_RECIP_BASIS[u_tetrad & 31] & y;
            // if even: flip bit 'u_tetrad' in cocode repr. 'c1'
        y  &=  1 << u_tetrad;            // y = 1 << u_tetrad if even
        syn = MAT24_SYNDROME_TABLE[ c1 & 0x7ff ];
        syn = (1 << (syn & 31)) | (1 << ((syn >> 5) & 31))   
                               | (1 << ((syn >> 10) & 31));
        // Now syn is the syndrome of the odd word c1. Thus syn has
        // odd parity. Bit 24 of syn is set if weight(syn) == 1.
        bad &= ((syn & (y | 0x1000000)) - 1) >> 25; 
            // bad &= weight(syn) > 1 and y & syn == 0
        syn ^= y;                        // the final syndrome
        return (syn & 0xffffff) | (0 - (bad & 1));
            // clear high bits, return syndrome of ok, else -1
}


/** 
  @brief Return Golay code syndrome of word ``v1``.

  Here ``v1`` is an arbitrary word in ``GF(2)**24`` in ``vector``
  representation. The function returns a Golay code syndrome of 
  ``v1`` (of minimum possible bit weight) as a bit vector in 
  ``vector`` representation. 

  Such a syndrome is unique if it has weight less than 4. In that
  case the unique syndrome is returned.

  If the minimum weight of the syndrome is four then the six
  possible syndroms form a partition of the the underlying set
  of 24 elements. In this case we return the syndrome of bit 
  weight four where the bit at position ``u_tetrad`` is  set.
  Therefore parameter ``u_tetrad`` must satisfy
  `` 0 <= u_tetrad <= 24``; otherwise the function fails.

  If the minimum weight of the sydrome is at most three,
  parameter ``u_tetrad`` must satisfy `` 0 <= u_tetrad < 24``; 
  otherwise the function fails.

  The function returns ``(uint32_t)(-1)`` in case of failure.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_syndrome(uint32_t v1, uint32_t u_tetrad)
{
        uint_fast32_t as_cocode;

        as_cocode = MAT24_ENC_TABLE0[v1 & 0xff]
                  ^ MAT24_ENC_TABLE1[(v1 >> 8) & 0xff]
                  ^ MAT24_ENC_TABLE2[(v1 >> 16) & 0xff];
                  // This is  mat24_vect_to_vintern(v1)
        return  mat24_cocode_syndrome(as_cocode, u_tetrad);
}



/** 
  @brief Returns bit weight of Golay code word ``v1`` divided by 4

  Here ``0 <= v1 < 4096`` is the number of a Golay code word,
  i.e. ``v1`` is given in ``gcode`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_gcode_weight(uint32_t v1)
{
   register uint_fast32_t  t = 0 - ((v1 >> 11) & 1);
   return (((MAT24_THETA_TABLE[v1 & 0x7ff] >> 12) & 7) ^ t) 
                 + (t & 7);  
}


/** 
  @brief Store bit positions of Golay code ``v1`` in array ``a_out`` 

  Here ``0 <= v1 < 4096`` is the number of a Golay code word,  i.e. 
  ``v1`` is given in ``gcode`` representation. The Golay code word 
  ``v1`` is stored in the array referred by ``a_out`` as an ordered 
  list of the positions of the bits being set in the word ``v1``.

  That array must have physical length at least 24. The function 
  returns the actual length of the returned array, which is equal 
  to the bit weight of the word ``v1``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_gcode_to_bit_list(uint32_t v1, uint8_t *a_out)
{
   v1 = MAT24_DEC_TABLE1[(v1 << 4) & 0xf0]
          ^ MAT24_DEC_TABLE2[(v1 >> 4) & 0xff];
   return mat24_vect_to_bit_list(v1, a_out);
}

/** 
  @brief Return the minimum possible weight of the cocode vector ``c1``

  Here ``c1`` is a cocode element in ``cocode`` representation.
*/ 
// %%EXPORT p
MAT24_API
uint32_t mat24_cocode_weight(uint32_t c1)

{
    uint_fast32_t syn = MAT24_SYNDROME_TABLE[c1 & 0x7ff], mask;
    if (c1 & 0x800) 
        return 3 - ((((syn & 0x7fff) + 0x2000) >> 15) << 1);
    mask = (0UL - (c1 & 0xfffUL)) >> 16;
    return (4 - ((syn >> 15) << 1)) & mask;
}


/** 
  @brief Store Golay code syndrome of cocode word ``c1`` in an array

  Here ``c1`` is an cocode word in cocode representation. The function 
  stores the sorted  bit positions of the syndrome of ``c1`` in the 
  array referred by ``a_out`` and returns the actual length of that
  array, which is the weight of the syndrome. The array referred by 
  ``a_out`` must have physical length at least 4. 

  Such a syndrome is unique if it has weight less than 4. In that
  case the unique syndrome is returned.

  If the minimum weight of the syndrome is four then the six
  possible syndroms form a partition of the the underlying set
  of 24 elements. In this case we return the syndrome of bit 
  weight four where the bit at position ``u_tetrad`` is  set.
  Therefore parameter ``u_tetrad`` must
  satisfy ``0 <= u_tetrad < 24``; otherwise the function fails.

  If the minimum weight of the sydrome is at most three,
  parameter ``u_tetrad`` must satisfy `` 0 <= u_tetrad <= 24``; 
  otherwise the function fails.

  The function returns ``(uint32_t)(-1)`` in case of failure.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_cocode_to_bit_list(uint32_t c1, uint32_t u_tetrad, uint8_t *a_out)
{
        uint_fast32_t  syn, bad, len, i, tmp, a[6]; 
        if (u_tetrad > 24) return (uint32_t)(-1L);
        if ((c1 & 0x800) == 0) {             // case even cocode word
            bad = u_tetrad == 24;       
            u_tetrad -= bad;                 // change 24 to 23
            c1 ^= MAT24_RECIP_BASIS[u_tetrad & 31];
                          // flip bit 'u_tetrad' in cocode repr. 'c1'
            syn = MAT24_SYNDROME_TABLE[ c1 & 0x7ff ];
            a[3] = a[4] = a[5] = 24;      
            a[0] =  syn & 31; 
            a[1] =  (syn >> 5) & 31; 
            len = a[1] == 24 ? 2 : 4;
            a[2] =  (syn >> 10) & 31; 
            a[len-1] = u_tetrad;
            i = len - 1;
            while (i > 0 && a[i] < a[i-1]) {
                tmp = a[i]; a[i] = a[i-1]; a[i-1] = tmp;
                --i;
            }
            if (i > 0 &&  a[i] == a[i-1]) {
                 a[i-1] = a[i+1]; a[i] = a[i+2]; len -= 2;
            }
            a_out[0] = (uint8_t)a[0]; a_out[1] = (uint8_t)a[1]; 
            a_out[2] = (uint8_t)a[2]; a_out[3] = (uint8_t)a[3]; 
            return  (bad && len == 4) ? (uint32_t)(-1) : len;
        } else{                             // case odd cocode word
            syn = MAT24_SYNDROME_TABLE[ c1 & 0x7ff ];
            a_out[0] =  (uint8_t)(syn & 31); 
            a_out[1] =  (uint8_t)((syn >> 5) & 31); 
            len = a_out[1] == 24 ? 1 : 3;            
            a_out[2] =  (uint8_t)((syn >> 10) & 31);
            a_out[3] = 24; 
            return len;
        }
}


/** 
  @brief Store a cocode word ``c1`` in array ``a_out`` as a sextet

  Here ``c1`` is an cocode word in cocode representation. That 
  cocode word must correspond to a syndrome of length four, i.e.
  the syndrome must be a tetrad. Otherwise the function fails.

  The function stores the six tetrads that make up the sextet ``c1`` 
  in ``a_out[4*i],...,a_out[4*i+3]`` for ``i = 0,...,5``. The 
  (ordered) tetrads are stored in lexical order. 

  The function returns ``(uint32_t)(-1)`` if ``c1`` has not
  minimum weight 4.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_cocode_to_sextet(uint32_t c1, uint8_t *a_out)
{
    uint_fast32_t c2, syn, v;
    if (c1 & 0x800) return (uint32_t)(-1L);
    c2 =  c1 ^ MAT24_RECIP_BASIS[0];
    syn = MAT24_SYNDROME_TABLE[c2 & 0x7ff];
    if ((syn & 31) == 0) return (uint32_t)(-1L);
    a_out[0] = 0;
    a_out[1] = syn & 31; 
    a_out[2] = (syn >> 5) & 31; 
    a_out[3] = (syn >> 10) & 31; 
    v = 0xffffff;
    // %%FOR i in range(4, 24, 4)
        v ^= (1 << a_out[4-4]) ^ (1 << a_out[4-3]) 
           ^ (1 << a_out[4-2]) ^ (1 << a_out[4-1]);
        a_out[4] = mat24_def_lsbit24(v); 
        c2 =  c1 ^ MAT24_RECIP_BASIS[a_out[4]];
        syn = MAT24_SYNDROME_TABLE[c2 & 0x7ff];
        a_out[4+1] = syn & 31; 
        a_out[4+2] = (syn >> 5) & 31; 
        a_out[4+3] = (syn >> 10) & 31; 
        v ^= (1 << a_out[8-4]) ^ (1 << a_out[8-3]) 
           ^ (1 << a_out[8-2]) ^ (1 << a_out[8-1]);
        a_out[8] = mat24_def_lsbit24(v); 
        c2 =  c1 ^ MAT24_RECIP_BASIS[a_out[8]];
        syn = MAT24_SYNDROME_TABLE[c2 & 0x7ff];
        a_out[8+1] = syn & 31; 
        a_out[8+2] = (syn >> 5) & 31; 
        a_out[8+3] = (syn >> 10) & 31; 
        v ^= (1 << a_out[12-4]) ^ (1 << a_out[12-3]) 
           ^ (1 << a_out[12-2]) ^ (1 << a_out[12-1]);
        a_out[12] = mat24_def_lsbit24(v); 
        c2 =  c1 ^ MAT24_RECIP_BASIS[a_out[12]];
        syn = MAT24_SYNDROME_TABLE[c2 & 0x7ff];
        a_out[12+1] = syn & 31; 
        a_out[12+2] = (syn >> 5) & 31; 
        a_out[12+3] = (syn >> 10) & 31; 
        v ^= (1 << a_out[16-4]) ^ (1 << a_out[16-3]) 
           ^ (1 << a_out[16-2]) ^ (1 << a_out[16-1]);
        a_out[16] = mat24_def_lsbit24(v); 
        c2 =  c1 ^ MAT24_RECIP_BASIS[a_out[16]];
        syn = MAT24_SYNDROME_TABLE[c2 & 0x7ff];
        a_out[16+1] = syn & 31; 
        a_out[16+2] = (syn >> 5) & 31; 
        a_out[16+3] = (syn >> 10) & 31; 
        v ^= (1 << a_out[20-4]) ^ (1 << a_out[20-3]) 
           ^ (1 << a_out[20-2]) ^ (1 << a_out[20-1]);
        a_out[20] = mat24_def_lsbit24(v); 
        c2 =  c1 ^ MAT24_RECIP_BASIS[a_out[20]];
        syn = MAT24_SYNDROME_TABLE[c2 & 0x7ff];
        a_out[20+1] = syn & 31; 
        a_out[20+2] = (syn >> 5) & 31; 
        a_out[20+3] = (syn >> 10) & 31; 
    // %%END FOR
    return 0;
}



/*************************************************************************
*** Scalar product of Golay code and cocode
*************************************************************************/

/** 
  @brief Return scalar product of Golay code and cocode vector

  ``v1`` is a Golay code vector in 'gcode' representation, ``c1``
  is a cocode vector in cocode representation.

  Actually the function returns the bit parity of ``v1 & c1 & 0xfff``.
  
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_scalar_prod(uint32_t v1, uint32_t c1)
{
    v1 &= c1;
    mat24_def_parity12(v1);
    return v1;
}



/*************************************************************************
*** Conversion from and to suboctads
*************************************************************************/
/** 
  @brief Convert even suboctad of octad  to cocode representation
  
  The function converts a suboctad ``u_sub`` (in ``suboctad`` 
  representation) of an octad ``v1`` (in ``gcode`` representation) 
  to a cocode element. It returns that cocode element in ``cocode``
  representation.

  Each octad ``v1`` has 64 even subsets, when each subset of ``v1``
  is identified with its complement in ``v1``. These subsets are 
  called suboctads. Let ``b_0, ..., b_7 `` be the elements of the 
  octad ``v1`` in natural order. Then the even subset ``(b_0 , b_i)``
  has suboctad number ``2**(i-1)`` for ``i = 1,...,6``. Combining 
  suboctads by symmetric difference corresponds to combining their 
  numbers by ``xor``. The empty subocatad has number zero. This yields 
  a one-to-one correspondence between the integers ``0,...,63`` and
  the suboctads of a fixed octad ``v1``, when identifying a suboctad 
  with its complement. 
 
  The function returns the suboctad of ``v1`` with number ``u_sub``
  in ``cocode`` representation. Octad ``v1`` must be given in 
  ``gcode`` representation. If ``v1`` is a complement 
  of an octad ``o`` the ``o`` is taken instead of ``v1``.
 
  The function fails if ``v1`` does not represent an octad.
  It returns ``(uint32_t)(-1)`` in case of failure.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_suboctad_to_cocode(uint32_t u_sub, uint32_t v1)
{
    uint_fast32_t oct, l;
    // Let oct = vector of v1 in 'vect' representation
    oct =  MAT24_DEC_TABLE1[(v1 << 4) & 0xf0]
                       ^ MAT24_DEC_TABLE2[(v1 >> 4) & 0xff]; 
    // Let  l =  weight(v1)/4
    l = mat24_gcode_weight(v1);
    // Complement ``oct`` if weight(v1) == 16, 
    // abort if that weight is not 8 or 16
    if (l == 4) oct ^= 0xffffff;
    else if (l != 2) return (uint32_t)(-1);
    // Put l = parity of u_sub
    l =  (0x96 >> ((u_sub ^ (u_sub >> 3)) & 7)) & 1;  
    // Let u_sub be a vector representing the suboctad of w with No u_sub
    u_sub = l + ((u_sub & 0x3f) << 1); 
    u_sub = mat24_spread_b24(u_sub, oct);
    // Finally, convert that vector to cocode representation
    return  (MAT24_ENC_TABLE0[u_sub & 0xff]
          ^ MAT24_ENC_TABLE1[(u_sub >> 8) & 0xff]
          ^ MAT24_ENC_TABLE2[(u_sub >> 16) & 0xff]) & 0xfff;
}

/** 
  @brief Convert cocode element ``c1`` to suboctad of octad ``v1``

  The function converts a cocode element ``c1`` (in ``cocode`` 
  representation) of an octad ``v1`` (in ``gcode`` representation) 
  to a suboctad. 

  This is an inverse of function mat24_suboctad_to_cocode().
  The function returns the suboctad number corresponding to the
  cocode element ``c1``, if ``v1`` is an octad and ``c1`` is an 
  even subset of ``v1``. See documentation of function 
  mat24_suboctad_to_cocode() for the numbering of the suboctads.
 
  The function fails if ``v1`` is not a octad or ``c1`` cannot be
  represented as an even subset of ``v1``. If ``v1`` is a complement 
  of an octad ``o`` the ``o`` is taken instead of ``v1``.
  The function returns ``(uint32_t)(-1)`` in case of failure.
*/

// %%EXPORT p
MAT24_API
uint32_t mat24_cocode_to_suboctad(uint32_t c1, uint32_t v1)

{
    uint_fast32_t syn, oct, l;
    // Let oct = vector of v1 in 'vect' representation
    oct =  MAT24_DEC_TABLE1[(v1 << 4) & 0xf0]
                       ^ MAT24_DEC_TABLE2[(v1 >> 4) & 0xff]; 
    // Let  l =  weight(v1)/4
    l = mat24_gcode_weight(v1);
    // Complement ``oct`` if weight(v1) == 16, 
    // abort if that weight is not 8 or 16
    if (l == 4) oct ^= 0xffffff;
    else if (l != 2) return (uint32_t)(-1);
    // Abort if c1 is not even
    if (c1 & 0x800) return (uint32_t)(-1);
    // l = lsbit of oct
    l = mat24_def_lsbit24(oct);
    // compute syndrome of (odd) vector w ^ 2**l, w = gcode_to_vect(v1)
    c1 ^= MAT24_RECIP_BASIS[l];
    syn = MAT24_SYNDROME_TABLE[ c1 & 0x7ff ];
    syn = mat24_def_syndrome_from_table(syn);
    // Abort if syndrome is not a subset of the octad oct
    if ((syn & oct) != syn) return (uint32_t)(-1);
    // Compress syndrome to suboctad number
    syn = mat24_extract_b24(syn, oct) >> 1;
    // Complement suboctad number if highest bit is set
    l = (syn >> 6) & 1;
    return (syn ^ (0-l)) & 0x3f;
}    

/** 
  @brief Return parity of halved bit weight of the even suboctad

  Here parameter ``u_sub`` is the number of a suboctad. A suboctad
  cooresponds to a subset of an octad of even parity. The function 
  returns 0 is the bit weight of that subset is divisible by four 
  and 1 otherwise.

  The numbering of suboctads is described in the documentation
  of function mat24_suboctad_to_cocode().
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_suboctad_weight(uint32_t u_sub)
{
   uint_fast32_t w = (u_sub & 0x15) + ((u_sub & 0x2a) >> 1);
   w = w + (w >> 2) + (w >> 4) + 1;
   return (w >> 1) & 1; 
}


/** 
  @brief Return scalar product of two suboctads

  The function returns the scalar product of the two suboctads 
  with the numbers ``u_sub1, u_sub2``.  
     
  Here the scalar product is the parity of the vector 
  ``u_sub1 & u_sub2`` when ``u_sub1`` and ``u_sub2`` are given as 
  subsets of an octad in vector notation.
 
  But in this functions parameters ``u_sub1, u_sub2`` are suboctad 
  numbers as documented in function mat24_suboctad_to_cocode().
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_suboctad_scalar_prod(uint32_t u_sub1, uint32_t u_sub2)
{
   uint_fast32_t wp = (0x96 >> ((u_sub1 ^ (u_sub1 >> 3)) & 7)) 
                    & (0x96 >> ((u_sub2 ^ (u_sub2 >> 3)) & 7));
   u_sub1 &= u_sub2;
   wp ^= (0x96 >> ((u_sub1 ^ (u_sub1 >> 3)) & 7));
   return wp & 1;
}


/*************************************************************************
*** Represent a cocode element as a subset of a docecad
*************************************************************************/

/** 
  @brief Represent a cocode element as a subset of a docecad

  Given a Golay cocode element ``c1`` (in ``cocode`` representation)
  and a dodecad ``v1`` (in ``gcode`` representation), the function
  returns a bit vector ``c_out`` equivalent to the cocode word ``c1``,
  which is a subset of the dodecad ``d1``. This is possible if the 
  scalar product of ``c1`` and the complement of ``v1`` is even. 
  Otherwise the function fails.

  The user may specify a bit position ``0 <= u_single < 24`` disjoint
  from the bits of dodecad ``d1``. Then that bit of the return value
  ``c_out`` will be set if the scalar product mentioned above is odd, 
  and the function succeeds also in this case.

  The intersection of ``c_out`` with ``v1`` has bit weight at  most 6. 
  If that bit weight is equal to 6 then ``c_out`` contains the
  least significant bit of the bit vector corresponding to ``v1``. 

  The function fails if ``v1`` is not a dodecad. It
  returns ``(uint32_t)(-1)`` in case of failure.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_cocode_as_subdodecad(uint32_t c1, uint32_t v1, uint32_t u_single)
{
    uint32_t vect1, lsb, syn, res, w;
    uint32_t single = 0;
    static uint8_t pos[20] = 
        {0,1, 0,2, 0,3, 0,4, 1,2, 1,3, 1,4, 2,3, 2,4, 3,4};  
    
    // Fail if ``v1`` is not a dodecad.
    if ((MAT24_THETA_TABLE[v1 & 0x7ff] & 0x1000) == 0) 
        return (uint32_t)(0-1);
    // Let ``vect1`` be the bit vector corresponding to ``v1``.
    vect1 = mat24_def_gcode_to_vect(v1);

    // Try to correct ``c1`` if scalar product of complemented 
    // ``vect1`` and ``c1`` is one.
    if (mat24_scalar_prod(v1 ^ 0x800, c1)) {
        // Try to change the bit of ``c1`` at position ``u_single``.
        // Remember correction in variable ``single``.
        if (u_single >= 24 || (single = 1 << u_single) & vect1)
            return (uint32_t)(0-1);
        // Change bit ``u_single`` in cocode word ``c1``
        c1 ^=  MAT24_RECIP_BASIS[u_single] & 0xfff; 
    }

    // Compute syndrome of cocode element ``c1`` in ``syn``.
    // If syndrome has weight 4, it will intersect with ``vect1``.
    lsb = mat24_def_lsbit24(vect1); // lowest bit of bit vector ``vect1``
    syn = mat24_cocode_syndrome(c1, lsb);
    // Abort if computation of syndrome has failed.
    if (syn & 0xff000000) return  (uint32_t)(0-1);
    // Put ``res = syn & vect1, syn = syn & ~vect1``.
    // So ``res`` is the part of the syndrome already done, and ``syn``
    // is the part of the syndrome yet to be processed.
    res = syn & vect1; syn = syn & ~vect1;


    // Now the unprocessed syndrome ``syn`` has bit weight 0 or 2.
    // If ``syn`` has bit weight 2 we have to find an equivalent
    // bit vector ``c6`` (modulo the Golay code) that is a subset 
    // of ``vect1``. Such a bit vector ``c6`` has always weight 6.
    // Any such bit vector (or its complement) intersects with
    // a fixed subset ``c`` of the dodecad of weight 5 in at least
    // 3 entries. So we construct ``c6`` from ``c`` and ``syn``
    // by completing all sets ``syn ^ c3`` to an octad, where 
    // ``c3`` runs over the subsets of ``c`` of weight 3.
    if (syn) {
        uint32_t i, u0, u1, tab, syn1, c = 0, c6,  p0, p1;
        uint8_t b[24];
        uint32_t coc[5];
        // Now deal with the element ``syn`` of  bit weight 2.
        // Store the i-th entry ``v1[i]`` of docecad ``vect1`` in 
        // ``b[i]``; and store the cocode element corresponding to 
        // that entry in ``coc[i]`` in cocode representation. 
        // Here we drop the parity bit 11 in ``coc[i]``.
        // It suffices to compute the first 5 entries of ``vect1``.
        // We also put ``c = coc[0] ^... , coc[4]`` with ``c`` 
        // stored in vector representation; and we put
        // ``u0 = c ^ syn`` with ``u0`` in cocode representation.
        // So the bit vector corresponding to ``u0`` has weight 7.
        mat24_vect_to_bit_list(vect1, b);
        u0 = mat24_vect_to_cocode(syn) & 0x7ff;
        for (i = 0; i <= 4; ++i) {
            u0 ^= (coc[i] = MAT24_RECIP_BASIS[b[i] & 0x1f] & 0x7ff); 
            c ^= 1 << b[i];
        }

        // For the pairs ``p0, p1`` stored in ``pos`` do the following:
        // Put ``u1 = u0 ^ v1[p0] ^ v1[p1]``, where ``v1[k]`` is the
        // ``k``-th entry of the dodecad ``vect1``. We compute ``u1`` 
        // in cocode representation, dropping the parity bit. Let
        // ``syn1`` be the syndrome of the cocode element ``u1``, which
        // has always bit weight 3. We are successful if ``syn1`` is 
        // a subset of ``vect1``; then we proceed as described below.
        for (i = 0; i < 20; i += 2) {
            p0 = pos[i]; p1 = pos[i+1];
            // Compute syndrome ``syn1`` of ``u1`` as described above.
            u1 = u0 ^ coc[p0] ^ coc[p1]; 
            tab =  MAT24_SYNDROME_TABLE[u1];
            syn1 = mat24_def_syndrome_from_table(tab);
            // Success if ``syn1`` is a subset of ``vect1``.
            if ((syn1 & vect1) == syn1) {
                // Then we compute a bit vector ``c6`` equivalent to
                // ``syn``, such that ``c`` is a subset of ``vect1``.
                c6 = c ^ syn1 ^ (1 << b[p0]) ^ (1 << b[p1]);
                // We add ``c6`` (instead of ``syn``) to ``res`` .
                res ^= c6;
                //  Now we are done and jump to the finalization.
                goto done;
            }           
        }
        // Fail if no suitable syndrome ``syn1`` has been found.
        return (uint32_t)(0-1);
    }
  done:
    // Here we arrive in case of success with result ``res ^ single``.
    // Complement ``res`` inside dodecad ``vect1`` if neccesary. 
    w = mat24_bw24(res);   // bit weight of ``res``
    if (w > 6 || (w == 6 && (res & (1 << lsb)) == 0)) res ^= vect1;
    return res ^ single;
}


/*************************************************************************
*** Parker Loop
*************************************************************************/

/** 
  @brief Returns the theta function for the Parker loop

  Here function ``theta()`` is a quadratic function from the Golay code 
  ``C`` to the cocode ``C*``. Parameter ``v1`` of function ``theta`` 
  is a Golay code word in ``gcode`` representation. The result of 
  the ``theta`` function is returned as a Golay cocode word in 
  ``cocode`` representation.

  The cocycle of the Parker loop is given by:
 
           cocycle(v1, v2) =   mat24_scalar_prod(theta(v1), v2),
         
  where mat24_scalar_prod() computes the scalar product.

  The function evluates the lower 12 bits of ``v1``  only. Thus
  ``v1`` may also be an element of the Parker loop.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_ploop_theta(uint32_t v1)
{
   return MAT24_THETA_TABLE[v1 & 0x7ff] & 0xfff;
}


/** 
  @brief Returns the cocycle of the Parker loop.
 
  Here parameters `v1` and `v2` are Golay code vectors in  ``gcode`` 
  representations or elements of the Parker loop, coded as in 
  function ``mat24_mul_ploop``. Then the Parker  loop product  of 
  ``v1`` and ``v2`` is given by
 
      v1 (*) v2  =  v1 ^ v2 * (-1)**cocycle(v1, v2). 
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_ploop_cocycle(uint32_t v1, uint32_t v2)
{
    uint_fast32_t s;
    s = MAT24_THETA_TABLE[v1 & 0x7ff] & v2 & 0xfff;
    mat24_def_parity12(s);
    return s; 
}

/** 
  @brief Returns the product of two elements of the Parker loop
 
  Here the Parker loop elements ``v1`` and ``v2`` are integers
  coded as follows:

      bit 0,...,11:   a Golay code word in ``gcode`` representation

      bit 12:         Parker loop sign

  The other bis of``v1`` and ``v2`` are ignored.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_mul_ploop(uint32_t v1, uint32_t v2)
{

   return v1 ^ v2 ^ (mat24_ploop_cocycle(v1, v2) << 12);
}


/** 
  @brief Returns a power of an element of the Parker loop
 
  Here ``v1`` is a the Parker loop element coded as in function
  mat24_mul_ploop(). ``u_exp`` is the exponent. The function
  returns the power ``v1 ** exp`` as an element of the Parker loop.

  E.g. mat24_pow_ploop(v1, 3) is the inverse of ``v1``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_pow_ploop(uint32_t v1, uint32_t u_exp)
{
    return (v1 & (0 - (u_exp & 1))) 
      ^ (MAT24_THETA_TABLE[v1 & 0x7ff] & ((u_exp & 2) << 11));
}


/** 
  @brief Return commutator of Golay code words ``v1`` and ``v2``
 
  This is equal to 0 if the intersection of the bit vectors ``v1`` 
  and  ``v2`` has  bit weight 0 mod 4, and equal to 1 is that 
  intersection has bit weight 2 mod 4. Words ``v1`` and ``v2`` 
  must be given in ``gcode``  representation.

  For  Parker loop elements ``v1`` and ``v2`` (coded as in function
  ``mat24_mul_ploop``) the commutator of  ``v1`` and ``v2`` is
  equal to

         (-1) ** mat24_ploop_comm(v1, v2),

  where ``**`` denotes exponentiation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_ploop_comm(uint32_t v1, uint32_t v2)
{   
    uint_fast32_t r;
    r = (MAT24_THETA_TABLE[v1 & 0x7ff] & v2)
      ^ (MAT24_THETA_TABLE[v2 & 0x7ff] & v1);
    mat24_def_parity12(r);
    return r;      
} 


/** 
  @brief Return intersection of two Golay code words as cocode word.
 
  Here ``v1`` and ``v2`` are Golay code words in ``gcode`` 
  representation. The result is a cocode word returned in 
  ``cocode`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_ploop_cap(uint32_t v1, uint32_t v2)

{
    v1 &= 0x7ff; v2 &= 0x7ff;
    return (MAT24_THETA_TABLE[v1]  ^  MAT24_THETA_TABLE[v2] 
              ^ MAT24_THETA_TABLE[v1 ^ v2]) & 0xfff ;
}

/** 
  @brief Return associator of Golay code words ``v1, v2,`` and ``v3``
 
  This is the parity of the intersection of the bit vectors ``v1, v2,`` 
  and ``v3``. So the function returns 0 or 1. Vectors ``v1, v2, v3`` 
  are in ``gcode``  representation.

  The associator of three Parker loop elements ``v1, v2, v3`` is equal 
  to

       (-1) ** mat24_ploop_assoc(v1, v2, v3) .
	   
  Here ``v1, v2, v3`` are encoded as in function mat24_mul_ploop(). 	   
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_ploop_assoc(uint32_t v1, uint32_t v2, uint32_t v3)
{
    uint_fast32_t r;
    r = (MAT24_THETA_TABLE[v1 & 0x7ff] & v3)
      ^ (MAT24_THETA_TABLE[v2 & 0x7ff] & v3)
      ^ (MAT24_THETA_TABLE[(v1 ^ v2) & 0x7ff] & v3);
    mat24_def_parity12(r);
    return r;
}


/** 
  @brief Return cocode element that kills signs of Parker loop elements
  
  Here ``p_io`` refers to an array of ``u_len`` Parker loop elements
  are coded as in function mat24_mul_ploop(). The function tries to 
  find a cocode element that makes all these Parker loop elements 
  positive, when operating on them as a diagonal automorphism. The 
  function returns the least cocode  element in lexical order 
  satisfying that condition in the bits ``0,...,11`` of the return 
  value. For that order we assume that lower bits have higher valence. 
  If no such cocode element  exists, the function fails.
 
  We set bit 12 of the return value to indicate a failure.
 
  The array ``p_io`` is destroyed. More specifically, the first 
  ``k`` entries of that array are changed to an array of linear
  independent Parker loop elements. When these ``k`` elements are
  mapped to positive Parker loop elements, this also yields a
  solution of the original problem. If the problem cannot be 
  solved then we put ``p_io[k-1] = 0x1000``. 
 
  The function returns the value ``k`` in bits ``31,...,16``
  of the result.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_ploop_solve(uint32_t *p_io, uint32_t u_len)
{
    uint_fast32_t col, row, nrows, mask, piv, piv_col[13], res;
    nrows = 0;
    for (col = 0; col <= 12; ++col) {
        mask = 1 << col;
        for (row = nrows; row < u_len; ++row) {
            if (p_io[row] & mask) {
                piv = p_io[row];  
                p_io[row] = p_io[nrows];
                for (row = 0; row < u_len; ++row) {
                    p_io[row] ^= piv & (0UL - ((p_io[row] >> col) & 1)); 
                } 
                p_io[nrows] = piv;
                piv_col[nrows++] = col;
                break;
            }
        }
    }
    res = 0;
    for (row = 0; row < nrows; ++row) {
        res |= ((p_io[row] >> 12) & 1) << piv_col[row];
    }
    return res + (nrows << 16);  
}



/*************************************************************************
*** Mathieu group Mat24
*************************************************************************/


/// @cond DO_NOT_DOCUMENT

// Return the same result as function mat24_syndrome(x, 24).
// But this is faster and works for vectors x with odd
// parity only.
static inline uint_fast32_t odd_syn(uint_fast32_t x) {
    x = MAT24_ENC_TABLE0[(x) & 0xff] 
      ^ MAT24_ENC_TABLE1[((x) >> 8) & 0xff]  
      ^ MAT24_ENC_TABLE2[((x) >> 16) & 0xff];
    x = MAT24_SYNDROME_TABLE[(x) & 0x7ff]; 
    return  mat24_def_syndrome_from_table(x);
}

#define lsb24(x) ((uint8_t)(mat24_def_lsbit24_pwr2(x)))

/// @endcond


/** 
  @brief Complete permutation in the Mathieu group ``Mat24`` from 7 images

  This is an auxilary function for function mat24_perm_from_heptads().
  We use the terminology introduced in that function.

  The function completes the array ``p_io`` to a permutation ``p``
  in the Mathieu group ``Mat24``. On output, permutation ``p`` is 
  given as a mapping ``i -> p_io[i]`` for ``i = 0,...,23``.

  On input, the images ``p_io[i]`` must be given for 
  ``i = 0,1,2,3,4,5,8``; the other entries of ``p_io`` are ignored.

  The set ``(p_io[i], i = 0,1,2,3,4,5,8)`` must be an umbral heptad 
  with distiguished element ``p_io[8]``. Then the mapping
  ``i -> p_io[i], i = 0,1,2,3,4,5,8`` is a feasible mapping between 
  umbral heptads; it extends to a unique permutation in ``Mat24``.
  Note that ``8`` is the distingished element of the umbral heptad
  ``(0,1,2,3,4,5,8)``. 

  The function returns 0 if the mapping given on input can be
  extended to an element of ``Mat24``, and a nonzero value
  otherwise.

  Implementation idea:

  We choose pentads, i.e. subsets of size 5 of the set ``(0,....,23)``
  that consist of known values ``p_io[i]``. We calculate the syndromes
  of such pentads, which are triads, i.e. sets of size three. 
  Calculating the syndromes of the preimages of these pentads we obtain 
  mappings between triads. Intersecting triads in a suitable way we 
  obtain mappings between singletons, and hence peviously unknown 
  images of elements of the set ``(0,....,23)``.
*/

// %%EXPORT p
MAT24_API
uint32_t mat24_perm_complete_heptad(uint8_t *p_io)
{
    // This implementation is (almost) a copy of the 
    // implementation of the corresponding python function
    // mmgroup.dev.mat24.mat24heptad.mat24_complete_heptad().
    uint_fast32_t  err, s1, s5, s015, s3, s4, s8, s01234; 
    uint_fast32_t  s567, s67, s9AB, s9CD, s9, s6GH, s6;
    uint_fast32_t  sACE, sD, sFGI, sG, sFJK, sJLM, sALN;

    err = ((p_io[0] + 8) | (p_io[1] + 8) | (p_io[2] + 8) | 
      (p_io[3] + 8) | (p_io[4] + 8) | (p_io[5] + 8) | (p_io[8] + 8));
    err &= (0 - 0x20);
    s1 = 1 << p_io[1]; 
    s5 = 1 << p_io[5];
    s015 = (1 << p_io[0]) ^ s1 ^ s5;
    s3 = 1 << p_io[3]; 
    s4 = 1 << p_io[4]; 
    s8 = 1 << p_io[8];
    s01234 = s015 ^ s5 ^ (1 << p_io[2]) ^ s3 ^ s4;
    // if err == 0 then 0 <= s01234 < 0x1000000 has odd parity
    // octad = [0, 1, 2, 3, 4, 5, 6, 7]
    s567 = odd_syn(s01234);
    err |= (s01234) & s567;
    // if err == 0 then entries [0,1,2,3,4,6] are in an octad
    err |= (s01234 | s567) & s8;
    // if err == 0 then entry 8 is not in that octad
    err |= s5 ^ (s5 & s567);
    s67 = s567 & ~s5;
    // octad = [0, 1, 2, 3, 8, 9, 10, 11]
    s9AB = odd_syn(s01234 ^ s4 ^ s8);
    // octad = [0, 1, 4, 5, 8, 9, 12, 13]
    s9CD = odd_syn(s015 ^ s4 ^ s8);
    s9 = s9AB & s9CD;
    p_io[9] = lsb24(s9);
    // octad [1, 3, 5, 6, 8, 9, 16, 17]
    s6GH = odd_syn(s1 ^ s3 ^  s5 ^ s8 ^ s9);
    s6 = s67 &  s6GH;
    p_io[6] = lsb24(s6);
    p_io[7] = lsb24(s67 & ~s6GH);
    // still needed: 
    //   err, s1, s015, s3, s8, s01234, s9AB, s9CD, s9, s6GH, s6
    // octad [0, 2, 4, 6, 8, 10, 12, 14]
    sACE = odd_syn(s01234 ^ s1 ^ s3 ^ s6 ^ s8);
    p_io[10] = lsb24(s9AB & sACE);
    p_io[11] = lsb24(s9AB & ~sACE & ~s9);
    p_io[12] = lsb24(s9CD & sACE);
    sD = s9CD & ~sACE & ~s9;
    p_io[13] = lsb24(sD);
    p_io[14] = lsb24(sACE & ~s9AB & ~s9CD);
    // still needed: 
    //   err, s1, s015, s3, s8, s6GH, s6, sACE, sD
    // octad [0, 1, 5, 6, 13, 15, 16, 18]
    sFGI = odd_syn(s015 ^ s6 ^ sD);
    sG = s6GH & sFGI;
    p_io[16] = lsb24(sG);
    p_io[17] = lsb24(s6GH & ~s6 & ~sFGI);
    // octad [0, 1, 3, 5, 8, 15, 19, 20]
    sFJK = odd_syn(s015 ^ s3 ^ s8);
    p_io[15] = lsb24(sFGI & sFJK);
    p_io[18] = lsb24(sFGI & ~sG & ~sFJK);
    // octad [0, 3, 5, 6, 16, 19, 21, 22]
    sJLM = odd_syn(s015 ^ s1 ^ s3 ^ s6 ^ sG);
    p_io[19] = lsb24(sFJK & sJLM);
    p_io[20] = lsb24(sFJK & ~sFGI & ~sJLM);
    // octad [0, 1, 5, 6, 8, 10, 21, 23]
    sALN = odd_syn(s015 ^ s6 ^ s8); 
    p_io[21] = lsb24(sALN & sJLM);
    p_io[22] = lsb24(sJLM & ~sALN & ~sFJK);
    p_io[23] = lsb24(sALN & ~sACE & ~sJLM);
    return err;
}


/**
  @brief Check if permutation is in in the Mathieu group ``Mat24``.

  The function checks the mapping ``i -> p1[i]``, ``i = 0,...,23``. 

  It returns zero if that mapping is a permutation in ``Mat24`` 
  and a nonzero value otherwise.

  The implementation uses function mat24_perm_complete_heptad().
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_perm_check(uint8_t *p1)
{
    uint8_t p2[24];
    memcpy(p2, p1, 9*sizeof(uint8_t));
    return mat24_perm_complete_heptad(p2) || memcmp(p1, p2, 24);
}        

/**
  @brief Complete an octad given by 6 elements of it. 

  Given entries ``p_io[i], i = 0,1,2,3,4,5``, we calculate values
  ``p_io[6], p_io[7]`` such that the set ``(p_io[i], 0 <= i < 8)`` 
  is an octad. Furthermore, we order the values ``p_io[6], p_io[7]`` 
  in such way that the mapping ``i -> p_io[i]`` may be extended to a 
  permutation in the grpup ``Mat24``. This restrtiction determines
  the order uniquely. Note that the set ``0,...,7`` is an octad,
  which is called the standard octad.

  The set ``p_io[i], i = 0,1,2,3,4,5`` must be a subset of an
  octad; otherwise the function fails. The function returns 0
  in case of success and ``(uint32_t)(-1)`` in case of failure.

  The implementation is a simplified version of function
  mat24_perm_complete_heptad().
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_perm_complete_octad(uint8_t *p_io)
{
    uint_fast32_t  err, s1, s5, s015, s3, s4, s8, s01234; 
    uint_fast32_t  s567, s67, s9AB, s9CD, s9, s6GH, s6;

    err = ((p_io[0] + 8) | (p_io[1] + 8) | (p_io[2] + 8) | 
      (p_io[3] + 8) | (p_io[4] + 8) | (p_io[5] + 8));
    err &= (0 - 0x20);
    s1 = 1 << p_io[1]; 
    s5 = 1 << p_io[5];
    s015 = (1 << p_io[0]) ^ s1 ^ s5;
    s3 = 1 << p_io[3]; 
    s4 = 1 << p_io[4]; 
    s01234 = s015 ^ s5 ^ (1 << p_io[2]) ^ s3 ^ s4;
    // if err == 0 then 0 <= s01234 < 0x1000000 has odd parity
    // octad = [0, 1, 2, 3, 4, 5, 6, 7]
    s567 = odd_syn(s01234);
    // Put s8 = 1 << u, with u the smallest entry not in the octad
    s8 = 0xffffff ^ (s01234 | s567);
    s8 = s8 & (0 - s8);   
    err |= (s01234) & s567;
    // if err == 0 then entries [0,1,2,3,4,6] are in an octad
    err |= s5 ^ (s5 & s567);
    s67 = s567 & ~s5;
    // octad = [0, 1, 2, 3, 8, 9, 10, 11]
    s9AB = odd_syn(s01234 ^ s4 ^ s8);
    // octad = [0, 1, 4, 5, 8, 9, 12, 13]
    s9CD = odd_syn(s015 ^ s4 ^ s8);
    s9 = s9AB & s9CD;
    // octad [1, 3, 5, 6, 8, 9, 16, 17]
    s6GH = odd_syn(s1 ^ s3 ^  s5 ^ s8 ^ s9);
    s6 = s67 &  s6GH;
    p_io[6] = lsb24(s6);
    p_io[7] = lsb24(s67 & ~s6GH);
    return err ? (0 - 1) : 0;
}



/** 
  @brief Complete a mapping to a permutation in the Mathieu group ``Mat24``

  A permutation in the  Mathieu group ``Mat24`` is a mapping  from the
  set ``(0,...,23)`` to itself.  The function completes the  mapping 
  ``h1[i] -> h2[i]``, ``0 <= i < 7``, ``0 <= h1[i], h2[i] < 24`` to
  a permutation ``i -> p_out[i]``, ``0 <= i < 24`` in the 
  group ``Mat24``. The result is returned in the array ``p_out[i]``.

  The sets ``h1[i], 0 <= i < 7`` and ``h2[i], 0 <= i < 7`` must be
  umbral heptads, and the mapping from ``h1`` to ``h2`` must be
  feasible.

  An umbral heptad is a set of seven elements of the set ``(0,...,23)``
  which is not a subset of an octad. The syndrome of an umbral heptad, 
  i.e. the smallest set equivalent to the heptad  modulo the Golay code, 
  is a singleton containing exactly one element of the umbral heptad. 
  That element is called the distiguished element of the heptad. 
  A feasible mapping from an umbral heptad to another umbral heptad is
  a mapping that maps the distiguished element of the first heptad to
  the distiguished element of the second heptad.

  It can be shown that a feasible mapping from an umbral heptad to 
  another umbral heptad extends to a unique element of the Mathieu 
  group. 

  The function returns 0 if the mapping ``h1[i] -> h2[i]`` can be
  extended to an element of ``Mat24`` and ``(uint32_t)(-1)``
  otherwise.

  The implementation uses function mat24_perm_complete_heptad().
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_perm_from_heptads(uint8_t *h1, uint8_t *h2, uint8_t *p_out)
{
    uint8_t p1[24], p2[24];
    uint_fast32_t v, y, i;
 
    // First find the special element v of h1 not contained in the octad
    v = 0;
    for (i = 0; i < 7; ++i)  v |= 1 << (h1[i] & 31);

    // Put y = mat24_syndrome(v).
    y = MAT24_ENC_TABLE0[v & 0xff]
           ^ MAT24_ENC_TABLE1[(v >> 8) & 0xff]
           ^ MAT24_ENC_TABLE2[(v >> 16) & 0xff];
    y = MAT24_SYNDROME_TABLE[y & 0x7ff];
    y =  mat24_def_syndrome_from_table(y);  
    
    // Put v = lsbit(v & y). Then v is the special element of h1
    v &= y; 
    v =  mat24_def_lsbit24(v); 
  
    // Find position y of element v in h1
    y = 0; 
    for (i = 0; i < 7; ++i)   y |= ((h1[i] != v) - 1) & i;

    // Copy special element of h1 to position 8 of p1 and copy the other
    // elements of h1 to positions 0,...,6. Copy h2 similarly to p2
    memcpy(p1, h1, 7*sizeof(uint8_t));
    memcpy(p2, h2, 7*sizeof(uint8_t));
    p1[8] = p1[y];   p1[y] = p1[6];
    p2[8] = p2[y];   p2[y] = p2[6];

    // Complete p1 and p2 from heptad. Return error if any completion fails
    if (mat24_perm_complete_heptad(p1) |
          mat24_perm_complete_heptad(p2)) return (uint32_t)(-1);

    //  If success, put p = p1**(-1) * p2
    for (i = 0; i < 24; ++i)  p_out[p1[i]] = p2[i];
    return 0;
}        




/// @cond DO_NOT_DOCUMENT 

static inline void insertsort_i8(uint8_t *a1, uint8_t *a2, int32_t n)
// Sort the array ``a1`` of length ``n``.
// Perform the same permutation on the array ``a2`` as on ``a1``
{
    int_fast32_t i, j;
    for (i = 1; i < n; i += 1) {
        uint_fast8_t temp1 = a1[i], temp2 = a2[i];
        for (j = i; j >= 1 && a1[j - 1] > temp1; --j) {
            a1[j] = a1[j - 1]; a2[j] = a2[j - 1];
        }
        a1[j] = temp1;  a2[j] = temp2;
    }
}

/* Extend mapping from an umbral hexad ``h1`` to ``h2``

The function appends one entry to ``h1`` and one entry to ``h2`` so
that ``h1`` and ``h2`` will be umbral heptads, with ``h2`` an image
of ``h1`` under ``Mat24``. It computes the pair ``h1, h2`` that leads
to the least possible permutation in ``Mat24`` in lexical order.

Inputs ``bm1`` and ``bm2`` are the bitmaps of ``h1`` and ``h2``;
they have already been computed by the calling procedure.
*/
static inline void extend_umbral_hexad(
    uint8_t *h1,  uint8_t *h2, uint32_t bm1, uint32_t bm2
)
{
    uint_fast8_t src, img = 24, j;
    // Let src be the smallest entry not in h1; put h1[6] = src
    h1[6] = src = mat24_def_lsbit24(~bm1);
    // Complete ``bm1`` to a heptad; this heptad must be umbral
    bm1 |= (1UL << src); 

    // Obtain the special element of that umbral heptad
    // Store the singleton containing that element in ``bm1``
    bm1 &= mat24_syndrome(bm1, 0);
    // Obtain the image of that special element in ``img``
    for (j = 0; j < 6; ++j) if ((1UL << h1[j]) == bm1) img = h2[j];
  
    // Delete image of that special element from bm2
    bm2 &= ~(1UL << img);
    // Compute syndrome of modified ``bm2`` in ``bm2``.
    bm2 = mat24_syndrome(bm2, 0);
    // The image of ``src`` must lie in that syndrome
    // Store first element of that syndrome in h2[6]
    h2[6] = mat24_def_lsbit24(bm2);  
}


/// @endcond



/** 
  @brief Complete a mapping to a permutation in the Mathieu group ``Mat24``

  A permutation in the  Mathieu group ``Mat24`` is a mapping  from the
  set ``(0,...,23)`` to itself.  The function tries to complete the
  mapping ``h1[i] -> h2[i]``, ``0 <= i < n``, ``0 <= h1[i], h2[i] < 24``
  to a permutation ``i -> p_out[i]``, ``0 <= i < 24`` in the Mathieu
  group ``Mat24``. In case of success, such a permutation is stored in
  the array ``p_out``.

  The function returns

  -1 if the mapping ``h1[i] -> h2[i]`` does not extend to a legal
  permutation of the numbers 0,...,23. Note that duplicate entries
  in ``h1`` or ``h2`` are illegal.

  0  if no such permutation exists in the Mathieu group ``Mat24``.

  1  if the mapping ``h1[i] -> h2[i]`` extends to a unique permutation
  in ``Mat24``.

  2 if if the mapping ``h1[i] -> h2[i]`` can be completed to several
  permutations in ``Mat24``, and not all entries ``h1[i]`` can be
  covered by an octad. This may happen in case ``n = 6`` only.

  3 if if the mapping ``h1[i] -> h2[i]`` can be completed to several
  permutations in ``Mat24``, and all entries ``h1[i]`` can be
  covered by an octad.

  If the return value is greater then zero then a suitable permutation
  in ``Mat24`` is returned in the array referred by ``p_out``. The
  function computes the lowest permutation (in lexical order) that 
  maps ``h1`` to ``h2`.

  Caution:

  Some input mappings allow several output permutations. Changing the
  specification of this function such that the same input leads to
  a different output permutation destroys the interoperability between
  different versions of the project!!
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_perm_from_map(uint8_t *h1, uint8_t *h2, uint32_t n, uint8_t *p_out)
{
    uint_fast32_t err, bm1, bm2, i, o1, o2, i8, i16;
    uint8_t p1[32], p2[32], t;
    int32_t res;

    // Check for errors. We reject duplicate entries in any of the 
    // arrays ``h1`` or ``h2``, and also enries >= 24.
    // Compute the bitmap of the entries in ``h1`` in ``bm1``,
    // and the bitmap of the entries in ``h2`` in ``bm2``.
    err = 0 - (n > 24);
    bm1 = bm2 = 0;
    if (err == 0) for (i = 0; i < n; ++i) {
        err |= (h1[i] + 8) | (h2[i] + 8);
        bm1 |= 1UL << h1[i]; 
        bm2 |= 1UL << h2[i];
    }
    if (err & (0-32) || mat24_bw24(bm1) != n || mat24_bw24(bm2) != n) {
        for (i = 0; i < 24; ++i) p_out[i] = 24;
        return (uint32_t)(-1); 
    }
    
    // Copy ``h1`` to ``p1`` and ``h2`` to ``p2``. In case ``n < 9``
    // we sort the copy ``p1`` of ``h1`` and permute ``p2``
    // correspondingly, so that the permutation depends on the 
    // mapping ``h1 -> h2`` only. In case ``n >= 9`` there is at
    // most one feasible permutation in ``Mat24``.
    // In case ``n < 5`` we append entries (with lowest possible 
    // values in natural order) to  ``p1`` and ``p2`` so that both 
    // lists will have length at least 5.  
    if (n < 5) {
        mat24_vect_to_bit_list(bm1, p1);
        mat24_vect_to_bit_list(bm2, p2);
    }
    for (i = 0; i < n; ++i) {
        p1[i] = h1[i];
        p2[i] = h2[i];
    }
    if (n < 9) insertsort_i8(p1, p2, n);

    // Store the bit vectors containing the first five entries
    // of ``p1`` in ``bm1``.
    bm1 = bm2 = 0;
    for (i = 0; i < 5; ++i)  bm1 |= 1UL << p1[i]; 
    for (i = 0; i < 5; ++i)  bm2 |= 1UL << p2[i]; 

    // Store the (unique) octads containing the first five entries 
    // of ``p1`` and ``p2`` in ``bm1`` and ``bm2``, respectively.
    o1 = bm1 | mat24_syndrome(bm1, 0);
    o2 = bm2 | mat24_syndrome(bm2, 0);

    // Try to find an index ``i8 >= 5`` such that ``p1[i8]`` is in
    // the octad ``o1``. Try to find an index ``i16 >= 5`` such 
    // that ``p1[i16]`` is not in the octad ``o1``.
    // Index ``i8 == 24`` means 'no entry found'.
    // Index ``i16 == 25 means`` 'no entry found'.
    // If no entry has ben found the we will later put some entry
    // into  ``p1[i8]`` or ``p1[i16]``.
    i8 = 24;  // This is a rather bad index
    i16 = 25;  // This is a rather bad index
    for (i = 5; i < n; ++i) {
        if ((1UL << p1[i]) & o1) i8 = (i8 == 24) ? i : i8;
        else i16 = (i16 == 25) ? i : i16;
    }

    // Compute return value (in case of success) from i8 and i16
    if (i16 == 25) res = 3; // everything is in the octad ``o1``.
    else res = 1 + (i8 == 24 && n < 7);

    // In the next step we compute a set of size 7
    // in ``p1[0], p1[1], p1[2], p1[3], p1[4], p1[i8], p1[i16].
    // We have ``i16 == 25`` iff that set has size 6. The images of 
    // the entries of that set are in the corresponding entries 
    // of ``p2``. If several images are possible the we store an 
    // image that extends to the lexically lowest possible image of
    // the complete set ``h1``, provided that such an image exists. 
    // The computed set is eiterh a hexad that completes to an octad
    // or an umbral heptad. A permutation in ``Mat24`` is uniquely
    // determined by the image of an umbral heptad.
       
    // If no index ``i8`` found then:
    //    if n < 7 then take entries from the syndromes of 
    //    the first five entries of ``p1`` and ``p2``;
    //    otherwise just put ``i8 = 5, i16 = 6``.
    if (i8 == 24) {
        if (n == 6) {
            // This case is so tricky that we need an extra function.
            // First compute bitmaps of ``h1, h2`` in ``bm1, bm2``.
            bm1 |= 1UL << p1[5]; bm2 |= 1UL << p2[5]; 
            extend_umbral_hexad(p1, p2, bm1, bm2);
            i8 = 5; i16 = 6;
        } else if (n < 6)  {
            bm1 ^= o1;  bm2 ^= o2;  // compute symdromes
            p1[24] = mat24_def_lsbit24(bm1);
            p2[24] = mat24_def_lsbit24(bm2);
        } else {
            i8 = 5; i16 = 6;
        }
    }

    // If no index ``i16`` found then take entries from the 
    // complements of the octads  ``o1`` and o2.
    if (i16 == 25) {
        o1 = ~o1;  o2 = ~o2; // complement octads o1 and o2
        p1[25] =  mat24_def_lsbit24(o1);
        p2[25] =  mat24_def_lsbit24(o2);
    }
    // Copy entries at positions ``i8`` and ``i16`` 
    // of ``h1`` and ``h2`` to positions 5 and 6.
    t = p1[i16]; p1[5] = p1[i8]; p1[6] = t;
    t = p2[i16]; p2[5] = p2[i8]; p2[6] = t;

    // Compute ``p_out`` from ``p1[0,...,6]`` and ``p2[0,...,6]``
    // Return 0 if this fails
    if (mat24_perm_from_heptads(p1, p2, p_out)) {
        // For debugging
        for (i = 0; i < 8; ++i) {
            p_out[i] = p1[i]; p_out[i+8] = p2[i];
        }
        p_out[16] = (uint8_t)i8;  p_out[16] = (uint8_t)i16;         
        p_out[18] = p1[24]; p_out[19] = p1[25];
        p_out[20] = p2[24]; p_out[21] = p2[25];
        p_out[22] = 0xca; p_out[23] = 0xfe;
        return 0;
    }    
 
    // Check that permutation ``p_out`` really maps ``h1`` to ``h2``.
    // Return 0 if this check fails.
    err = 0;
    for (i = 0; i < n; ++i) err |= p_out[h1[i]] ^ h2[i];
    if (err)  return 0;

    // Otherwise we are successful and return ``res``.
    return res;    
}



/// @cond DO_NOT_DOCUMENT
#define SH 58ULL
#define FACTOR24 (24ULL * ((1ULL << SH) / MAT24_ORDER + 1ULL))
#define DFIELD1 0x555555555555ULL
/// @endcond

/**
  @brief Compute permutation in the Mathieu group ``Mat24`` from its number

  The Mathieu group has order ``244823040``. We assign numbers
  ``0 <= n < 244823040`` to the elements of ``Mat24``, in
  lexicographic order, with ``0`` the number of the neutral element. 
  This is just a convenient way to refer to an element of ``Mat24``. 

  The function calculates the permutation with the number ``u_m24``
  and stores it in the array ``p_out`` as a mapping
  ``i -> p_out[i]``. ``0 <= u_m24 < 244823040`` must hold;
  otherwise the function fails.

  The function returns 0 in case of success and ``(uint32_t)(-1)``
  in case of failure. 
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_m24num_to_perm(uint32_t u_m24, uint8_t *p_out)
{
    // This implementation is equivalent to the python function
    // mmgroup.dev.mat24.mat24heptad.mat24_int_to_perm 
    // Documentation is given in that python function.

    uint64_t n1, d, mask;
    uint_fast32_t k, bitmap, last, cocode, syn, j, res;
    uint8_t p1[32]; 

    res = 0 - (u_m24 >= MAT24_ORDER); // This is the return value
    u_m24 &= ~res;                    // Change an illegal input to 0
      
    n1 = FACTOR24 * u_m24;
    k = (uint_fast32_t)(n1 >> SH);
    p_out[0] = (uint8_t)k;
    n1 -= (uint64_t)k << SH;
    bitmap = 1UL << k;
    d = DFIELD1 << (2*k);

    // %%FOR i in [23, 22, 21]
        n1 = 23 * n1;
        k = (uint_fast32_t)(n1 >> SH);
        n1 &= (1ULL << SH) - 1;
        j = k + ((d >> (2*k)) & 3);
        p_out[24-23] = (uint8_t)j;
        mask = (1ULL << (2*k)) - 1;
        d = (((d + DFIELD1) >> 2) & ~mask) + (d & mask); 
        bitmap |= 1UL << j; 
        n1 = 22 * n1;
        k = (uint_fast32_t)(n1 >> SH);
        n1 &= (1ULL << SH) - 1;
        j = k + ((d >> (2*k)) & 3);
        p_out[24-22] = (uint8_t)j;
        mask = (1ULL << (2*k)) - 1;
        d = (((d + DFIELD1) >> 2) & ~mask) + (d & mask); 
        bitmap |= 1UL << j; 
        n1 = 21 * n1;
        k = (uint_fast32_t)(n1 >> SH);
        n1 &= (1ULL << SH) - 1;
        j = k + ((d >> (2*k)) & 3);
        p_out[24-21] = (uint8_t)j;
        mask = (1ULL << (2*k)) - 1;
        d = ((d >> 2) & ~mask) + (d & mask); 
        last = k;
        bitmap |= 1UL << j; 
    //%%END FOR

    n1 = 20 * n1;
    k = (uint_fast32_t)(n1 >> SH);
    n1 &= (1ULL << SH) - 1;
    j = k + ((d >> (2*k)) & 3) + (k >= last);
    p_out[4] = (uint8_t)j;
    bitmap |= 1UL << p_out[4]; 

    // Store cocode of bitmap in variable 'cocode'
    cocode = MAT24_ENC_TABLE0[bitmap & 0xff]
           ^ MAT24_ENC_TABLE1[(bitmap >> 8) & 0xff]
           ^ MAT24_ENC_TABLE2[(bitmap >> 16) & 0xff];
    // Store syndrome of bitmap in 'syn'
    syn = MAT24_SYNDROME_TABLE[cocode & 0x7ff];

    k = (uint_fast32_t)((3 * n1) >> SH);
    j = (syn >>  (5 * k)) & 31; 
    p_out[5] = (uint8_t)j;

    bitmap |= mat24_def_syndrome_from_table(syn);
    bitmap ^= 0xffffff;  

    // Compute list of entries j with bitmap[j] = 1 in the array p1
    j = 0;
    // %%FOR i in range(24)
        p1[j] = 0;              // write index 0 to output pos.
        j += (bitmap >> 0) & 1; // increment output pos. if bitmap[0]=1
        p1[j] = 1;              // write index 1 to output pos.
        j += (bitmap >> 1) & 1; // increment output pos. if bitmap[1]=1
        p1[j] = 2;              // write index 2 to output pos.
        j += (bitmap >> 2) & 1; // increment output pos. if bitmap[2]=1
        p1[j] = 3;              // write index 3 to output pos.
        j += (bitmap >> 3) & 1; // increment output pos. if bitmap[3]=1
        p1[j] = 4;              // write index 4 to output pos.
        j += (bitmap >> 4) & 1; // increment output pos. if bitmap[4]=1
        p1[j] = 5;              // write index 5 to output pos.
        j += (bitmap >> 5) & 1; // increment output pos. if bitmap[5]=1
        p1[j] = 6;              // write index 6 to output pos.
        j += (bitmap >> 6) & 1; // increment output pos. if bitmap[6]=1
        p1[j] = 7;              // write index 7 to output pos.
        j += (bitmap >> 7) & 1; // increment output pos. if bitmap[7]=1
        p1[j] = 8;              // write index 8 to output pos.
        j += (bitmap >> 8) & 1; // increment output pos. if bitmap[8]=1
        p1[j] = 9;              // write index 9 to output pos.
        j += (bitmap >> 9) & 1; // increment output pos. if bitmap[9]=1
        p1[j] = 10;              // write index 10 to output pos.
        j += (bitmap >> 10) & 1; // increment output pos. if bitmap[10]=1
        p1[j] = 11;              // write index 11 to output pos.
        j += (bitmap >> 11) & 1; // increment output pos. if bitmap[11]=1
        p1[j] = 12;              // write index 12 to output pos.
        j += (bitmap >> 12) & 1; // increment output pos. if bitmap[12]=1
        p1[j] = 13;              // write index 13 to output pos.
        j += (bitmap >> 13) & 1; // increment output pos. if bitmap[13]=1
        p1[j] = 14;              // write index 14 to output pos.
        j += (bitmap >> 14) & 1; // increment output pos. if bitmap[14]=1
        p1[j] = 15;              // write index 15 to output pos.
        j += (bitmap >> 15) & 1; // increment output pos. if bitmap[15]=1
        p1[j] = 16;              // write index 16 to output pos.
        j += (bitmap >> 16) & 1; // increment output pos. if bitmap[16]=1
        p1[j] = 17;              // write index 17 to output pos.
        j += (bitmap >> 17) & 1; // increment output pos. if bitmap[17]=1
        p1[j] = 18;              // write index 18 to output pos.
        j += (bitmap >> 18) & 1; // increment output pos. if bitmap[18]=1
        p1[j] = 19;              // write index 19 to output pos.
        j += (bitmap >> 19) & 1; // increment output pos. if bitmap[19]=1
        p1[j] = 20;              // write index 20 to output pos.
        j += (bitmap >> 20) & 1; // increment output pos. if bitmap[20]=1
        p1[j] = 21;              // write index 21 to output pos.
        j += (bitmap >> 21) & 1; // increment output pos. if bitmap[21]=1
        p1[j] = 22;              // write index 22 to output pos.
        j += (bitmap >> 22) & 1; // increment output pos. if bitmap[22]=1
        p1[j] = 23;              // write index 23 to output pos.
        j += (bitmap >> 23) & 1; // increment output pos. if bitmap[23]=1
    // %%END FOR 

    j = p1[u_m24 & 15];  
    p_out[8] = (uint8_t)j;

    // Now entries at pos. 0,1,2,3,4,5,8 are valid. Use
    // mat24_perm_complete_heptad() to compute the remaining entries
    mat24_perm_complete_heptad(p_out);
    return res;
}







/**
  @brief Compute number of a permutation in the Mathieu group ``Mat24``

  This is the inverse of function mat24_m24num_to_perm(). 

  Given a permutation ``i -> p1[i], 0 <= i < 24``, the function
  returns the number ``n`` of that permutation. We have 
  ``0 <= n < 244823040``, as described in function 
  ``mat24_int_to_perm``.

  The function returns garbage if ``p1`` is not a valid permutation
  in ``Mat24``. One may use function mat24_perm_check() to check
  if permutation ``p1`` is in ``Mat24``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_perm_to_m24num(uint8_t  *p1)
{
    // This implementation is equivalent to the python function
    // mmgroup.dev.mat24.mat24heptad.mat24_perm_to_int 
    // Documentation is given in that python function.

    uint64_t d;
    uint_fast32_t n, k, bitmap, last, cocode, syn, syn1;

    n = k = p1[0];
    bitmap = 1 << k;
    d = DFIELD1  << (2*k);
    // %%FOR i in [23, 22, 21]
        k = p1[24-23];
        n = 23 * n + k - (uint_fast32_t)((d >> (2*k)) & 3);
        bitmap |= 1 << k;
            d += DFIELD1 << (2*k);
        k = p1[24-22];
        n = 22 * n + k - (uint_fast32_t)((d >> (2*k)) & 3);
        bitmap |= 1 << k;
            d += DFIELD1 << (2*k);
        k = p1[24-21];
        n = 21 * n + k - (uint_fast32_t)((d >> (2*k)) & 3);
        bitmap |= 1 << k;
            last = k;
    // %%END FOR

    k = p1[4];
    bitmap |= 1 << k;
    n = 20 * n + k - (uint_fast32_t)((d >> (2*k)) & 3) - (k >= last);

    // Store cocode of bitmap in variable 'cocode'
    cocode = MAT24_ENC_TABLE0[bitmap & 0xff]
           ^ MAT24_ENC_TABLE1[(bitmap >> 8) & 0xff]
           ^ MAT24_ENC_TABLE2[(bitmap >> 16) & 0xff];
    // Store syndrome of bitmap in 'syn'
    syn = MAT24_SYNDROME_TABLE[cocode & 0x7ff];

    syn1 = (syn >> 5) & 31;
    k = (p1[5] > syn1) + (p1[5] >= syn1);
    n = 3 * n + k;

    bitmap |= (1 << (syn & 31)) | (1 << syn1)
           |  (1 << ((syn >> 10) & 31));

    k = ((1 << p1[8]) - 1) & bitmap;
    // Compute the bit weight of the k in k. This is at most 8    
    k = (k & 0x555555) + ((k & 0xaaaaaa) >> 1); 
    k = (k & 0x333333) + ((k & 0xcccccc) >> 2);
    k = k + (k >> 4);
    k = (k + (k >> 8) + (k >> 16)) & 0x0f; 

    n = 16 * n + p1[8] - k;
    return n & ((n >= MAT24_ORDER) - 1); 
}
            
/// @cond DO_NOT_DOCUMENT
#undef SH 
#undef FACTOR24
#undef DFIELD1
/// @endcond




/**
  @brief Convert permutation in the Mathieu group ``Mat24`` to bit matrix

  The input of the function is the permutation ``p: i -> p1[i]``,
  ``0 <= i < 24`` which must be in the Mathieu group ``Mat24``.

  The function computes a ``12 times 12`` bit matrix ``m``, acting 
  on  a Golay code vector ``v`` (in ``gcode`` representation) by right 
  multiplication. Then we have ``v * m = p(v)``. Bit ``m[i,j]`` is
  stored in bit ``j`` of the the integer ``m_out[i]``.

  Output ``m_out[i], 0 <= i < 12`` contains garbage if ``p`` is not
  in ``Mat24``.

  Implementation idea:

  In the standard basis of ``GF(2)**24``, that operation corresponds
  to a permutation. We have precomputed a matrix converting that
  standard basis to an internal basis, where Golay code words are
  visible, and also the inverse of that matrix. Thus the operation
  is just an (optimized) sequence of matrix multiplications.
*/
// %%EXPORT p
MAT24_API
void mat24_perm_to_matrix(uint8_t  *p1, uint32_t *m_out)
{
    uint32_t a[24]; 
    // %%FOR i in range(24)
        a[0] = MAT24_RECIP_BASIS[p1[0] & 0x1f] >> 12;
        a[1] = MAT24_RECIP_BASIS[p1[1] & 0x1f] >> 12;
        a[2] = MAT24_RECIP_BASIS[p1[2] & 0x1f] >> 12;
        a[3] = MAT24_RECIP_BASIS[p1[3] & 0x1f] >> 12;
        a[4] = MAT24_RECIP_BASIS[p1[4] & 0x1f] >> 12;
        a[5] = MAT24_RECIP_BASIS[p1[5] & 0x1f] >> 12;
        a[6] = MAT24_RECIP_BASIS[p1[6] & 0x1f] >> 12;
        a[7] = MAT24_RECIP_BASIS[p1[7] & 0x1f] >> 12;
        a[8] = MAT24_RECIP_BASIS[p1[8] & 0x1f] >> 12;
        a[9] = MAT24_RECIP_BASIS[p1[9] & 0x1f] >> 12;
        a[10] = MAT24_RECIP_BASIS[p1[10] & 0x1f] >> 12;
        a[11] = MAT24_RECIP_BASIS[p1[11] & 0x1f] >> 12;
        a[12] = MAT24_RECIP_BASIS[p1[12] & 0x1f] >> 12;
        a[13] = MAT24_RECIP_BASIS[p1[13] & 0x1f] >> 12;
        a[14] = MAT24_RECIP_BASIS[p1[14] & 0x1f] >> 12;
        a[15] = MAT24_RECIP_BASIS[p1[15] & 0x1f] >> 12;
        a[16] = MAT24_RECIP_BASIS[p1[16] & 0x1f] >> 12;
        a[17] = MAT24_RECIP_BASIS[p1[17] & 0x1f] >> 12;
        a[18] = MAT24_RECIP_BASIS[p1[18] & 0x1f] >> 12;
        a[19] = MAT24_RECIP_BASIS[p1[19] & 0x1f] >> 12;
        a[20] = MAT24_RECIP_BASIS[p1[20] & 0x1f] >> 12;
        a[21] = MAT24_RECIP_BASIS[p1[21] & 0x1f] >> 12;
        a[22] = MAT24_RECIP_BASIS[p1[22] & 0x1f] >> 12;
        a[23] = MAT24_RECIP_BASIS[p1[23] & 0x1f] >> 12;
    // %%END FOR
    // %%BITMATMUL Mat24_basis[12:23], uint32_t, a, m_out   


    // GF(2) bit matrix multiplication as a sequence of XOR operations:
    //   m_out  = _MFIX_ * a  ,
    // with bit matrices represented as arrays of unsigned integers,
    // each integer representing a row of the matrix. 
    // Here _MFIX_ is the fixed bit matrix  {
    //  0xfff0f0,0xff0ff0,0xf0fff0,0x0ffff0,0xcccc00,0xaaaa00,
    //  0x6ac0c0,0xc6a0a0,0xa6c00c,0x6ca00a,0x11111e
    // }
    {
     uint32_t _r[2];
     m_out[9] = (uint32_t)(a[3]) ^ (uint32_t)(a[1]);
     m_out[8] = (uint32_t)(a[3]) ^ (uint32_t)(a[2]);
     m_out[10] = m_out[8] ^ (uint32_t)(a[1]);
     m_out[10] = (uint32_t)(a[4]) ^ m_out[10];
     m_out[10] = (uint32_t)(a[8]) ^ m_out[10];
     m_out[10] = (uint32_t)(a[12]) ^ m_out[10];
     m_out[10] = (uint32_t)(a[16]) ^ m_out[10];
     m_out[10] = (uint32_t)(a[20]) ^ m_out[10];
     m_out[7] = (uint32_t)(a[7]) ^ (uint32_t)(a[5]);
     m_out[0] = (uint32_t)(a[5]) ^ (uint32_t)(a[4]);
     m_out[6] = (uint32_t)(a[7]) ^ (uint32_t)(a[6]);
     m_out[0] = m_out[6] ^ m_out[0];
     m_out[1] = (uint32_t)(a[9]) ^ (uint32_t)(a[8]);
     m_out[5] = (uint32_t)(a[11]) ^ (uint32_t)(a[9]);
     m_out[4] = (uint32_t)(a[11]) ^ (uint32_t)(a[10]);
     m_out[1] = m_out[4] ^ m_out[1];
     m_out[1] = m_out[1] ^ m_out[0];
     m_out[2] = (uint32_t)(a[13]) ^ (uint32_t)(a[12]);
     _r[0] = (uint32_t)(a[15]) ^ (uint32_t)(a[13]);
     m_out[5] = _r[0] ^ m_out[5];
     m_out[9] = _r[0] ^ m_out[9];
     m_out[7] = _r[0] ^ m_out[7];
     _r[0] = (uint32_t)(a[15]) ^ (uint32_t)(a[14]);
     m_out[2] = _r[0] ^ m_out[2];
     m_out[4] = _r[0] ^ m_out[4];
     m_out[8] = _r[0] ^ m_out[8];
     m_out[6] = _r[0] ^ m_out[6];
     m_out[0] = m_out[2] ^ m_out[0];
     m_out[2] = m_out[2] ^ m_out[1];
     _r[0] = (uint32_t)(a[18]) ^ (uint32_t)(a[17]);
     m_out[8] = _r[0] ^ m_out[8];
     m_out[7] = _r[0] ^ m_out[7];
     _r[0] = (uint32_t)(a[19]) ^ (uint32_t)(a[17]);
     m_out[6] = _r[0] ^ m_out[6];
     m_out[5] = _r[0] ^ m_out[5];
     _r[0] = (uint32_t)(a[19]) ^ (uint32_t)(a[18]);
     m_out[9] = _r[0] ^ m_out[9];
     m_out[4] = _r[0] ^ m_out[4];
     m_out[3] = (uint32_t)(a[17]) ^ (uint32_t)(a[16]);
     m_out[3] = _r[0] ^ m_out[3];
     m_out[0] = m_out[3] ^ m_out[0];
     m_out[1] = m_out[3] ^ m_out[1];
     m_out[3] = m_out[3] ^ m_out[2];
     _r[0] = (uint32_t)(a[23]) ^ (uint32_t)(a[22]);
     m_out[7] = _r[0] ^ m_out[7];
     m_out[4] = _r[0] ^ m_out[4];
     _r[1] = (uint32_t)(a[22]) ^ (uint32_t)(a[21]);
     m_out[9] = _r[1] ^ m_out[9];
     m_out[6] = _r[1] ^ m_out[6];
     _r[1] = (uint32_t)(a[23]) ^ (uint32_t)(a[21]);
     m_out[8] = _r[1] ^ m_out[8];
     m_out[5] = _r[1] ^ m_out[5];
     _r[1] = (uint32_t)(a[21]) ^ (uint32_t)(a[20]);
     _r[1] = _r[0] ^ _r[1];
     m_out[0] = _r[1] ^ m_out[0];
     m_out[1] = _r[1] ^ m_out[1];
     m_out[2] = _r[1] ^ m_out[2];
     // 57 operations generated
    }

    m_out[11] = 0x800;
}



/**
  @brief Convert bit matrix to permutation in the Mathieu group ``Mat24``

  This is the inverse of function mat24_perm_to_matrix()

  The input ``m1`` of the function is a bit matrix that maps
  a Golay code word ``v`` to ``p(v) = v * m1``, as described in
  function mat24_perm_to_matrix().

  The function computes the permutation ``p: i -> p_out[i]``, 
  ``0 <= i < 24``, from that matrix and stores the result in
  the output vector ``p_out`` of length 24.

  Output ``p_out[i], 0 <= i < 24`` contains garbage if ``m1`` is not
  bit matrix corresponding to an element of ``mat24``.

  Implementation idea:

  We could have reversed the operation of function 
  mat24_perm_to_matrix(), but the following implememtation is
  faster:

  Converting rows of matrix ``m1`` from ``gcode`` to ``standard``
  representation yields the images of some Golay code words as bit
  vectors. Intersecting these bit vectors in a suitable way yields
  the images of singletons and hence the requestend permutation.
*/
// %%EXPORT p
MAT24_API
void mat24_matrix_to_perm(uint32_t *m1, uint8_t *p_out)
{
   // %%MAT24_MATRIX_TO_PERM   m1, p_out
   uint_fast32_t _i, ba[14], t[11];
   for (_i=0; _i < 12; ++_i) ba[_i] =
       (MAT24_DEC_TABLE1[(m1[_i] << 4) & 0xf0]
          ^ MAT24_DEC_TABLE2[(m1[_i]  >> 4) & 0xff])
   ;
   ba[12] = ba[4] ^ ba[7] ^ ba[9];
   ba[13] = ba[4] ^ ba[5] ^ ba[6] ^ ba[8];
   t[0] = ba[10];
   t[1] = ~(ba[10]);
   t[2] = ba[12] & ba[13];
   t[3] = ba[12] & ~(ba[13]);
   t[4] = ba[13] & ~(ba[12]);
   t[5] = ba[11] & ~(ba[0] | ba[1]);
   t[6] = ba[0] & ba[1] & ba[2] & ba[3];
   t[7] = ba[1] & ~(ba[0]);
   t[8] = ba[2] & ~(ba[1]);
   t[9] = ba[3] & ~(ba[2]);
   t[10] = ba[0] & ~(ba[3]);
   for (_i = 0; _i < 6; ++_i) {
      uint_fast32_t _w, _k = t[_i + 5];
      _w =  t[(0x1 >> (_i << 2)) & 0xf] & _k;
      *p_out++ = MAT24_LSBIT_TABLE[(0x077cb531UL *  \
              (_w) >> 26) & 0x1f];
      _w =  t[(0x224433 >> (_i << 2)) & 0xf] & _k;
      *p_out++ = MAT24_LSBIT_TABLE[(0x077cb531UL *  \
              (_w) >> 26) & 0x1f];
      _w =  t[(0x332244 >> (_i << 2)) & 0xf] & _k;
      *p_out++ = MAT24_LSBIT_TABLE[(0x077cb531UL *  \
              (_w) >> 26) & 0x1f];
      _w =  t[(0x443322 >> (_i << 2)) & 0xf] & _k;
      *p_out++ = MAT24_LSBIT_TABLE[(0x077cb531UL *  \
              (_w) >> 26) & 0x1f];
   }
   p_out -= 24;
}

/**
  @brief Complete bit matrix for Mathieu group ``Mat24`` from submatrix

  Let the input ``m1`` of the function be a 12 times 12 bit matrix
  that maps  a Golay code word ``v`` to ``p(v) = v * m1``, as 
  described in function ``mat24_perm_to_matrix()``.

  There are cases where the first 11 rows and columns of ``m1``
  can be deduced from an external source, but the last row and 
  column is unknown. This means the operation of an element of
  ``Mat24`` on the Golay code is know modulo the code word 
  ``Omega = (1,...,1)`` only. This function completes such an 
  11 times 11 bit matrix to a 12 times 12 matrix in place.
*/
// %%EXPORT p
MAT24_API
void mat24_matrix_from_mod_omega(uint32_t *m1)
{
    uint32_t weights = 0xff0 << 11;
    // Let b[i] be the i-th basis vector of the Golay code and w[i] 
    // the weight of b[i]. Bit i + 11 of ``weights`` is equal to bit  
    // 3 of ``w[i]``. Bit 3 of the bit weight of the image ``m1[i]``  
    // of b[i] is obtained from table MAT24_THETA_TABLE. Adding
    // ``Omega`` to the Golay code word ``m[i]`` flips both, bit 3 
    // of ``w[i]``, and bit 11 of ``m[i]``. So we can adjust ``m[i]``.

    m1[11] &= ~0xfff;   // m1[11] is always equal to Omega
    // %%FOR i in range(12)
        m1[0] ^= ((MAT24_THETA_TABLE[m1[0] & 0x7ff] >> 2) 
                  ^ (weights >> 0)) & 0x800;
        m1[1] ^= ((MAT24_THETA_TABLE[m1[1] & 0x7ff] >> 2) 
                  ^ (weights >> 1)) & 0x800;
        m1[2] ^= ((MAT24_THETA_TABLE[m1[2] & 0x7ff] >> 2) 
                  ^ (weights >> 2)) & 0x800;
        m1[3] ^= ((MAT24_THETA_TABLE[m1[3] & 0x7ff] >> 2) 
                  ^ (weights >> 3)) & 0x800;
        m1[4] ^= ((MAT24_THETA_TABLE[m1[4] & 0x7ff] >> 2) 
                  ^ (weights >> 4)) & 0x800;
        m1[5] ^= ((MAT24_THETA_TABLE[m1[5] & 0x7ff] >> 2) 
                  ^ (weights >> 5)) & 0x800;
        m1[6] ^= ((MAT24_THETA_TABLE[m1[6] & 0x7ff] >> 2) 
                  ^ (weights >> 6)) & 0x800;
        m1[7] ^= ((MAT24_THETA_TABLE[m1[7] & 0x7ff] >> 2) 
                  ^ (weights >> 7)) & 0x800;
        m1[8] ^= ((MAT24_THETA_TABLE[m1[8] & 0x7ff] >> 2) 
                  ^ (weights >> 8)) & 0x800;
        m1[9] ^= ((MAT24_THETA_TABLE[m1[9] & 0x7ff] >> 2) 
                  ^ (weights >> 9)) & 0x800;
        m1[10] ^= ((MAT24_THETA_TABLE[m1[10] & 0x7ff] >> 2) 
                  ^ (weights >> 10)) & 0x800;
        m1[11] ^= ((MAT24_THETA_TABLE[m1[11] & 0x7ff] >> 2) 
                  ^ (weights >> 11)) & 0x800;
    // %%END FOR
}


/*************************************************************************
*** Mathieu group M24: Mapping a dodecad
*************************************************************************/
/**
  @brief Compute a (unique) heptad from a dodecad.

  This is a (rather technical) auxiliary function for function 
 ``mat24_perm_from_dodecads``

  Let ``d1`` be a dodecad as in function mat24_perm_from_dodecads().

  There is a unique umbral heptad ``h``, as defined in the documentation
  of function mat24_perm_from_heptads(), satisfying the properties 
  described below.
   
  The function evaluates the first 9 elements ``d1[i], 0 <= i < 9``. 
  It fails if these elements are not a subset of a dodecad or not 
  pairwise disjoint.
  
  The function returns 0 in case of success and ``(uint32_t)(-1)``
  in case of failure.
  
  Properties of heptad ``h``:
  
  ``h`` contains ``d1[i]`` for ``0 <= i < 5`` and also the unique 
  element ``h_5`` in the intersection  of ``d1`` and the syndrome 
  ``S5`` of the set ``(d1[i], 0 <= i < 5)``.
  
  Let ``S5 = (h_5, h_6, h_7)`` such that ``Mat24`` contains a
  mapping that maps ``i`` to ``d1[i]`` for ``i < 5`` and ``i`` to
  ``h_i`` for ``i = 5, 6, 7``. This determines ``h_6``  uniquely. 
  Then ``h_6`` is not in the dodecad ``d1``. Let ``T`` be the
  tetrad containing  the set ``(d1[0], d1[1], d1[2], h_6)``. 
  Tetrad ``T`` contains exactly one set ``U`` intersecting ``d1`` 
  in 3  elements disjoint to ``(d1[i], 0 <= i < 5)``.  Then 
  heptad ``h`` contains the element ``d_7`` of the singleton 
  ``U \ d1`` as ts  distinguished element.

  The function puts ``h_out[i] = d1[i]`` for ``0 <= i < 5`` and
  ``h_out[5] = h_5, h_out[6] = d_7.``
*/
static uint32_t dodecad_to_heptad(uint8_t *d1, uint8_t *h_out)
{
    uint_fast32_t s5, rem, all_12, syn, t, i;
    uint8_t a[8];
    uint8_t sextet[24];
    syn = s5 = (1 << d1[0]) ^ (1 << d1[1]) ^ (1 << d1[2]) 
         ^ (1 << d1[3]) ^ (1 << d1[4]);
    syn = odd_syn(syn);
    t = rem = s5 ^ (1 << d1[5]) ^ (1 << d1[6]) 
         ^ (1 << d1[7]) ^ (1 << d1[8]);
    t = odd_syn(t);
    all_12 = t ^ rem;
    if (mat24_bw24(all_12) != 12) return (uint32_t)(-1);
    h_out[0] = a[0] = d1[0]; h_out[1] = a[1] = d1[1]; 
    h_out[2] = a[2] = d1[2]; h_out[3] = a[3] = d1[3];  
    h_out[4] = a[4] = d1[4]; 
    t = syn & all_12;
    h_out[5] = a[5] = mat24_def_lsbit24(t);
    if (mat24_perm_complete_octad(a)) return (uint32_t)(-1);
    t = (1 << a[0]) ^ (1 << a[1]) ^ (1 << a[2]) ^ (1 << a[6]); 
    t = MAT24_ENC_TABLE0[(t) & 0xff] 
           ^ MAT24_ENC_TABLE1[((t) >> 8) & 0xff]  
           ^ MAT24_ENC_TABLE2[((t) >> 16) & 0xff];
    if (mat24_cocode_to_sextet(t, sextet)) return (uint32_t)(-1);
    rem = ~(all_12 | syn);
    for (i = 0; i < 24; i += 4) {
        t = ((1 << sextet[i]) ^ (1 << sextet[i+1]) 
          ^ (1 << sextet[i+2]) ^ (1 << sextet[i+3])) & rem;
        if (t != 0 && (t & (t-1)) == 0) {
            h_out[6] = mat24_def_lsbit24_pwr2(t);
            return 0;
        }        
    }
    return (uint32_t)(0-1);
}      


/**
  @brief Find permutation in ``Mat24`` mapping one dodecad to another

  A dodecad is a word of the Golay code of weight 12. Given two dodecads
  ``d1, d2``, and five elements ``d1[0],...,d1[4]`` of ``d1``, and also
  five elements ``d2[0],...,d2[4]`` of ``d2``, there is a unique
  permutation ``p`` in ``Mat24`` with the following properties:

         d1     is mapped to   d2  ,

         d1[i]  is mapped to   d2[i]  for  0 <= i < 5 .
  
  On input the function  takes two dodecads ``d1, d2`` as arrays
  of integers, and it computes a permutation ``p: i -> p_out[i]``
  satisfying the properies given above. In case of success it stores
  ``p`` in the array ``p_out``. Only the first 9 elements
  ``d1[i], d2[i], 0 <= i < 9`` of ``d1`` and ``d2`` are evalutated.
  There is at most one dodecad containing ``d1[i], 0 <= i < 9`` and
  at most one dodecad containing ``d2[i], 0 <= i < 9``, assuming
  ``d1[i] != d1[j]``  and  ``d2[i] != d2[j]`` for ``i != j``.

  The function fails if the evaluated entries of ``d1`` or of ``d2``
  are not a subset of a dodecad or not pairwise disjoint.
  
  The function returns 0 in case of success and ``(uint32_t)(-1)``
  in case of failure.

  The implementation calls function dodecad_to_heptad() for
  contructing (unique) heptads ``h1`` and ``h2`` from  ``d1`` and 
  ``d2``. Then it calls function mat24_perm_from_heptads() for 
  computing the unique permutation in ``Mat24`` that maps ``h1`` 
  to ``h2``.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_perm_from_dodecads(uint8_t *d1, uint8_t *d2, uint8_t *p_out)
{
    uint8_t h1[8], h2[8];
    return (dodecad_to_heptad(d1, h1) || dodecad_to_heptad(d2, h2)
            || mat24_perm_from_heptads(h1, h2, p_out)) 
            ? (uint32_t)(-1) : 0;
}





/*************************************************************************
*** Mathieu group M24: operation of group elements
*************************************************************************/
/**
  @brief Apply a permutation in the Mathieu group ``Mat24`` to a bit vector

  Apply the permutation ``p: i -> p1[i]`` to the bit vector ``v1``.
  This maps bit ``i`` of ``v1`` to bit ``p1[i]`` of the returned 
  result.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_op_vect_perm(uint32_t v1, uint8_t *p1)
{
   uint_fast32_t i, w = 0;
   for (i = 0; i < 24; ++i) w |=  ((v1 >> i) & 1) << p1[i];
   return w;
}


/**
  @brief Apply a ``12 times 12`` bit matrix to a Golay code vector

  A matrix ``12 times 12`` bit matrix ``m`` must be encoded
  in the input parameter ``m1`` as specified in function
  mat24_perm_to_matrix(). The function returns the matrix
  product ``v1 * m`` as bit vector. Input ``v1`` and  the
  return value are Golay code words given in ``gcode`` 
  representation.    
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_op_gcode_matrix(uint32_t v1, uint32_t *m1)
{
    uint_fast32_t w = 0;
    // %%FOR i in range(12)
        w ^= m1[0] & (0 - ((v1 >> 0) & 1)); 
        w ^= m1[1] & (0 - ((v1 >> 1) & 1)); 
        w ^= m1[2] & (0 - ((v1 >> 2) & 1)); 
        w ^= m1[3] & (0 - ((v1 >> 3) & 1)); 
        w ^= m1[4] & (0 - ((v1 >> 4) & 1)); 
        w ^= m1[5] & (0 - ((v1 >> 5) & 1)); 
        w ^= m1[6] & (0 - ((v1 >> 6) & 1)); 
        w ^= m1[7] & (0 - ((v1 >> 7) & 1)); 
        w ^= m1[8] & (0 - ((v1 >> 8) & 1)); 
        w ^= m1[9] & (0 - ((v1 >> 9) & 1)); 
        w ^= m1[10] & (0 - ((v1 >> 10) & 1)); 
        w ^= m1[11] & (0 - ((v1 >> 11) & 1)); 
    // %%END FOR
    return w;
}


/**
  @brief Apply a permutation in the group ``Mat24`` to a Golay code vector 

  Apply the permutation ``p: i -> p1[i]`` (which must be an element 
  of the Mathieu group Mat24) to the Golay code word ``v1``, 
  with ``v1`` given in ``gcode`` representation.

  The function returnes the permuted Golay code  word in 
  ``gcode`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_op_gcode_perm(uint32_t v1, uint8_t *p1)
{
    uint_fast32_t i, w = 0;
    v1 =   MAT24_DEC_TABLE1[(v1 << 4) & 0xf0]
           ^ MAT24_DEC_TABLE2[(v1 >> 4) & 0xff];
    for (i = 0; i < 24; ++i) w |=  ((v1 >> i) & 1) << p1[i];
    v1 =  MAT24_ENC_TABLE0[w & 0xff]
           ^ MAT24_ENC_TABLE1[(w >> 8) & 0xff]
           ^ MAT24_ENC_TABLE2[(w >> 16) & 0xff];
    return v1 >> 12;
}


/**
  @brief Apply a permutation in the group ``Mat24`` to a Golay cocode element 

  Apply the permutation ``p: i -> p1[i]`` (which must be an element 
  of the Mathieu group Mat24) to the Golay cocode element ``c1``, 
  with ``c1`` given in ``cocode`` representation.

  The function returnes the permuted cocode  word in 
  ``cocode`` representation.
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_op_cocode_perm(uint32_t c1, uint8_t *p1)
{
   uint_fast32_t res;
   res =  0 - (((c1 >> 11) + 1) & 1);   // res = 0 if c1 is odd else -1
   c1 ^= MAT24_RECIP_BASIS[0] & res;    // make c1 odd
   res &= MAT24_RECIP_BASIS[p1[0] & 31]; // .. and adjust result
   c1 = MAT24_SYNDROME_TABLE[ c1 & 0x7ff ]; // get syndrome
   res ^= MAT24_RECIP_BASIS[p1[c1 & 31] & 31]
        ^ MAT24_RECIP_BASIS[p1[(c1 >> 5) & 31] & 31]
        ^ MAT24_RECIP_BASIS[p1[(c1 >> 10) & 31] & 31];
   return res & 0xfff;
}



/**
   @brief Compute product of two permutations in the Mathieu group ``Mat24``

   Here inputs ``p1, p2`` must be permutations represented as mappings
   ``i -> p1[i], i -> p2[i]``. The function computes the product
   ``p1 * p2`` and stores it in the array ``p_out`` in the same form.
   Thus ``p_out[i] = p2[p1[i]]``.

   Input errors are not detected, but output buffer overflow is
   prevented. Any overlap between ``p1, p2,`` and ``p_out`` is
   possible.
*/
// %%EXPORT p
MAT24_API
void mat24_mul_perm(uint8_t *p1, uint8_t *p2, uint8_t *p_out)
{
    uint8_t p[32];
    // %%FOR i in range(24)
        p[0] = p2[p1[0] & 31];
        p[1] = p2[p1[1] & 31];
        p[2] = p2[p1[2] & 31];
        p[3] = p2[p1[3] & 31];
        p[4] = p2[p1[4] & 31];
        p[5] = p2[p1[5] & 31];
        p[6] = p2[p1[6] & 31];
        p[7] = p2[p1[7] & 31];
        p[8] = p2[p1[8] & 31];
        p[9] = p2[p1[9] & 31];
        p[10] = p2[p1[10] & 31];
        p[11] = p2[p1[11] & 31];
        p[12] = p2[p1[12] & 31];
        p[13] = p2[p1[13] & 31];
        p[14] = p2[p1[14] & 31];
        p[15] = p2[p1[15] & 31];
        p[16] = p2[p1[16] & 31];
        p[17] = p2[p1[17] & 31];
        p[18] = p2[p1[18] & 31];
        p[19] = p2[p1[19] & 31];
        p[20] = p2[p1[20] & 31];
        p[21] = p2[p1[21] & 31];
        p[22] = p2[p1[22] & 31];
        p[23] = p2[p1[23] & 31];
    // %%END FOR
    memcpy(p_out, p, 24); 
}


/**
   @brief Compute the inverse of a permutation in the Mathieu group ``Mat24``

   Here input ``p1`` must be a permutation represented as mapping
   ``i -> p1[i]``. The function computes the inverse of ``p1``
   and stores it in the array ``p_out`` in the same form.
   Thus ``p_out[p1[i]] = i``.

   Input errors are not detected, but output buffer overflow is
   prevented. Any overlap between ``p1`` and ``p_out`` is possible.
*/
// %%EXPORT p
MAT24_API
void mat24_inv_perm(uint8_t *p1, uint8_t *p_out)
{
    uint8_t p[32];
    // %%FOR i in range(24)
        p[p1[0] & 31] = 0;
        p[p1[1] & 31] = 1;
        p[p1[2] & 31] = 2;
        p[p1[3] & 31] = 3;
        p[p1[4] & 31] = 4;
        p[p1[5] & 31] = 5;
        p[p1[6] & 31] = 6;
        p[p1[7] & 31] = 7;
        p[p1[8] & 31] = 8;
        p[p1[9] & 31] = 9;
        p[p1[10] & 31] = 10;
        p[p1[11] & 31] = 11;
        p[p1[12] & 31] = 12;
        p[p1[13] & 31] = 13;
        p[p1[14] & 31] = 14;
        p[p1[15] & 31] = 15;
        p[p1[16] & 31] = 16;
        p[p1[17] & 31] = 17;
        p[p1[18] & 31] = 18;
        p[p1[19] & 31] = 19;
        p[p1[20] & 31] = 20;
        p[p1[21] & 31] = 21;
        p[p1[22] & 31] = 22;
        p[p1[23] & 31] = 23;
    // %%END FOR
    memcpy(p_out, p, 24); 
}


/*************************************************************************
*** Automorphisms of the Parker Loop
*************************************************************************/


/**
  @brief Auxiliary function for function mat24_perm_to_autpl()
  
  Given a Parker loop autmorphism ``a``, the function computes a
  quadratic form ``qf`` on the Golay code defined as follows:
  
  ``qf(g[i]) = 0`` for all basis vectors ``g[i]`` of the standard
  basis of the Golay code. Furthermore we have
   
        qf(v1 + v2) = qf(v1) + qf(v2) + b(v1, v2) ,
		
  where ``b`` is a bilinear form on the Golay code defined by	
    
        b(x,y) = theta(p(x), p(y)) + theta(x, y)    (mod 2).
		
  Here ``p`` is the element of the group ``Mat24`` obtained by 
  taking the automorphism ``a``  modulo sign, and ``theta`` is 
  the cocycle of the Parker loop. Then ``b`` is an alternating
  bilinear form by [Seys20], Lemma 4.1. 
	
  Let ``b[i,j] = b(g[i], g[j])`` where ``g[i]`` is the ``i-th``
  basis vector of the Golay code in our selected standard basis. 
  
  Input ``m_io`` represents the Parker loop automorphism ``a`` as 
  documented in function mat24_perm_to_autpl(). Here we modify
  the array ``m_io`` by storing the bit ``b[i,j]`` in bit ``13+j``
  of entry ``m_io[i]`` for ``i > j``.

  So the quadratic form ``qf`` is now also stored in the array
  ``m_io`` representing the automorphsm ``a``. As explained in
  [Seys20] this facilitates computation in the automorphism group
  of the Parker loop.
*/
// %%EXPORT p
MAT24_API
void mat24_autpl_set_qform(uint32_t *m_io)
{
    uint_fast32_t i;
    uint_fast64_t v,  m2[10];

    // The quadratic form qf on the Golay code is defined as follows:
    // qf(b[i]) = 0 for all basis vectors b[i] of the standard
    // basis of the Golay code. Furthermore
    //   qf(v1+v2) = qf(v1) + qf(v2) + v1 * q * transpose(v2),
    // with matrix q as defined below.
 
    // First compute the 12 x 12  matrix q with
    // q[i,j] = theta(m[i], m[j])  ^  theta(b[i],b[j]).
    // Here b[i] is the i-th standard basis vector of the Golay code
    // and m[i] is it image under the automorphism given by m_io.
    // So m[i] = m_io[i] & 0xfff.
    // The matrix q is alternating.
    // We just compute the lower triangle of q in order to evaluate a
    // quadratic form associated with q. Our last basis vector b[11] is 
    // is Omega, so q[i,11] = q[11,i] = 0, and hence for the lower 
    // triangle it suffices to compute q[i,j] for i=0,...,10; 
    // j=0,...,i-1. We store q[i,j] in bit (j+13) of m[i].

    // Internal operation:
    // Most of the work is the computation of  theta(m[i], m[j]).
	
	
    for (i = 0; i < 10; ++i)  {
        v =  (m_io[i] & 0x7ff);
        v ^= v << 12; v ^= v << 24;
        m2[i] = v ^ (v << 48);
    }
	
	v = (uint64_t)MAT24_THETA_TABLE[m_io[1] & 0x7ff] & 0x7ff;
	// %%FOR i in range(1, 5)
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[2] & 0x7ff] & 0x7ff) << 12;
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[3] & 0x7ff] & 0x7ff) << 24;
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[4] & 0x7ff] & 0x7ff) << 36;
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[5] & 0x7ff] & 0x7ff) << 48;
	// %%END FOR
	
	// %%BITVMULTRANSP v, m2, 12, 5, 5
 // Compute ``v_i = v_i * transpose(m_i), i = 0,...,4``, ``v_i`` 
 // a bit vector of length 12, ``m_i`` a 5 times 12  bit 
 // matrix. ``v_i`` is coded in the integer ``v``, ``m_i`` 
 // is coded in the array  ``m2`` of integers. Bits ``v_i[k]`` 
 // and ``m_i[j][k]`` are coded in bits ``12*i + k`` of the 
 // variables  ``v`` and ``m2[j]``, ``j = 0,...,4``, 
 // respectively. 
 {
 uint_fast64_t t_0, t_1, t_2;
 t_0 =  m2[0] & v;
 t_0 = (t_0 ^ (t_0 >> 1)) & 0x555555555555555ULL;
 t_1 =  m2[1] & v;
 t_1 = ((t_1 << 1) ^ t_1) & 0xaaaaaaaaaaaaaaaULL;
 t_0 |= t_1;
 t_0 = (t_0 ^ (t_0 >> 2)) & 0x333333333333333ULL;
 t_1 =  m2[2] & v;
 t_1 = (t_1 ^ (t_1 >> 1)) & 0x555555555555555ULL;
 t_2 =  m2[3] & v;
 t_2 = ((t_2 << 1) ^ t_2) & 0xaaaaaaaaaaaaaaaULL;
 t_1 |= t_2;
 t_1 = ((t_1 << 2) ^ t_1) & 0xcccccccccccccccULL;
 t_0 |= t_1;
 t_0 = (t_0 ^ (t_0 >> 4) ^ (t_0 >> 8)) & 0xf00f00f00f00fULL;
 t_1 =  m2[4] & v;
 t_1 = (t_1 ^ (t_1 >> 1)) & 0x555555555555555ULL;
 t_1 = (t_1 ^ (t_1 >> 2)) & 0x333333333333333ULL;
 t_1 = ((t_1 << 4) ^ t_1 ^ (t_1 >> 4)) & 0xf00f00f00f00f0ULL;
 t_0 |= t_1;
 // 43 operations
 v = t_0;
 }
	v ^= 0xf00f00700b00dULL;

	// %%FOR i in range(5)
	m_io[1] &= 0x1fff;
	m_io[1] ^= ((v << 13) & 0x2000UL);
	m_io[2] &= 0x1fff;
	m_io[2] ^= ((v << 1) & 0x6000UL);
	m_io[3] &= 0x1fff;
	m_io[3] ^= ((v >> 11) & 0xe000UL);
	m_io[4] &= 0x1fff;
	m_io[4] ^= ((v >> 23) & 0x1e000UL);
	m_io[5] &= 0x1fff;
	m_io[5] ^= ((v >> 35) & 0x3e000UL);
	// %%END FOR
	
	v = (uint64_t)MAT24_THETA_TABLE[m_io[6] & 0x7ff] & 0x7ff;
	// %%FOR i in range(1, 5)
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[7] & 0x7ff] & 0x7ff) << 12;
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[8] & 0x7ff] & 0x7ff) << 24;
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[9] & 0x7ff] & 0x7ff) << 36;
	v ^= (uint64_t)(MAT24_THETA_TABLE[m_io[10] & 0x7ff] & 0x7ff) << 48;
	// %%END FOR
	
	// %%BITVMULTRANSP v, m2, 12, 10, 5
 // Compute ``v_i = v_i * transpose(m_i), i = 0,...,4``, ``v_i`` 
 // a bit vector of length 12, ``m_i`` a 10 times 12  bit 
 // matrix. ``v_i`` is coded in the integer ``v``, ``m_i`` 
 // is coded in the array  ``m2`` of integers. Bits ``v_i[k]`` 
 // and ``m_i[j][k]`` are coded in bits ``12*i + k`` of the 
 // variables  ``v`` and ``m2[j]``, ``j = 0,...,9``, 
 // respectively. 
 {
 uint_fast64_t t_0, t_1, t_2, t_3;
 t_0 =  m2[0] & v;
 t_0 = (t_0 ^ (t_0 >> 1)) & 0x555555555555555ULL;
 t_1 =  m2[1] & v;
 t_1 = ((t_1 << 1) ^ t_1) & 0xaaaaaaaaaaaaaaaULL;
 t_0 |= t_1;
 t_0 = (t_0 ^ (t_0 >> 2)) & 0x333333333333333ULL;
 t_1 =  m2[2] & v;
 t_1 = (t_1 ^ (t_1 >> 1)) & 0x555555555555555ULL;
 t_2 =  m2[3] & v;
 t_2 = ((t_2 << 1) ^ t_2) & 0xaaaaaaaaaaaaaaaULL;
 t_1 |= t_2;
 t_1 = ((t_1 << 2) ^ t_1) & 0xcccccccccccccccULL;
 t_0 |= t_1;
 t_0 = (t_0 ^ (t_0 >> 4) ^ (t_0 >> 8)) & 0xf00f00f00f00fULL;
 t_1 =  m2[4] & v;
 t_1 = (t_1 ^ (t_1 >> 1)) & 0x555555555555555ULL;
 t_2 =  m2[5] & v;
 t_2 = ((t_2 << 1) ^ t_2) & 0xaaaaaaaaaaaaaaaULL;
 t_1 |= t_2;
 t_1 = (t_1 ^ (t_1 >> 2)) & 0x333333333333333ULL;
 t_2 =  m2[6] & v;
 t_2 = (t_2 ^ (t_2 >> 1)) & 0x555555555555555ULL;
 t_3 =  m2[7] & v;
 t_3 = ((t_3 << 1) ^ t_3) & 0xaaaaaaaaaaaaaaaULL;
 t_2 |= t_3;
 t_2 = ((t_2 << 2) ^ t_2) & 0xcccccccccccccccULL;
 t_1 |= t_2;
 t_1 = ((t_1 << 4) ^ t_1 ^ (t_1 >> 4)) & 0xf00f00f00f00f0ULL;
 t_0 |= t_1;
 t_1 =  m2[8] & v;
 t_1 = (t_1 ^ (t_1 >> 1)) & 0x555555555555555ULL;
 t_2 =  m2[9] & v;
 t_2 = ((t_2 << 1) ^ t_2) & 0xaaaaaaaaaaaaaaaULL;
 t_1 |= t_2;
 t_1 = (t_1 ^ (t_1 >> 2)) & 0x333333333333333ULL;
 t_1 = ((t_1 << 8) ^ (t_1 << 4) ^ t_1) & 0xf00f00f00f00f00ULL;
 t_0 |= t_1;
 // 79 operations
 v = t_0;
 }
	v ^= 0x40140100e00eULL;

	// %%FOR i in range(5)
	m_io[6] &= 0x1fff;
	m_io[6] ^= ((v << 13) & 0x7e000UL);
	m_io[7] &= 0x1fff;
	m_io[7] ^= ((v << 1) & 0xfe000UL);
	m_io[8] &= 0x1fff;
	m_io[8] ^= ((v >> 11) & 0x1fe000UL);
	m_io[9] &= 0x1fff;
	m_io[9] ^= ((v >> 23) & 0x3fe000UL);
	m_io[10] &= 0x1fff;
	m_io[10] ^= ((v >> 35) & 0x7fe000UL);
	// %%END FOR



    m_io[0] &= 0x1fff; m_io[11] &= 0x1fff;
}

/**
  @brief Construct a Parker loop automorphism 

  The function combines a cocode element ``c1`` and a permutation
  ``p`` in the Mathieu group ``Mat24`` to a Parker loop automorphism.
  Here ``c1`` must be given in ``cocode`` representation. Permutation 
  ``p`` must be given as a mapping ``i -> p1[i], 0 <= i < 24``.
  
  Up to sign, the image of an element of the Parker loop is the 
  corresponding Golay code vector permuted by the permutation ``p``. 
  The sign of the image of the ``i``-th positive basis vector of 
  the Parker loop is given by  bit ``i`` of ``c1``. This determines 
  the automorphism uniqely. We will write ``AutPL(c1, p)`` for that 
  automorphism.
  
  The function returns the automorphism ``AutPL(c1, p)`` as an array 
  ``m_out`` of 12 integers of  type ``uint32_t``. The lowest 13 bits
  of ``m_out[i]`` contain the image of the ``i``-th positive basis 
  vector. Here each image is encoded as a Parker loop element as in
  function ``mat24_mul_ploop``. 
  
  We also compute a quadratic form in the higher bits of the entries  
  of ``m_out``, as described in function mat24_autpl_set_qform(). 
  This facilitates computations in  the automorphism group of the 
  Parker loop. 
  
  Let ``Id`` be the neutral element in ``Mat24``. Then we have
  
        AutPL(c1, p)  = AutPL(c1, Id) * AutPL(0, p) .
*/  
// %%EXPORT p
MAT24_API
void mat24_perm_to_autpl(uint32_t c1, uint8_t *p1, uint32_t *m_out)
{
    uint_fast32_t i;
    mat24_perm_to_matrix(p1, m_out);
    for (i = 0; i < 12; ++i) m_out[i] ^= ((c1 >> i) & 1) << 12;
    mat24_autpl_set_qform(m_out);
}


/**
  @brief Compute a diagonal Parker loop automorphism 

  The function converts a cocode element ``c1`` to a Parker loop 
  automorphism. Here ``c1`` must be given in ``cocode`` 
  representation. Such an automorphism is called a diagnonal
  asutomorphism; it changes the signs of the Parker loop
  elements only.
  
  The resulting automorphism is stored in ``m_out`` in the same 
  way as in function mat24_cocode_to_autpl().
    
  If ``p0`` is an array representing the neutral element of the
  group ``Mat24`` then ``mat24_cocode_to_autpl(cl, m_out)`` is 
  equivalent to ``mat24_perm_to_autpl(c1, p0, m_out)``.  
*/
// %%EXPORT p
MAT24_API
void mat24_cocode_to_autpl(uint32_t c1, uint32_t *m_out)
{
    uint_fast32_t i;
    for (i = 0; i < 12; ++i) {
        m_out[i] = (1 << i) + (((c1 >> i) & 1) << 12);
    }
}


/**
  @brief Extract permutation from Parker loop automorphism.
  
  Ignoring the signs of the Parker loop, an automorphism ``m1`` 
  of  the Parker loop is an automorphism of the Golay code 
  and can be represented as a permutation in the Mathieu 
  group ``Mat24``. Here ``m1`` must be encoded as described in
  function mat24_perm_to_autpl(). 
  
  The function computes the permutation in the group ``Mat24`` 
  corresponding the automorphism ``m1`` and returns it in ``p1``
  as a  mapping ``i -> p1[i]``.
*/  
// %%EXPORT p
MAT24_API
void mat24_autpl_to_perm(uint32_t *m1, uint8_t  *p_out)
{
    mat24_matrix_to_perm(m1, p_out);
}

/**
  @brief Extract cocode element from Parker loop automorphism.
  
  Given an automorphism ``m1`` of the  Parker loop, as constructed 
  by function mat24_perm_to_autpl(), the function returns a
  cocode element ``c`` in ``cocode`` representation. Element ``c``
  has the following property:
  
  Let ``p`` be the permutation in ``Mat24`` obtained from ``m1``
  by calling mat24_autpl_to_perm(m1, p). Then calling
  ``mat24_perm_to_autpl(c, p, m2)``, where ``m2`` is a suitable 
  array, constructs a copy ``m2`` of ``m1`` from ``c`` and ``p``.  
*/  
// %%EXPORT p
MAT24_API
uint32_t mat24_autpl_to_cocode(uint32_t *m1)
{
    uint_fast32_t i, v = 0;
    for (i = 0; i < 12; ++i)  v += ((m1[i] >> 12) & 1) << i;
    return v;
}


/// @cond DO_NOT_DOCUMENT

// The following macro computes t = mat24_op_ploop_autpl(v1, m1).
// It destroys v1. Description see function mat24_op_ploop_autpl().
#define inline_op_ploop_autpl(v1, m1, t) \
    t = (v1 & 0x1000) \
      ^ (m1[0] & (0-(v1 & 1))) ^ (m1[1] & (0-((v1 >> 1) & 1))) \
      ^ (m1[2] & (0-((v1 >> 2) & 1)))  ^ (m1[3] & (0-((v1 >> 3) & 1))) \
      ^ (m1[4] & (0-((v1 >> 4) & 1)))  ^ (m1[5] & (0-((v1 >> 5) & 1))) \
      ^ (m1[6] & (0-((v1 >> 6) & 1)))  ^ (m1[7] & (0-((v1 >> 7) & 1))) \
      ^ (m1[8] & (0-((v1 >> 8) & 1)))  ^ (m1[9] & (0-((v1 >> 9) & 1))) \
      ^ (m1[10] & (0-((v1 >> 10) & 1))) ^ (m1[11] & (0-((v1 >> 11) & 1)));\
    v1 = (t >> 13) & v1;  v1 ^= v1 >> 6;  v1 ^= v1 >> 3; \
    v1 = (0x96 >> (v1 & 7)) & 1; \
    t = (t & 0x1fff) ^ (v1 << 12);     

/// @endcond


/**
  @brief Apply a Parker loop automorphism to a Parker Loop element

  Apply Parker loop automorphism ``m1`` to Parker Loop element ``v1``
  and return the result as a Parker Loop element.
 
  Here ``m1`` is a Parker loop autmorphism as constructed by function 
  mat24_perm_to_autpl(). ``v1`` and the return value is an element 
  of the Parker loop, encoded as in function mat24_mul_ploop().
*/
// %%EXPORT p
MAT24_API
uint32_t mat24_op_ploop_autpl(uint32_t v1, uint32_t *m1)
{
    // Operation:
    // Matrix m1 contains a quadratic form qf and the images of the
    // basis vectors, as described in function mat24_autpl_set_qform().
    // Let m = (m[0],...,m[1]), with row vector m[i] the image of the 
    // i-th basis vector b[i]. Then we compute the product binary 
    // matrix product:
    //    t0 = v_12 * m,
    // where v_12 is the vector containing the lower 12 bits of v, 
    // excluding the sign bit. t0 is the correct result up to sign.
    // Then we asjust the sign as follows:
    //   t = t0  ^  (v1 & 0x1000) ^ (s << 12),  
    // where (v1 & 0x1000) is the sign bit of v1 and s is defined by
    // s = qf(v_12) =  v_12 *  q  * transpose(v_12),
    // and q is the 12 x 12 matrix representing the quadratic form qf 
    // as in function mat24_autpl_set_qform().  

    uint_fast32_t  t;
    inline_op_ploop_autpl(v1, m1, t);
    return t;
}


/**
  @brief Compute the product of two Parker Loop automorphisms
  
  Given two Parker Loop automorphism ``m1, m2`` the function
  computes ``m1 * m2`` and stores the result in ``m_out``. All
  Parker loop automorphisms are encoded as in function
  mat24_perm_to_autpl(). 
  
  For an element ``a`` of the Parker loop we have
  ``m_out(a) = m2(m1(a))``.
*/
// %%EXPORT p
MAT24_API
void mat24_mul_autpl(uint32_t *m1, uint32_t *m2, uint32_t *m_out)
{
    uint_fast32_t  i, v, t;
    uint32_t m[12];
    // Compute images of the vectors m[i] in m1 under the
    // automorphism m2 of the parker loop,
    for (i = 0; i < 12; ++i) {
        v = m1[i];
        inline_op_ploop_autpl(v, m2, t);
        m[i] = t;
    }
    // Store the images of the vectors m[i]  in output matrix m_out
    for (i = 0; i < 12; ++i) m_out[i] = m[i];
    // Compute the quadratic form for m_out.
    mat24_autpl_set_qform(m_out);
}

/**
  @brief Compute the inverse of a Parker Loop automorphisms
  
  Given a Parker Loop automorphism ``m1`` the function computes
  the inverse of  ``m1`` and stores the result in ``m_out``. All
  Parker loop automorphisms are encoded as in function
  mat24_perm_to_autpl(). 
*/
// %%EXPORT p
MAT24_API
void mat24_inv_autpl(uint32_t *m1, uint32_t *m_out)
// Put m_out = m1**(-1) for a Parker loop automorphisms m1
//
// Here all automorphisms are in 'autpl' representation.
{
    uint_fast32_t  i, v, t;
    uint8_t p[32], p_inv[32];
    uint32_t mi[12];

    mat24_matrix_to_perm(m1, p); 
    for (i = 0; i < 24; ++i) p_inv[p[i] & 31] = (uint8_t)i;
    mat24_perm_to_matrix(p_inv, mi);
    for (i = 0; i < 12; ++i) {
         v = mi[i];
         inline_op_ploop_autpl(v, m1, t);
         mi[i] ^= (t & 0x1000);
    }
    for (i = 0; i < 12; ++i) m_out[i] = mi[i]; 
    mat24_autpl_set_qform(m_out);
}


//345678901234567890123456789012345678901234567890123456789012345678901234567890  


/**
  @brief Compute inverse Parker Loop automorphism from permutation
  
  This is equivalent to
  
        mat24_inv_perm(p1, p_out);
        mat24_perm_to_autpl(c1, p1, m_temp);  
        mat24_inv_autpl(m_temp, m_out);  
		
  The function saves some intermedate steps so that it is faster.		
*/   
// %%EXPORT p
MAT24_API
void mat24_perm_to_iautpl(uint32_t c1, uint8_t *p1, uint8_t *p_out, uint32_t *m_out)
{
    uint_fast32_t i, v, t;
    uint32_t m1[16];
    uint8_t p_inv[32];
    mat24_perm_to_matrix(p1, m1);
    for (i = 0; i < 12; ++i) m1[i] ^= ((c1 >> i) & 1) << 12;
    mat24_autpl_set_qform(m1);

    for (i = 0; i < 24; ++i) p_inv[p1[i] & 31] = (uint8_t)i;
    for (i = 0; i < 24; ++i) p_out[i] = p_inv[i];
    mat24_perm_to_matrix(p_inv, m_out);
    for (i = 0; i < 12; ++i) {
        v = m_out[i];
        inline_op_ploop_autpl(v, m1, t);
        m_out[i]  ^= (t & 0x1000);
    }
    mat24_autpl_set_qform(m_out);
}



/*************************************************************************
*** Auxiliary functions for the Monster group
*************************************************************************/

/**
  @brief Compute modified Benes network for permutation of 24 entries

  The Benes network is computed for the permutation ``p: i -> p1[i]``.
  The network consists of 9 layers. The returned array ``a_out`` of 
  length 9 describes that network. In layer ``i``, entry ``j`` is to
  be  exchanged with entry  ``j + d[i]``, if bit ``j`` of the value 
  ``a_out[i]``  is set. Here ``d[i] = 1,2,4,8,16,8,4,2,1`` for
  ``i = 0,...,8``. For all such exchange steps we have ``j & d[i] == 0``.
  We also assert that no entry with index ``>=24`` will be touched. 
*/
// %%EXPORT p
MAT24_API
void mat24_perm_to_net(uint8_t *p1, uint32_t *a_out)
{
    uint_fast8_t p[32], q[32];
    uint_fast32_t i, j, sh, d, done;
    uint_fast32_t res0, res1, res2;

    for (i = 0; i < 24; ++i) 
        p[i] = p1[i] & 31; // copy permutation p1 to p

    // The first and the last three layers are a standard Benes network. 
    // Do Benes network looping algorithm steps for d = 1, 2, 4
    for (sh = 0; sh < 3; ++sh)
    {      
        d = 1 << sh;
        for (i = 0; i < 24; ++i)
            q[p[i]] = (uint8_t)i;  // q := inverse of p
        done = 0;            // bit i marks that step i->p[i] is done
        res0 = 0;            // initial looping transpositions
        res1 = 0;            // final looping transpositions
        for (i = 0; i < 24; ++i)  // Looping step for Benes network
        {
            j = i;           // j is a node not yet processed
            while (!(done & (1 << j))) // while node j not done
            {
                done |= 1 << j;        // delare node j done
                j = p[j];              // j := permutation result p[j]
                // route node p[j] thru '0' part of inner Benes network
                // so we do: if (j & d): res1 |=  1 << (j & ~d)
                res1 |= ((j & d) >> sh) << (j & ~d);
                j = q[j ^ d];          // j = origin of buddy of p[j]
                done |= 1 << j;        // declare that buddy done
                // route buddy thru '1' part of inner Benes network
                // so we do: if (~j & d): res0 |=  1 << (j & ~d)
                res0 |= ((~j & d) >> sh) << (j & ~d);
                j = j ^ d;             // j = buddy of that origin
            }
        }
        a_out[sh] = res0;    // save initial looping transposition
        a_out[8-sh] = res1;  // save final looping transposition
        res0 |= res0 << d;   // initial: exchange i with i^d if bit i set
        res1 |= res1 << d;   // final: exchange i with i^d if bit i set
        for (i = 0; i < 24; ++i)  // compute q = (initial) * p * (final)
        {
            j = p[i ^ (((res0 >> i) & 1) << sh)];
            q[i] = (uint8_t)(j ^ (((res1 >> j) & 1) << sh));
        }
        for (i = 0; i < 24; ++i) // copy (initial) * p * (final) to p
            p[i] = q[i];
    }
    // It remains to compute the 3 middle layers. They must compute
    // the permutation i -> p[i] with p[i] = i (mod 8). E.g. for i=0
    // we do the following transpositions, if (0, 8, 16) maps to
    //
    //   ( 0,  8, 16):          (id)  *   (id)   *   (id)  // [1]
    //   ( 0, 16,  8):         (0,8)  *  (0,16)  *  (0,8)  // [0]     
    //   ( 8,  0, 16):         (0,8)  *   (id)   *   (id)  // [2]  
    //   ( 8, 16,  0):         (0,8)  *  (0,16)  *   (id)  // [3]
    //   (16,  0,  8):          (id)  *  (0,16)  *  (0,8)  // [4]  
    //   (16,  8,  0):          (id)  *  (0,16)  *   (id)  // [5]
    //          
    // For each permutation of (i, i+8, i+16) we compute a number j,
    // as indicated in square brackets above, from the bits 3 and 4 of
    // p[i] and p[i+8]. Then we use table look up for obtaining the
    // correct transpostions as given in the list above.   
    res0 = res1 = res2 = 0;
    for (i = 0; i < 8; ++i)
    {
        j = p[i] >> 3;
        j = 2 * j + ((p[i+8] >> (3 + (j & 1))) & 1);
        j = (0x236407 >> (j << 2)) & 0xf;
        res2 |=  (j & 1) << i;
        res1 |=  ((j >> 1) & 1) << i;
        res0 |=  ((j >> 2) & 1) << i;
    }
    a_out[3] = res0; a_out[4] = res1; a_out[5] = res2;
}





/**  
  @brief Auxiliary function for computing in the monster.
  
  The function is used for applying the automorphism ``m1`` of 
  the Parker loop to a vector of the ``196884``-dimensional 
  representation of the monster. ``m1`` is encoded as in function
  mat24_perm_to_autpl().

  It computes a table ``a_out[i], i = 0,...,0x7ff``, such that
  ``(a_out[i] & 0x7ff)`` is the image ``m1(i)`` of the Parker 
  loop element ``i`` modulo the center of the Parker loop. Signs 
  are stored in bits ``12,...,14`` of ``a_out[i]`` as follows:
  
        Bit 12: (sign of m1(i)) ^ (odd &  P(i))
	 
        Bit 13: (sign of m1(i))
	 
        Bit 14: (sign of m1(i)) ^ (bit 11 of m1(i))
		
  Here ``odd`` is the parity of the automorphism, and ``P()``
  is the power map of the Parker loop.
*/
// %%EXPORT p
MAT24_API
void mat24_op_all_autpl(uint32_t *m1, uint16_t *a_out)
{
    uint_fast32_t i;   // exponential counter: 1, 2, 4, 8,...,0x400
    uint_fast32_t j;   // counter from 1 to i-1
    uint_fast32_t ri;  // accumulator for computing a_out[i]
    uint_fast32_t q;   // q is row log2(i) of bilinear form in m1
    uint_fast32_t qq, qq1, qq2;  // used for computing a sign bit
    uint_fast32_t odd; // set to a nonzero value if m1 is odd
    odd = m1[11] & 0x1000;
    // We have to to the following:
    a_out[0] = 0; 
    // But we also don't like dummy operations with undefined input
    a_out[1] = a_out[2] = a_out[3] = 0;
    for (i = 1; i < 0x800; i += i) {
        // First compute ri = a_out[i] and copy the (halved) 
        // corresponding row of bilinear form from m1 to q. 
        ri = *m1++;                 // row  log2(i)   of  m1
        q = (ri >> 13) & 0x7ff;     // row of bilinear form B
        // m1[log2(i)], bit 0,..12 is the Parker loop element i,
        // with bit 12 the sign bit. Store sign bit to bits 12...14
        // of ri. Store image of element i in bits 11...0.
        // of ri. xor bit 11 of that image to bit 14 of ri. Note that 
        // the Power map bit is 0 for all basis vectors.
        ri = (0-(ri & 0x1000)) ^ (ri & 0xfff) ^ ((ri & 0x800) << 3);
        a_out[i] = (uint16_t)ri;   // Save result ri in a_out.
        qq1 = 0 - ((q & 1) << 12);
        a_out[i+1] = (uint16_t)(ri ^ a_out[1] ^ qq1);   
        qq2 = 0 - ((q & 2) << 11);     
        a_out[i+2] = (uint16_t)(ri ^ a_out[2] ^ qq2);   
        a_out[i+3] = (uint16_t)(ri ^ a_out[3] ^ qq1 ^ qq2);   
        // Next compute a_out[i+j], 1 <= j < i.
        // We do cases j,..j+3 in a single iteration for j = 0 mod 4
        for (j = 4; j < i; j += 4) {
            // Store bit dsign = B(i, j) = parity(j & q) in 
            // qq, bits 12..14. We have 
            //  sign(i+j) = sign(i) ^ sign(j) ^ dsign
            qq = j & q;
            qq ^= qq >> 6;
            qq ^= qq >> 3;
            qq = -((0xD20 << (qq & 7)) & 0x1000); 
            // Put a_out[i+j] = a_out[i] ^ a_out[j] ^ dsign
            a_out[i+j] = (uint16_t)(ri ^ a_out[j] ^ qq); 
            qq1 = qq ^ (0-((q & 1) << 12)); // qq1[12..14] = qq0^B(i,1) 
            a_out[i+j+1] = (uint16_t)(ri ^ a_out[j+1] ^ qq1); 
            qq2 = 0 - ((q & 2) << 11);     // qq2[12..14] =  B(i,2) 
            a_out[i+j+2] = (uint16_t)(ri ^ a_out[j+2] ^ qq ^ qq2); 
            a_out[i+j+3] = (uint16_t)(ri ^ a_out[j+3] ^ qq1 ^ qq2); 
        }
    }
    if (odd) for (i = 0; i < 0x800; i += 4) {
        // Adjust bit 12  for power map if m1 is odd   
        a_out[i] ^= MAT24_THETA_TABLE[i] & 0x1000;
        a_out[i+1] ^= MAT24_THETA_TABLE[i+1] & 0x1000;
        a_out[i+2] ^= MAT24_THETA_TABLE[i+2] & 0x1000;
        a_out[i+3] ^= MAT24_THETA_TABLE[i+3] & 0x1000;
    }
}




/**  
  @brief Auxiliary function for computing in the monster.
  
  This is a simplified version of function mat24_op_all_autpl(),
  which is used for applying the diagonal automorphism ``c1`` 
  of the Parker loop (encoded in ``cocode`` representation) to
  a vector of a representation of the monster.

  The function computes a table ``a_out[i], i= 0,...,0x7ff``, 
  containing the signs related to this operation as follows:
  
         Bit 0:  (sign of c1(i)) ^ (odd &  P(i))
	
         Bit 1:  (sign of c1(i))
	
         Bit 2:  same as bit 1
		
  Here ``odd`` and ``P()`` are as in function mat24_op_all_autpl().
*/
// %%EXPORT p
MAT24_API
void mat24_op_all_cocode(uint32_t c1, uint8_t *a_out)
{
    uint_fast32_t i;      // exponential counter: 1, 2, 3, 8,...,0x400
    uint_fast32_t j;      // counter from 1 to i-1
    uint_fast32_t sh = 0; // shift factor: i = 2 << sh
    uint_fast8_t ri;     // accumulator for computing a_out[i]
    // We have to to the following:
    a_out[0] = 0; 
    // But we also don't like dummy operations with undefined input
    a_out[1] = a_out[2] = a_out[3] = 0;
    for (i = 1; i < 0x800; i += i) {
        // First compute ri = a_out[i]. ri is equal to the scalar 
        // product of the Golay code element i and  the cocode 
        // element c1.  Note that the Power map bit is 0 for all 
        // basis vectors.
        a_out[i] = ri = (uint8_t)(0 - ((c1 >> sh++) & 1));
        a_out[i+1] = ri ^ a_out[1];
        a_out[i+2] = ri ^ a_out[2];
        a_out[i+3] = ri ^ a_out[3];
        // Next compute a_out[i+j], 1 <= j < i.
        for (j = 4; j < i; j += 4) {
            // Put a_out[i+j] = a_out[i] ^ a_out[j]
            a_out[i+j] = ri ^ a_out[j];      
            a_out[i+j+1] = ri ^ a_out[j+1];      
            a_out[i+j+2] = ri ^ a_out[j+2];      
            a_out[i+j+3] = ri ^ a_out[j+3];      
        }
    }
    if (c1 & 0x800) for (i = 0; i < 0x800;  i += 4) {
        // Adjust bit 12  for power map if c1 is odd   
        a_out[i] ^= (MAT24_THETA_TABLE[i] >> 12) & 0x1;
        a_out[i+1] ^= (MAT24_THETA_TABLE[i+1] >> 12) & 0x1;
        a_out[i+2] ^= (MAT24_THETA_TABLE[i+2] >> 12) & 0x1;
        a_out[i+3] ^= (MAT24_THETA_TABLE[i+3] >> 12) & 0x1;
    }
}








// %%GEN ch
#ifdef __cplusplus
}
#endif
// %%GEN h
