The C interface of the mmgroup project
Introduction
This document describes the functionality of the C modules in this project. For most of these C modules there is also a python extension. Unless otherwise stated, each documented C function is wrapped by a Cython function with the same name and signature.
Note that almost all parameters of such a C function are declared as
(signed or unsigend) integers, or as pointers to such integers. In
python, a numpy array of appropriate dtype may be passed as
an argument to a parameter delared as a pointer to an integer.
Description of the mmgroup.mat24 extension
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 Parker loop
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 Implementing Automorphisms of the Parker loop 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
_outis 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
_iorefer to pointers in the C function and hence to iterables in the corresponding python function. Here the sufix_iomeans that the function may modify that iterable object.
C interface
Header files
File mat24_functions.h is the header file for mat24_functions.c.
Defines
-
MAT24_ORDER
Order of Mathieu group
Mat24. This is equal to 244823040.
-
MAT24_SUBOCTAD_WEIGHTS
(MAT24_SUBOCTAD_WEIGHTS >> x) & 1 is halved weight of suboctad x (mod 2).
-
mat24_def_lsbit24(v1)
Macro version of function
mat24_lsbit24.
-
mat24_def_lsbit24_pwr2(v1)
Special macro version of function
mat24_lsbit24.This is faster than
mat24_def_lsbit24, but herev1must be power of two.
-
mat24_def_parity12(v1)
Parity of vector
v1of 12 bits length.Return the bit parity of
v1 & 0xfff.
-
mat24_def_octad_to_gcode(o)
Eqivalent to
mat24_octad_to_gcode(o)mat24_def_octad_to_gcode(o)returns the number of the Golay code word corresponding to octado. Parameterois not checked.
-
mat24_def_gcode_to_octad(v)
Eqivalent to
mat24_gcode_to_octad(v)mat24_def_gcode_to_octad(v)returns the number of the octad corresponding to Golay code vectorv, withvingcode. It returns garbage ifvis not an octad.
-
mat24_def_not_nonstrict_octad(v)
Check if
v(or its complement) is an octad.Returns 0 if
v(or its complement) is an octad and 1 otherwise.Vector
vmust be given ingcoderepresentation
-
mat24_def_gcode_to_vect(v)
Convert Golay code element number
vto a vector inGF(2)^24Macro version of function
mat24_gcode_to_vect.
-
mat24_def_vect_to_cocode(v1)
Return Golay cocode element corresponding to a bit vector in
GF(2)^24.Macro version of function
mat24_vect_to_cocode.
-
mat24_def_syndrome_from_table(t)
Convert entry
tof tableMAT24_SYNDROME_TABLEto syndrome.An entry
tof the tableMAT24_SYNDROME_TABLEencodes an odd cocode syndrome. The macro returns that syndrome as a bit vector.
-
mat24_def_suboctad_weight(u_sub)
Equivalent to mat24_suboctad_weight(u_sub)
Enums
-
enum mat24_rand_flags
Flags describing subgroups of the Mathieu group \(M_{24}\).
This enumeration contains flags describing some subgroups of the Mathieu group \(M_{24}\) fixing certain subsets (or sets of subsets) of the set \(\tilde{\Omega} = \{0,\ldots,23\}\) on which the group \(M_{24}\) acts. Intersetions of these subgroups may be described by combining these flags with the bitwise or operator
|. For each flag we state the set being fixed.Values:
-
enumerator MAT24_RAND_2
fixes \(\{2, 3\} \)
-
enumerator MAT24_RAND_o
fixes \(\{0, \ldots,7 \}\)
-
enumerator MAT24_RAND_t
fixes \(\{\{8i,\ldots,8i+7\} \mid i < 3 \}\)
-
enumerator MAT24_RAND_s
fixes \(\{\{4i,\ldots,4i+3\} \mid i < 6 \}\)
-
enumerator MAT24_RAND_l
fixes \(\{\{2i, 2i+1\} \mid 4 \leq i < 12 \}\)
-
enumerator MAT24_RAND_3
fixes \(\{1, 2, 3\} \)
-
enumerator MAT24_RAND_d
fixes \(\{\{2i, 2i+1\} \mid 0 \leq i < 12 \}\)
-
enumerator MAT24_RAND_2
Functions
-
static inline uint32_t mat24_inline_cocode_to_suboctad(uint32_t c1, uint32_t v1, uint32_t u_strict)
Inline version of function
mat24_cocode_to_suboctad
-
static inline uint32_t mat24_inline_suboctad_to_cocode(uint32_t u_sub, uint32_t u_octad)
Inline version of function
suboctad_to_cocode
-
int32_t mat24_check_endianess(void)
Check endianess of the machine.
Return 0 if machine is little endian, 1 if it is Big endian, and -1 if endianess could not be detected.
C functions for the Mathieu group \(M_{24}\)
File mat24_tables.c contains tables that are used in the file mat24_functions.c.
Variables
-
const uint16_t MAT24_OCT_DEC_TABLE[759]
Table for converting
octadtogcoderepresentation.The public macro
mat24_def_octad_to_gcodeuses this table
-
const uint16_t MAT24_OCT_ENC_TABLE[2048]
Table for converting
gcodetooctadrepresentation.The public macro
mat24_def_gcode_to_octaduses this table
-
const uint16_t MAT24_THETA_TABLE[]
Table containing data about the Golay code.
For
0 <= d < 0x800entrydcontains the following information the code wordd, withdingcoderepresentation.Bit 11,…,0:
mat24_ploop_theta(d)Bit 14,…,12: Bit weight of code word
dinGF(2)**24divided by 4Bit 15: reserved
We have
d**2 = (-1)**<Bit 12 of entry d>fordin the Parker loop.
-
const uint8_t MAT24_OCTAD_ELEMENT_TABLE[759 * 8]
For
0 <= i < 759, the entries8*i,...8*i+7in the tableMAT24_OCTAD_ELEMENT_TABLEare the bit positions of the octad with the numberi.
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.
Functions
-
uint32_t mat24_lsbit24(uint32_t v1)
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.
-
uint32_t mat24_bw24(uint32_t v1)
Returns the bit weight of the lowest 24 bits of
v1.
-
uint32_t mat24_vect_to_bit_list(uint32_t v1, uint8_t *a_out)
Stores the positions of 1-bits of a bit vector to an array.
Let
wbe the bit weight of the bit vectorv1 & 0xffffff, i.e. number of bits ofv1at positions< 24equal to one. Then the ordered bit positions where the corresponding bit ofv1is 1 are stored ina_out[0],...,a_out[w-1].Then
(v1 & 0xffffff)has24 - wzero bits. The ordered list of the positions of these zero bits is stored ina_out[w],...,a_out[23].The function returns the bit weight
w.
-
uint32_t mat24_vect_to_list(uint32_t v1, uint32_t u_len, uint8_t *a_out)
Stores the positions of 1-bits of a bit vector to an array.
Let
wbe the minimum of the inputu_lenand the bit weight of the bit vectorv1 & 0xffffff, i.e. number of bits ofv1at positions< 24equal to one. Then the firstwbit positions where the corresponding bit ofv1is 1 are stored ina_out[0],...,a_out[w-1]in natural order. The function returnsw.For small values
wthis function is faster than functionmat24_vect_to_bit_list.
-
uint32_t mat24_extract_b24(uint32_t v1, uint32_t u_mask)
Extract the bits of 24-bit vector
v1given by the masku_maskIf
u_maskhas bits equal to one at positionsi_0, i_1, ..., i_k(in ascending order) then the bit ofv1at positioni_jis copied to the bit at positionjof the return value forj = 0,...,k.
-
uint32_t mat24_spread_b24(uint32_t v1, uint32_t u_mask)
Spread bits of 24-bit vector
v1according to the masku_maskIf
u_maskhas bits equal to one at positionsi_0, i_1, ..., i_k(in ascending order) then the bit ofv1at positionjis copied to the bit at positioni_jof the return value forj = 0,...,k.
-
uint32_t mat24_vect_to_vintern(uint32_t v1)
Convert bit vector
v1inGF(2)^24fromvectortovinternrepresentation.
-
uint32_t mat24_vintern_to_vect(uint32_t v1)
Convert bit vector
v1inGF(2)^24fromvinterntovectorrepresentation.
-
uint32_t mat24_vect_to_cocode(uint32_t v1)
Return Golay cocode element corresponding to a bit vector in
GF(2)^24.This amounts to reducing the vector
v1(given invectorrepresentation) modulo the Golay code. The function returns the cocode element corresponding tov1incocoderepresentation.
-
uint32_t mat24_gcode_to_vect(uint32_t v1)
Convert Golay code element number
v1to a vector inGF(2)^24Input
v1is a Golay code element ingcoderepresentation. The function returns the bit vector corresponding tov1invectorrepresentation.
-
uint32_t mat24_cocode_to_vect(uint32_t c1)
Return a vector in
GF(2)^24corresponding to cocode element.Here
c1is the number of a cocode element incocoderepresentation. One of2**12possible preimages ofc1inGF(2)^24is returned invectorrepresentation.
-
uint32_t mat24_vect_to_gcode(uint32_t v1)
Return a vector in
GF(2)^24as a Golay code element.If the vector
v1(given invectorrepresentation) is in the Golay code then the function returns the number of that Golay code word. Thus the return value is ingcoderepresentation.If
v1is not in the Golay code then the function returns(uint32_t)(-1).
-
uint32_t mat24_gcode_to_octad(uint32_t v1, uint32_t u_strict)
Return a Golay code vector as an octad.
If
u_strictis even then the function acts as follows:If the Golay code vector
v1(given ingcoderepresentation) is an octad or a complement of an octad then the function returns the number of that octad. Thus the return value is inoctadrepresentation. Then we have0 <= octad(v1, strict) < 759.If
v1is not a (possibly complemented) octad then the function returns(uint32_t)(-1).If
u_strictis odd then the function returns(uint32_t)(-1)also in case of a complemented octadv1.
-
uint32_t mat24_vect_to_octad(uint32_t v1, uint32_t u_strict)
Return a vector in
GF(2)^24as an octad.If
u_strictis even then the function acts as follows:If the vector
v1(given invectorrepresentation) is an octad or a complement of an octad then the function returns the number of that octad. Thus the return value is inoctadrepresentation. Then we have0 <= octad(v1, strict) < 759.If
v1is not a (possibly complemented) octad then the function returns(uint32_t)(-1).If
u_strictis odd then the function returns(uint32_t)(-1)also in case of a complemented octadv1.
-
uint32_t mat24_octad_to_gcode(uint32_t u_octad)
Convert an octad to a Golay code vector.
Given an octad
u_octad(inoctadrepresentation), the function returns the number of the corresponding Golay code number ingcoderepresentation.There are 759 octads. The function returns
(uint32_t)(-1)in caseu_octad >= 759.
-
uint32_t mat24_octad_to_vect(uint32_t u_octad)
Convert an octad to a bit vector in
GF(2)^24.Given an octad
u_octad(inoctadrepresentation), the function returns bit vector corresponding to that octad invectorrepresentation.There are 759 octads. The function returns
(uint32_t)(-1)in caseu_octad >= 759.
-
uint32_t mat24_cocode_syndrome(uint32_t c1, uint32_t u_tetrad)
Return Golay code syndrome of cocode element
c1.Here
c1is a cocode element incocoderepresentation. 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().
-
uint32_t mat24_cocode_all_syndromes(uint32_t c1, uint32_t *a_out)
Return all Golay code syndromes of cocode element
c1.Here
c1is a cocode element incocoderepresentation. The function writes all Golay code syndromes of length at most 4 as bit vectors invectorrepresentation into the arraya_out. It returns the length of the arraya_out, which will be 1 or 6. Buffera_outmust have length at least 6.
-
uint32_t mat24_syndrome(uint32_t v1, uint32_t u_tetrad)
Return Golay code syndrome of word
v1.Here
v1is an arbitrary word inGF(2)**24invectorrepresentation. The function returns a Golay code syndrome ofv1(of minimum possible bit weight) as a bit vector invectorrepresentation.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_tetradis set. Therefore parameteru_tetradmust satisfy0 <= u_tetrad < 24; otherwise the function fails.If the minimum weight of the sydrome is at most three then parameter
u_tetradmust satisfy0 <= u_tetrad <= 24; otherwise the function fails.The function returns
(uint32_t)(-1)in case of failure.
-
uint32_t mat24_all_syndromes(uint32_t v1, uint32_t *a_out)
Return all Golay code syndromes of bit vector
v1.Here
v1is an arbitrary word inGF(2)**24invectorrepresentation. The function writes all Golay code syndromes of length at most 4 as bit vectors invectorrepresentation into the arraya_out. It returns the length of the arraya_out, which will be 1 or 6. Buffera_outmust have length at least 6.
-
uint32_t mat24_gcode_weight(uint32_t v1)
Returns bit weight of Golay code word
v1divided by 4.Here
0 <= v1 < 4096is the number of a Golay code word, i.e.v1is given ingcoderepresentation.
-
uint32_t mat24_gcode_to_bit_list(uint32_t v1, uint8_t *a_out)
Store bit positions of Golay code
v1in arraya_outHere
0 <= v1 < 4096is the number of a Golay code word, i.e.v1is given ingcoderepresentation. The Golay code wordv1is stored in the array referred bya_outas an ordered list of the positions of the bits being set in the wordv1.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.
-
uint32_t mat24_cocode_weight(uint32_t c1)
Return the minimum possible weight of the cocode vector
c1Here
c1is a cocode element incocoderepresentation.
-
uint32_t mat24_cocode_to_bit_list(uint32_t c1, uint32_t u_tetrad, uint8_t *a_out)
Store Golay code syndrome of cocode word
c1in an array.Here
c1is an cocode word in cocode representation. The function stores the sorted bit positions of the syndrome ofc1in the array referred bya_outand returns the actual length of that array, which is the weight of the syndrome. The array referred bya_outmust 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_tetradis set. Therefore parameteru_tetradmust satisfy0 <= u_tetrad < 24; otherwise the function fails.If the minimum weight of the sydrome is at most three, parameter
u_tetradmust satisfy0 <= u_tetrad <= 24; otherwise the function fails.The function returns
(uint32_t)(-1)in case of failure.
-
uint32_t mat24_cocode_to_sextet(uint32_t c1, uint8_t *a_out)
Store a cocode word
c1in arraya_outas a sextet.Here
c1is 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
c1ina_out[4*i],...,a_out[4*i+3]fori = 0,...,5. The (ordered) tetrads are stored in lexical order.The function returns
(uint32_t)(-1)ifc1has not minimum weight 4.
-
uint32_t mat24_intersect_octad_tetrad(uint32_t v1, uint32_t v2)
Compute an octad intersecting another octad in a tetrad.
Let
v1be a vector given invectorrepresentation which is a (possibly complemented) octad; and letobe that octad. Letv2be another vector given invectorrepresentation. If there is an octad containing the vectorv2and intersectingoin a tetrad then the functon returns such an octad invectorrepresentation. Otherwise the function returns 0. Ifv1is not a (possibly complemented) octad then the function fails and returns(uint32_t)(-1).
-
uint8_t mat24_vect_type(uint32_t v1)
Compute the type of a vector
vin \(\mathbb{F}_2^{24}\).Here the type of a vector
vis its orbit under the action of the Mathieu group \(M_{24}\). These orbits are denoted as in Figure 10.1 in [CS99], Ch. 10.2.6. An orbit of weight <= 12 isSpecial (coded as 0) if in contains or is contained in a octad
Umbral (coded as 1) if in contains or is contained in a dodecad
Transversal (coded as 2) otherwise
A vector of weight > 12 is special, umbral, or transversal, if its complement has that property.
A vector of weight 12 is extraspecial (coded as 3) if it contains three octads, and penumbral (coded as 4) if it has Hamming distance two from a dodecad.
The function returns the value
32 * c + w, wherewis the weight of the vectorv, andcis the code for its type, as described above.
-
uint32_t mat24_scalar_prod(uint32_t v1, uint32_t c1)
Return scalar product of Golay code and cocode vector.
v1is a Golay code vector in ‘gcode’ representation,c1is a cocode vector in cocode representation.Actually the function returns the bit parity of
v1 & c1 & 0xfff.
-
uint32_t mat24_cocode_to_suboctad(uint32_t c1, uint32_t v1, uint32_t u_strict)
Convert cocode element
c1to suboctad of octadv1The function converts a cocode element
c1(incocoderepresentation) and an octadv1(ingcoderepresentation) to a suboctad.The function returns
(o << 6) + u_sub. Hereois the octad number corresponding to octadv1andu_subis the suboctad number corresponding to the cocode elementc1, ifu_octadis an octad andc1is an even subset ofu_octad.Each octad
v1has 64 even subsets, when each subset ofv1is identified with its complement inv1. These subsets are called suboctads. Letb_0, ..., b_7be the elements of the octadv1in the order as returned by applying functionmat24_octad_entriesto octad numbero. Then the even subset(b_0 , b_i)has suboctad number2**(i-1)fori = 1,...,6. Combining suboctads by symmetric difference corresponds to combining their numbers byxor. The empty subocatad has number zero. This yields a one-to-one correspondence between the integers0,...,63and the suboctads of a fixed octadv1, when identifying a suboctad ith its complement.At present elements of the octads are ordered in natural order. But this is subject to change!
The function fails if
v1is not a octad orc1cannot be represented as an even subset ofv1. Ifv1is a complement of an octadotheois taken instead ofv1. Ifu_strictis set then the pair(v1, c1)must correspond a short Leech lattice vector. Otherwise is suffices to specifyv1up to an additive term \(\Omega\).The function returns
(uint32_t)(-1)in case of failure.
-
uint32_t mat24_suboctad_to_cocode(uint32_t u_sub, uint32_t u_octad)
Convert even suboctad of octad to cocode representation.
The function converts a suboctad
u_sub(insuboctadrepresentation) of an octadu_octad(inoctadrepresentation) to a cocode element. It returns that cocode element incocoderepresentation. This is a partial inverse of functionmat24_suboctad_to_cocode(). The ordering of the suboctads is described in that function.The function fails if
u_octaddoes not represent an octad. It returns(uint32_t)(-1)in case of failure.
-
uint32_t mat24_octad_entries(uint32_t u_octad, uint8_t *a_out)
List the entries of an octad.
The function writes the list of entries of octad
u_octad(inoctadrepresentation) into the arraya_outof length 8. The order of these entries is the order used for the conversion of suboctads. It may differ from the natrual order.The function returns 0 if
u_octadis the number of an octad and(uint32_t)(-1)otherwise.
-
uint32_t mat24_suboctad_weight(uint32_t u_sub)
Return parity of halved bit weight of the even suboctad.
Here parameter
u_subis 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().
-
uint32_t mat24_suboctad_scalar_prod(uint32_t u_sub1, uint32_t u_sub2)
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_sub2whenu_sub1andu_sub2are given as subsets of an octad in vector notation.But in this functions parameters
u_sub1, u_sub2are suboctad numbers as documented in function mat24_suboctad_to_cocode().
-
uint32_t mat24_cocode_as_subdodecad(uint32_t c1, uint32_t v1, uint32_t u_single)
Represent a cocode element as a subset of a docecad.
Given a Golay cocode element
c1(incocoderepresentation) and a dodecadv1(ingcoderepresentation), the function returns a bit vectorc_outequivalent to the cocode wordc1, which is a subset of the dodecadd1. This is possible if the scalar product ofc1and the complement ofv1is even. Otherwise the function fails.The user may specify a bit position
0 <= u_single < 24disjoint from the bits of dodecadd1. Then that bit of the return valuec_outwill be set if the scalar product mentioned above is odd, and the function succeeds also in this case.The intersection of
c_outwithv1has bit weight at most 6. If that bit weight is equal to 6 thenc_outcontains the least significant bit of the bit vector corresponding tov1.The function fails if
v1is not a dodecad. It returns(uint32_t)(-1)in case of failure.
-
uint32_t mat24_ploop_theta(uint32_t v1)
Returns the theta function for the Parker loop.
Here function
theta()is a quadratic function from the Golay codeCto the cocodeC*. Parameterv1of functionthetais a Golay code word ingcoderepresentation. The result of thethetafunction is returned as a Golay cocode word incocoderepresentation.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
v1only. Thusv1may also be an element of the Parker loop.
-
uint32_t mat24_ploop_cocycle(uint32_t v1, uint32_t v2)
Returns the cocycle of the Parker loop.
Here parameters
v1andv2are Golay code vectors ingcoderepresentations or elements of the Parker loop, coded as in functionmat24_mul_ploop. Then the Parker loop product ofv1andv2is given byv1 (*) v2 = v1 ^ v2 * (-1)**cocycle(v1, v2).
-
uint32_t mat24_mul_ploop(uint32_t v1, uint32_t v2)
Returns the product of two elements of the Parker loop.
Here the Parker loop elements
v1andv2are integers coded as follows:bit 0,...,11: a Golay code word in ``gcode`` representation bit 12: Parker loop sign
The other bis of
v1andv2are ignored.
-
uint32_t mat24_pow_ploop(uint32_t v1, uint32_t u_exp)
Returns a power of an element of the Parker loop.
Here
v1is a the Parker loop element coded as in function mat24_mul_ploop().u_expis the exponent. The function returns the powerv1 ** expas an element of the Parker loop.E.g. mat24_pow_ploop(v1, 3) is the inverse of
v1.
-
uint32_t mat24_ploop_comm(uint32_t v1, uint32_t v2)
Return commutator of Golay code words
v1andv2This is equal to 0 if the intersection of the bit vectors
v1andv2has bit weight 0 mod 4, and equal to 1 is that intersection has bit weight 2 mod 4. Wordsv1andv2must be given ingcoderepresentation.For Parker loop elements
v1andv2(coded as in functionmat24_mul_ploop) the commutator ofv1andv2is equal to(-1) ** mat24_ploop_comm(v1, v2),
where
**denotes exponentiation.
-
uint32_t mat24_ploop_cap(uint32_t v1, uint32_t v2)
Return intersection of two Golay code words as cocode word.
Here
v1andv2are Golay code words ingcoderepresentation. The result is a cocode word returned incocoderepresentation.
-
uint32_t mat24_ploop_assoc(uint32_t v1, uint32_t v2, uint32_t v3)
Return associator of Golay code words
v1, v2,andv3This is the parity of the intersection of the bit vectors
v1, v2,andv3. So the function returns 0 or 1. Vectorsv1, v2, v3are ingcoderepresentation.The associator of three Parker loop elements
v1, v2, v3is equal to(-1) ** mat24_ploop_assoc(v1, v2, v3) .
Here
v1, v2, v3are encoded as in function mat24_mul_ploop().
-
uint32_t mat24_ploop_solve(uint32_t *p_io, uint32_t u_len)
Return cocode element that kills signs of Parker loop elements.
Here
p_iorefers to an array ofu_lenParker 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 bits0,...,11of 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_iois destroyed. More specifically, the firstkentries of that array are changed to an array of linear independent Parker loop elements. When thesekelements are mapped to positive Parker loop elements, this also yields a solution of the original problem. If the problem cannot be solved then we putp_io[k-1] = 0x1000.The function returns the value
kin bits31,...,16of the result.
-
uint32_t mat24_perm_complete_heptad(uint8_t *p_io)
Complete permutation in the Mathieu group
Mat24from 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_ioto a permutationpin the Mathieu groupMat24. On output, permutationpis given as a mappingi -> p_io[i]fori = 0,...,23.On input, the images
p_io[i]must be given fori = 0,1,2,3,4,5,8; the other entries ofp_ioare ignored.The set
(p_io[i], i = 0,1,2,3,4,5,8)must be an umbral heptad with distiguished elementp_io[8]. Then the mappingi -> p_io[i], i = 0,1,2,3,4,5,8is a feasible mapping between umbral heptads; it extends to a unique permutation inMat24. Note that8is 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 valuesp_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).
-
uint32_t mat24_perm_check(uint8_t *p1)
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
Mat24and a nonzero value otherwise.The implementation uses function mat24_perm_complete_heptad().
-
uint32_t mat24_perm_complete_octad(uint8_t *p_io)
Complete an octad given by 6 elements of it.
Given entries
p_io[i], i = 0,1,2,3,4,5, we calculate valuesp_io[6], p_io[7]such that the set(p_io[i], 0 <= i < 8)is an octad. Furthermore, we order the valuesp_io[6], p_io[7]in such way that the mappingi -> p_io[i]may be extended to a permutation in the grpupMat24. This restrtiction determines the order uniquely. Note that the set0,...,7is an octad, which is called the standard octad.The set
p_io[i], i = 0,1,2,3,4,5must 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().
-
uint32_t mat24_perm_from_heptads(uint8_t *h1, uint8_t *h2, uint8_t *p_out)
Complete a mapping to a permutation in the Mathieu group
Mat24A permutation in the Mathieu group
Mat24is a mapping from the set(0,...,23)to itself. The function completes the mappingh1[i] -> h2[i],0 <= i < 7,0 <= h1[i], h2[i] < 24to a permutationi -> p_out[i],0 <= i < 24in the groupMat24. The result is returned in the arrayp_out[i].The sets
h1[i], 0 <= i < 7andh2[i], 0 <= i < 7must be umbral heptads, and the mapping fromh1toh2must 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 ofMat24and(uint32_t)(-1)otherwise.The implementation uses function mat24_perm_complete_heptad().
-
uint32_t mat24_perm_from_map(uint8_t *h1, uint8_t *h2, uint32_t n, uint8_t *p_out)
Complete a mapping to a permutation in the Mathieu group
Mat24A permutation in the Mathieu group
Mat24is a mapping from the set(0,...,23)to itself. The function tries to complete the mappingh1[i] -> h2[i],0 <= i < n,0 <= h1[i], h2[i] < 24to a permutationi -> p_out[i],0 <= i < 24in the Mathieu groupMat24. In case of success, such a permutation is stored in the arrayp_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 inh1orh2are 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 inMat24.2 if if the mapping
h1[i] -> h2[i]can be completed to several permutations inMat24, and not all entriesh1[i]can be covered by an octad. This may happen in casen = 6only.3 if if the mapping
h1[i] -> h2[i]can be completed to several permutations inMat24, and all entriesh1[i]can be covered by an octad.If the return value is greater then zero then a suitable permutation in
Mat24is returned in the array referred byp_out. The function computes the lowest permutation (in lexical order) that mapsh1toh2.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!!
-
uint32_t mat24_m24num_to_perm(uint32_t u_m24, uint8_t *p_out)
Compute permutation in the Mathieu group
Mat24from its number.The Mathieu group has order
244823040. We assign numbers0 <= n < 244823040to the elements ofMat24, in lexicographic order, with0the number of the neutral element. This is just a convenient way to refer to an element ofMat24.The function calculates the permutation with the number
u_m24and stores it in the arrayp_outas a mappingi -> p_out[i].0 <= u_m24 < 244823040must hold; otherwise the function fails.The function returns 0 in case of success and
(uint32_t)(-1)in case of failure.
-
uint32_t mat24_perm_to_m24num(uint8_t *p1)
Compute number of a permutation in the Mathieu group
Mat24This is the inverse of function mat24_m24num_to_perm().
Given a permutation
i -> p1[i], 0 <= i < 24, the function returns the numbernof that permutation. We have0 <= n < 244823040, as described in functionmat24_m24num_to_perm.The function returns garbage if
p1is not a valid permutation inMat24. One may use function mat24_perm_check() to check if permutationp1is inMat24.
-
void mat24_perm_to_matrix(uint8_t *p1, uint32_t *m_out)
Convert permutation in the Mathieu group
Mat24to bit matrix.The input of the function is the permutation
p: i -> p1[i],0 <= i < 24which must be in the Mathieu groupMat24.The function computes a
12 times 12bit matrixm, acting on a Golay code vectorv(ingcoderepresentation) by right multiplication. Then we havev * m = p(v). Bitm[i,j]is stored in bitjof the the integerm_out[i].Output
m_out[i], 0 <= i < 12contains garbage ifpis not inMat24.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.
-
void mat24_matrix_to_perm(uint32_t *m1, uint8_t *p_out)
Convert bit matrix to permutation in the Mathieu group
Mat24This is the inverse of function mat24_perm_to_matrix()
The input
m1of the function is a bit matrix that maps a Golay code wordvtop(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 vectorp_outof length 24.Output
p_out[i], 0 <= i < 24contains garbage ifm1is not bit matrix corresponding to an element ofmat24.Implementation idea:
We could have reversed the operation of function mat24_perm_to_matrix(), but the following implememtation is faster:
Converting rows of matrix
m1fromgcodetostandardrepresentation 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.
-
void mat24_matrix_from_mod_omega(uint32_t *m1)
Complete bit matrix for Mathieu group
Mat24from submatrix.Let the input
m1of the function be a 12 times 12 bit matrix that maps a Golay code wordvtop(v) = v * m1, as described in functionmat24_perm_to_matrix().There are cases where the first 11 rows and columns of
m1can be deduced from an external source, but the last row and column is unknown. This means the operation of an element ofMat24on the Golay code is know modulo the code wordOmega = (1,...,1)only. This function completes such an 11 times 11 bit matrix to a 12 times 12 matrix in place.
-
static uint32_t dodecad_to_heptad(uint8_t *d1, uint8_t *h_out)
Compute a (unique) heptad from a dodecad.
This is a (rather technical) auxiliary function for function
mat24_perm_from_dodecadsLet
d1be 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:hcontainsd1[i]for0 <= i < 5and also the unique elementh_5in the intersection ofd1and the syndromeS5of the set(d1[i], 0 <= i < 5).Let
S5 = (h_5, h_6, h_7)such thatMat24contains a mapping that mapsitod1[i]fori < 5anditoh_ifori = 5, 6, 7. This determinesh_6uniquely. Thenh_6is not in the dodecadd1. LetTbe the tetrad containing the set(d1[0], d1[1], d1[2], h_6). TetradTcontains exactly one setUintersectingd1in 3 elements disjoint to(d1[i], 0 <= i < 5). Then heptadhcontains the elementd_7of the singletonU \ d1as ts distinguished element.The function puts
h_out[i] = d1[i]for0 <= i < 5andh_out[5] = h_5, h_out[6] = d_7.
-
uint32_t mat24_perm_from_dodecads(uint8_t *d1, uint8_t *d2, uint8_t *p_out)
Find permutation in
Mat24mapping one dodecad to another.A dodecad is a word of the Golay code of weight 12. Given two dodecads
d1, d2, and five elementsd1[0],...,d1[4]ofd1, and also five elementsd2[0],...,d2[4]ofd2, there is a unique permutationpinMat24with 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, d2as arrays of integers, and it computes a permutationp: i -> p_out[i]satisfying the properies given above. In case of success it storespin the arrayp_out. Only the first 9 elementsd1[i], d2[i], 0 <= i < 9ofd1andd2are evalutated. There is at most one dodecad containingd1[i], 0 <= i < 9and at most one dodecad containingd2[i], 0 <= i < 9, assumingd1[i] != d1[j]andd2[i] != d2[j]fori != j.The function fails if the evaluated entries of
d1or ofd2are 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
h1andh2fromd1andd2. Then it calls function mat24_perm_from_heptads() for computing the unique permutation inMat24that mapsh1toh2.
-
uint32_t mat24_op_vect_perm(uint32_t v1, uint8_t *p1)
Apply a permutation in the Mathieu group
Mat24to a bit vector.Apply the permutation
p: i -> p1[i]to the bit vectorv1. This maps bitiofv1to bitp1[i]of the returned result.
-
uint32_t mat24_op_gcode_matrix(uint32_t v1, uint32_t *m1)
Apply a
12 times 12bit matrix to a Golay code vector.A matrix
12 times 12bit matrixmmust be encoded in the input parameterm1as specified in function mat24_perm_to_matrix(). The function returns the matrix productv1 * mas bit vector. Inputv1and the return value are Golay code words given ingcoderepresentation.
-
uint32_t mat24_op_gcode_perm(uint32_t v1, uint8_t *p1)
Apply a permutation in the group
Mat24to 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 wordv1, withv1given ingcoderepresentation.The function returnes the permuted Golay code word in
gcoderepresentation.
-
uint32_t mat24_op_cocode_perm(uint32_t c1, uint8_t *p1)
Apply a permutation in the group
Mat24to 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 elementc1, withc1given incocoderepresentation.The function returnes the permuted cocode word in
cocoderepresentation.
-
void mat24_mul_perm(uint8_t *p1, uint8_t *p2, uint8_t *p_out)
Compute product of two permutations in the Mathieu group
Mat24Here inputs
p1, p2must be permutations represented as mappingsi -> p1[i], i -> p2[i]. The function computes the productp1 * p2and stores it in the arrayp_outin the same form. Thusp_out[i] = p2[p1[i]].Input errors are not detected, but output buffer overflow is prevented. Any overlap between
p1, p2,andp_outis possible.
-
void mat24_inv_perm(uint8_t *p1, uint8_t *p_out)
Compute the inverse of a permutation in the Mathieu group
Mat24Here input
p1must be a permutation represented as mappingi -> p1[i]. The function computes the inverse ofp1and stores it in the arrayp_outin the same form. Thusp_out[p1[i]] = i.Input errors are not detected, but output buffer overflow is prevented. Any overlap between
p1andp_outis possible.
-
void mat24_autpl_set_qform(uint32_t *m_io)
Auxiliary function for function mat24_perm_to_autpl()
Given a Parker loop autmorphism
a, the function computes a quadratic formqfon the Golay code defined as follows:qf(g[i]) = 0for all basis vectorsg[i]of the standard basis of the Golay code. Furthermore we haveqf(v1 + v2) = qf(v1) + qf(v2) + b(v1, v2) ,
where
bis a bilinear form on the Golay code defined byb(x,y) = theta(p(x), p(y)) + theta(x, y) (mod 2).
Here
pis the element of the groupMat24obtained by taking the automorphismamodulo sign, andthetais the cocycle of the Parker loop. Thenbis an alternating bilinear form by [Seys20], Lemma 4.1.Let
b[i,j] = b(g[i], g[j])whereg[i]is thei-thbasis vector of the Golay code in our selected standard basis.Input
m_iorepresents the Parker loop automorphismaas documented in function mat24_perm_to_autpl(). Here we modify the arraym_ioby storing the bitb[i,j]in bit13+jof entrym_io[i]fori > j.So the quadratic form
qfis now also stored in the arraym_iorepresenting the automorphsma. As explained in [Seys20] this facilitates computation in the automorphism group of the Parker loop.
-
void mat24_perm_to_autpl(uint32_t c1, uint8_t *p1, uint32_t *m_out)
Construct a Parker loop automorphism.
The function combines a cocode element
c1and a permutationpin the Mathieu groupMat24to a Parker loop automorphism. Herec1must be given incocoderepresentation. Permutationpmust be given as a mappingi -> 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 thei-th positive basis vector of the Parker loop is given by bitiofc1. This determines the automorphism uniqely. We will writeAutPL(c1, p)for that automorphism.The function returns the automorphism
AutPL(c1, p)as an arraym_outof 12 integers of typeuint32_t. The lowest 13 bits ofm_out[i]contain the image of thei-th positive basis vector. Here each image is encoded as a Parker loop element as in functionmat24_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
Idbe the neutral element inMat24. Then we haveAutPL(c1, p) = AutPL(c1, Id) * AutPL(0, p) .
-
void mat24_cocode_to_autpl(uint32_t c1, uint32_t *m_out)
Compute a diagonal Parker loop automorphism.
The function converts a cocode element
c1to a Parker loop automorphism. Herec1must be given incocoderepresentation. 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_outin the same way as in function mat24_perm_to_autpl().If
p0is an array representing the neutral element of the groupMat24thenmat24_cocode_to_autpl(cl, m_out)is equivalent tomat24_perm_to_autpl(c1, p0, m_out).
-
void mat24_autpl_to_perm(uint32_t *m1, uint8_t *p_out)
Extract permutation from Parker loop automorphism.
Ignoring the signs of the Parker loop, an automorphism
m1of the Parker loop is an automorphism of the Golay code and can be represented as a permutation in the Mathieu groupMat24. Herem1must be encoded as described in function mat24_perm_to_autpl().The function computes the permutation in the group
Mat24corresponding the automorphismm1and returns it inp1as a mappingi -> p1[i].
-
uint32_t mat24_autpl_to_cocode(uint32_t *m1)
Extract cocode element from Parker loop automorphism.
Given an automorphism
m1of the Parker loop, as constructed by function mat24_perm_to_autpl(), the function returns a cocode elementcincocoderepresentation. Elementchas the following property:Let
pbe the permutation inMat24obtained fromm1by calling mat24_autpl_to_perm(m1, p). Then callingmat24_perm_to_autpl(c, p, m2), wherem2is a suitable array, constructs a copym2ofm1fromcandp.
-
uint32_t mat24_op_ploop_autpl(uint32_t v1, uint32_t *m1)
Apply a Parker loop automorphism to a Parker Loop element.
Apply Parker loop automorphism
m1to Parker Loop elementv1and return the result as a Parker Loop element.Here
m1is a Parker loop autmorphism as constructed by function mat24_perm_to_autpl().v1and the return value is an element of the Parker loop, encoded as in function mat24_mul_ploop().
-
void mat24_mul_autpl(uint32_t *m1, uint32_t *m2, uint32_t *m_out)
Compute the product of two Parker Loop automorphisms.
Given two Parker Loop automorphism
m1, m2the function computesm1 * m2and stores the result inm_out. All Parker loop automorphisms are encoded as in function mat24_perm_to_autpl().For an element
aof the Parker loop we havem_out(a) = m2(m1(a)).
-
void mat24_inv_autpl(uint32_t *m1, uint32_t *m_out)
Compute the inverse of a Parker Loop automorphisms.
Given a Parker Loop automorphism
m1the function computes the inverse ofm1and stores the result inm_out. All Parker loop automorphisms are encoded as in function mat24_perm_to_autpl().
-
void mat24_perm_to_iautpl(uint32_t c1, uint8_t *p1, uint8_t *p_out, uint32_t *m_out)
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.
-
void mat24_perm_to_net(uint8_t *p1, uint32_t *a_out)
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 arraya_outof length 9 describes that network. In layeri, entryjis to be exchanged with entryj + d[i], if bitjof the valuea_out[i]is set. Hered[i] = 1,2,4,8,16,8,4,2,1fori = 0,...,8. For all such exchange steps we havej & d[i] == 0. We also assert that no entry with index>=24will be touched.
-
void mat24_op_all_autpl(uint32_t *m1, uint16_t *a_out)
Auxiliary function for computing in the monster.
The function is used for applying the automorphism
m1of the Parker loop to a vector of the196884-dimensional representation of the monster.m1is 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 imagem1(i)of the Parker loop elementimodulo the center of the Parker loop. Signs are stored in bits12,...,14ofa_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
oddis the parity of the automorphism, andP()is the power map of the Parker loop.
-
void mat24_op_all_cocode(uint32_t c1, uint8_t *a_out)
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
c1of the Parker loop (encoded incocoderepresentation) 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
oddandP()are as in function mat24_op_all_autpl().
C functions for generating random elements of \(M_{24}\)
File mat24_random.c contains the C implementations of the functions for generation random elements of some subgroups of the Mathieu group \(M_{24}\).
Equivalent python function are coded in module mmgroup.tests.test_mat24.test_mat24_rand.
A subgroup of \(M_{24}\) is decribed by an integer of type uint_32_t encoding a bit mask. Each bit in that mask encodes a certain subgroup of \(M_{24}\). By combining several bits with bitwise pr we may evcode the intersection of the subgroups corresponding to the bits being set.
The mapping of the bits to the subgroups is given in the description of the enum type mat24_rand_flags in file mat24_functions.h.
Functions
-
uint32_t mat24_complete_rand_mode(uint32_t u_mode)
Complete an intersection of subgroups of \(M_{24}\).
Here the integer
u_modeis a combination of flags of typeenum mat24_rand_flagsdescribing an intersection \(H\) of subgroups of \(M_{24}\). Then the group \(H\) may be contained in more subgroups of \(M_{24}\) encoded as bits of an integer of typeenum mat24_rand_flags. This function (hopefully!) sets all bits inu_modecorresponding to groups containing \(H\).The function returns the modified parameter
u_mode.
-
int32_t mat24_perm_in_local(uint8_t *p1)
Compute some subgroups containing an element of \(M_{24}\).
Let \(p_1\) be a permutation in \(M_{24}\) given as an array of 24 integers. The function computes a set of subgroups of \(M_{24}\) containing \(p_1\). These computations are done for all subgroups corresponding to the flags defined in
enum mat24_rand_flags. The function returns an integermodethat is the combination of flags of typeenum mat24_rand_flagsdescribing the subgroups of \(M_{24}\) containing \(H\) .The function returns -1 if \(p_1\) is not in \(M_{24}\).
-
int32_t mat24_perm_rand_local(uint32_t u_mode, uint32_t u_rand, uint8_t *p_out)
Generate a random element of a subgroup of \(M_{24}\).
The function generates an element of a subgroup \(H\) of the Mathieu group \(M_{24}\). Here the parameter
u_modeis a combination of flags of typeenum mat24_rand_flagsdescribing the group \(H\) as an intersection of subgroups of \(M_{24}\). The generated permutation is stored in the arrayp_outof length 24.Parameter
u_randis an integer describing the element of subgroup \(H\) to be generated. Hereu_randis reduced modulo the order of \(H\). In order to generate a uniform random element of \(H\), the user should generate a uniform random number0 <= u_rand < MAT24_ORDER, whereMAT24_ORDERis the order of the group \(M_{24}\).The function returns 0 in case of success and -1 in case of failure.
-
int32_t mat24_m24num_rand_local(uint32_t u_mode, uint32_t u_rand)
Generate number of random element of a subgroup of \(M_{24}\).
The function generates an element of a subgroup \(H\) of the Mathieu group \(M_{24}\). Here the parameters
u_modeand andu_randare as in functionmat24_perm_rand_local.The function returns the number of the generated element of \(M_{24}\) in case of success and -1 in case of failure.
See function
mat24_m24num_to_permfor the numbering of the elements of \(M_{24}\).
-
int32_t mat24_m24num_rand_adjust_xy(uint32_t u_mode, uint32_t v)
Make an element of the Parker loop compatible with a subgroup.
Here parameter
vis an element \(d\) of the Parker loop encoded as in filemat24.c. Parameteru_modedescribes a subgroup of the Mathieu group \(M_{24}\) as in functionmat24_perm_rand_local.Eventually, we want to construct random elements in a larger group then \(M_{24}\). For some values of
u_modewe want to use additional generators corresponding to a subloop of the Parker loop. Here the details are dictated by the 2-local structure of the Monster.If
u_modeis set so that one or more Golay cocode vectors of weight 2 are fixed pointwise then we require the scalar product of \(d\) with all these fixed weight-2 vectors to be zero. The function modifies the Parker loop element \(d\) appropriately and returns the modified element.
Generating C code for the mmgroup.mat24 extension
In this section we give a brief overview over the modules in
mmgroup.dev.mat24 used for generating C code for the
mmgroup.mat24 extension.
Module mat24_ref
Module mat24_ref contains the class Mat24.
Class Mat24 in module mmgroup.dev.mat24.mat24_ref is the
table-providing class used by the code generator to generate the C
file mat24_functions.c. That C file contains the functionality
of the python extension mmgroup.mat24.
Class Mat24 may also be used as a table-providing class for
generating other C files.
Class Mat24 also exports the same functions as the mmgroup.mat24
extension as class methods. So it can be used for testing that extension
and also as a pure-python substitute for that extension.
Class Mat24 is based on class mat24tables.Mat24Tables. It also
uses classes, functions and tables from the following modules
in mmgroup.dev.mat24:
make_addition_table,make_mul_transp,mat24aux,mat24heptad,mat24theta
Module mat24tables
Module mat24tables contains the class Mat24Tables
Class Mat24Tables is a base for class Mat24 in module
mmgroup.dev.mat24.mat24_ref. It contains the basis of the Golay code
and of (a set of representatives of) the Golay cocode. It also contains
tables for fast conversion of a vector in V = GF(2)**24 from the
standard to the internal representation and vice versa. That class also
contains a table of the syndromes of all 2048 odd elements of the
cocode. The 759 octads, i.e. Golay code word of length 8 are
numbered from 0 to 758. Class Mat24Tables provides tables
for computing the number of a octad from a Golay code word representing
an octad and vice versa.
Class Mat24Tables also contains python versions of some C functions
in file mat24_functions.c using these tables.
Module mat24aux
The module contains classes Lsbit24Function and MatrixToPerm.
Class Lsbit24Function contains tables and directives for computing
the least significant bit of a 24-bit integer using a
DeBruijn sequence. This may be overkill for such a simple function,
but it may also be considered as a didactic example of a
table-providing class.
Class MatrixToPerm contains a directive that generates highly
optimized code for converting a bit matrix acting on a Golay code
word to a permutation in the Mathieu group Mat_24. Here we
assume the bit matrix actually encodes an element of the
Mathieu group; otherwise garbage is returned. The Golay code
word must be given as an integer in gcode representation.
Module mat24heptad
Support for completing a permutation in the Mathieu group
A heptad is s subset of seven elements of the set on which that
Mathieu group acts. Under certain circumstances a mapping from one
heptad to another heptad can be completed to a unique element of
mat_24. The C function mat24_perm_from_heptads in file
mat24_functions.c performs that task. It calls a simpler
function mat24_perm_complete_heptad in that file which
completes a mapping from a fixed heptad to variable heptad.
This file contains python implementations of functions
mat24_perm_complete_heptad and mat24_perm_from_heptads.
The C function mat24_perm_to_m24num maps the elements of the
Mathieu group Mat_24 to the set if integers
0, ..., order(Mat_24). Function mat24_perm_complete_heptad
is also used as a subroutine of function mat24_m24num_to_perm
which compute the inverse of that mapping. This module also
contains python implementations of these functions.
Class HeptadCompleter is a table-providing class that is used
for code generation. It also exports the functionality of this
module.
Function hint_for_complete_heptads prints an explanation
of the implementation of function mat24_perm_complete_heptad,
including some precalulated data required for that implementation.
Function test_complete_octad test the correcteness of function
mat24_perm_complete_heptad. Here it suffices to check that
the identity permutation is generated correctly from the required
input values, and that the intersections of (possibly complemented)
octads and syndromes are indeed singletons if the ought to be
singletons.
Module make_addition_table
The module contains class BitMatrixMulFix.
Class BitMatrixMulFix contains a directive that generates
code to multiply a fixed bit matrix with a variable bit matrix.
The C function mat24_perm_to_matrix uses this kind of matrix
multiplication to convert a permutation in the Mathieu group
to a bit matrix operating on a Golay code word.
Module make_mul_transp
The module contains class BitMatrixMulTransp.
Class BitMatrixMulTransp contains a directive that generates
code to multiply a bit vector with the transposed matrix of a
fixed bit matrix. Depending on the size of the matrix and the
bit length of the underlying integer type, several bit vectors
can be multiplied with the same matrix simultaneously.
The C function mat24_autpl_set_qform uses that matrix
multiplication, see section Implementing Automorphisms of the Parker loop
in the Guide for developers for background.
Description of the mmgroup.generators extension
Module generators contains the definition of the generators of the
monster, so that they may be used in C files. It also contains support
for the subgroups \(N_{0}\) of structure
\(2^{2+11+2\cdot11}.(\mbox{Sym}_3 \times M_{24})\) and
\(G_{x0}\) of structure \(2^{1+24}.\mbox{Co}_1\) of the
monster, as described in [Con85] and [Sey20]. Here
\(M{24}\) is the Mathieu group acting on 24 elements, and
\(\mbox{Co}_1\) is the automorphism group of the 24-dimensional
Leech lattice modulo 2.
Here we fully support the computation in the subgroup \(N_{0}\) based on the generators defined in this module, so that a word in the generators of \(N_{0}\) can easily be reduced to a standard form.
We also support the operation of the group \(G_{x0}\) on the
Leech lattice mod 2 and mod 3 (in some cases up to sign only). For a
full support of the subgroup \(G_{x0}\) we also have to compute
in a Clifford group, which is implemented in module clifford12.
Our set of generators of the monster group is defined in section The Monster group. The C implementation of this set of generators is defined in section Header file mmgroup_generators.h.
The intersection \(N_{0} \cap G_{x0}\) is a group \(N_{x0}\)
of structure \(2^{1+24}.2^{11}.M_{24}\). The group \(M_{24}\)
(and, to some extent, also the group \(N_{x0}\)) is
supported by the C functions in file mat24_functions.c.
The Leech lattice and the extraspecial group \(Q_{x0}\)
Let \(Q_{x0}\) the normal subgroup of \(G_{x0}\) of structure \(2^{1+24}\). Then \(Q_{x0}\) is an extraspecial 2 group and also a normal subgroup of \(G_{x0}\). Let \(\Lambda\) be the Leech lattice. The quotient of \(Q_{x0}\) by its center \(\{\pm1\}\) is isomorphic to \(\Lambda/2 \Lambda\), which is the Leech lattice modulo 2.
For \(e_i \in Q_{x0}\) let \(\tilde{e}_i\) be the vector in the Leech lattice (mod 2) corresponding to \(\pm e_i\). Then \(e_1^2 = (-1)^s\) for \(s = \langle\tilde{e}_1, \tilde{e}_1 \rangle /2\), where \(\langle.,.\rangle\) is the scalar product in the Leech lattice. For the commutator \([e_1, e_2]\) we have \([e_1, e_2] = (-1)^t\), \(t = \langle \tilde{e}_1, \tilde{e}_2 \rangle\).
Leech lattice encoding of the elements of \(Q_{x0}\)
An element of of \(Q_{x0}\) can be written uniquely as a product \(x_d \cdot x_\delta\), \(d \in \mathcal{P} , \delta \in \mathcal{C}^*\), see [Sey20], section 5. Here \(\mathcal{P}\) is the Parker loop and \(\mathcal{C}^*\) is the Golay cocode. We encode the element \(x_d \cdot x_\delta\) of \(Q_{x0}\) as an integer \(x\) as follows:
Here elements of the Parker loop and elements of the cocode are encoded as integers as in section The Parker loop and The Golay code and its cocode. \(\theta\) is the cocycle given in section The basis of the Golay code and of its cocode, and ‘\(\oplus\)’ means bitwise addition modulo 2. Note that a Parker loop element is 13 bits long (with the most significant bit denoting the sign) and that a cocode element is 12 bits long.
From this representation of \(Q_{x0}\) we obtain a
representation of a vector in the Leech lattice modulo 2 by
dropping sign bit, i.e. the most significant bit at position 24.
A vector addition in the Leech lattice modulo 2 can be done by
applying the XOR operator ^ to the integers representing
the vectors, ignoring the sign bit.
Special elements of the group \(Q_{x0}\)
We write \(\Omega\) for the positive element of the Parker
loop such that \(\tilde{\Omega}\) is the Golay code word
\((1,\ldots,1)\) as in [Con85] and [Sey20].
In this specifiction we also write \(\Omega\) for the
element \(x_{\Omega}\) of \(Q_{x0}\) and for the element
\(\tilde{x}_{\Omega}\) of the Leech lattice modulo 2 if the
domain of \(\Omega\) is clear from the context. Then
\(\Omega\) has Leech lattice encoding 0x800000 in
our chosen basis of the Golay code; and the element \(\Omega\)
of \(\Lambda/2 \Lambda\) corresponds to the standard
coordinate frame of the real Leech lattice.
For fast computations in the monster group it is vital to compute
in the centralizer of a certain short element \(x_{\beta}\)
of \(Q_{x0}\), where \(\beta\) is an even coloured element
of the Golay cocode, as described in [Sey20]. Here we
choose the cocode element \(\beta\) corresponding to the
element \((0,0,1,1,0,\ldots,0)\) of \(\mbox{GF}_2^{24}\).
Then the centralizer of \(x_{\beta}\) is isomorphic to the
a double cover baby monster group and contains the generators
\(\tau\) and \(\xi\) of the monster. We also write
\(\beta\) for the element \(x_{\beta}\) of \(Q_{x0}\)
and for the element \(\tilde{x}_{\beta}\) of
\(\Lambda/2 \Lambda\) in the same way as for the element
\(\Omega\). Then \(\beta\) has Leech lattice
encoding 0x200 in our chosen basis.
Module gen_leech_reduce.c contains functions for rotating
arbitrary type-4 vectors in \(\Lambda/2 \Lambda\) to
\(\Omega\) and for rotating arbitrary type-2 vectors in
\(\Lambda/2 \Lambda\) to \(\beta\).
Computations in the Leech lattice modulo 3
For the construction of the subgroup \(G_{x0}\) of the monster
we also require the automorphism group \(\mbox{Co}_0\) of the
real Leech lattice, as decribed in [Con85]. That group has
a faithful representation as an automophism group of
\(\Lambda/3 \Lambda\), but not of \(\Lambda/2 \Lambda\).
Module gen_leech3.c provides functions for computing in the
Leech Lattice modulo 3.
Note that in [Sey20] the operation of the generators \(x_d, y_d, x_\delta, x_\pi, \xi\) of \(G_{x0}\) is also defined on the real Leech lattice.
Header file mmgroup_generators.h
The header file mmgroup_generators.h contains definitions for the C files in the generator extension. This extension comprises files mm_group_n.c, gen_xi_functions.c, and gen_leech.c.
In this header we also define an enum MMGROUP_ATOM_TAG_ that specifies the format of an atom that acts as a generator of the monster group.
Defines
-
MMGROUP_ATOM_TAG_ALL
Tag field of a monster group atom
-
MMGROUP_ATOM_DATA
Data field of a monster group atom
-
gen_leech2_def_mul(x1, x2, result)
Macro version of function
gen_leech2_mul.Macro
gen_leech2_def_mul(x1, x2, result)is equivalent to the statementresult = gen_leech2_mul(x1, x2). The macro generates a sequence of statements!Caution:
Here
resultmust be an integer lvalue that is different from both integers,x1andx2!
Enums
-
enum MMGROUP_ATOM_TAG_
In this header file we also define the tags for the atoms generating the Monster group. An element of the monster group is represented as an array of integers of type
uint32_t, where each integer represents an atom, i.e. an atomic element of the monster. An atom represents a triple(sign, tag, value), and is encoded in the following bit fields of an unsigned 32-bit integer:Bit 31 | Bit 30,...,28 | Bit 27,...,0 --------|----------------|---------------- Sign | Tag | Value
Standard tags and values are defined as in the constructor of the Python class
mmgroup.mm, see section The monster group in the API reference. If thesignbit is set, this means that the atom bit given by the pair(tag, value)has to be inverted. In ibid., a tag is given by a small letter. These small letters are converted to 3-bit numbers as follows:Tag | Tag number | Range of possible values i -----|------------|---------------------------- 'd' | 1 | 0 <= i < 0x1000 'p' | 2 | 0 <= i < 244823040 'x' | 3 | 0 <= i < 0x2000 'y' | 4 | 0 <= i < 0x2000 't' | 5 | 0 <= i < 3 'l' | 6 | 0 <= i < 3
A tag with tag number 0 is interpreted as the neutral element. A tag with tag number 7 is illegal (and reserved for future use).
Tags with other letters occuring in the constructor of class
MMare converted to a word of atoms with tags taken from the table above.For tags ‘t’ and ‘l’ the values 0 <= i <= 3 are legal on input.
Values:
-
enumerator MMGROUP_ATOM_TAG_1
Tag indicating the neutral element of the group
-
enumerator MMGROUP_ATOM_TAG_I1
Tag indicating the neutral element of the group
-
enumerator MMGROUP_ATOM_TAG_D
Tag corresponding to ‘d’
-
enumerator MMGROUP_ATOM_TAG_ID
Tag corresponding to inverse of tag ‘d’
-
enumerator MMGROUP_ATOM_TAG_P
Tag corresponding to ‘p’
-
enumerator MMGROUP_ATOM_TAG_IP
Tag corresponding to inverse of tag ‘p’
-
enumerator MMGROUP_ATOM_TAG_X
Tag corresponding to ‘x’
-
enumerator MMGROUP_ATOM_TAG_IX
Tag corresponding to inverse of tag ‘x’
-
enumerator MMGROUP_ATOM_TAG_Y
Tag corresponding to ‘y’
-
enumerator MMGROUP_ATOM_TAG_IY
Tag corresponding to inverse of tag ‘y’
-
enumerator MMGROUP_ATOM_TAG_T
Tag corresponding to ‘t’
-
enumerator MMGROUP_ATOM_TAG_IT
Tag corresponding to inverse of tag ‘t’
-
enumerator MMGROUP_ATOM_TAG_L
Tag corresponding to ‘l’
-
enumerator MMGROUP_ATOM_TAG_IL
Tag corresponding to inverse of tag ‘l’
-
enumerator MMGROUP_ATOM_TAG_1
-
enum gen_ufind_error_type
Error codes for functions in this module.
Unless otherwise stated, the functions in modules
gen_union_find.c, andgen_ufind_lin2.creturn nonnegative values in case of success and negative values in case of failure. Negative return values mean error codes as follows:Values:
-
enumerator ERR_GEN_UFIND_MEM
Out of memory.
-
enumerator ERR_GEN_UFIND_UF_LARGE
Too many entries for union-find algorithm.
-
enumerator ERR_GEN_UFIND_IN_LARGE
Input parameter too large.
-
enumerator ERR_GEN_UFIND_OUT_SHORT
Output buffer too short.
-
enumerator ERR_GEN_UFIND_ENTRY_UF
Entry not in union-find table.
-
enumerator ERR_GEN_UFIND_TABLE_UF
Union-find table too large.
-
enumerator ERR_GEN_UFIND_LIN2_DIM
Dimension n of GF(2)^n is 0 or too large.
-
enumerator ERR_GEN_UFIND_LIN2_GEN
Too many generators for subgroup of SL_2(2)^n.
-
enumerator ERR_GEN_UFIND_INVERSE
Generator matrix is not invertible.
-
enumerator ERR_GEN_UFIND_STATE
Main buffer is not in correct state for this function.
-
enumerator ERR_GEN_UFIND_DUPL
Duplicate entry in union-find table.
-
enumerator ERR_GEN_UFIND_INT_TABLE
-100 .. -199 are internal errors in module gen_union_find.c
-
enumerator ERR_GEN_UFIND_INT_LIN2
-200 .. -299 are internal errors in module gen_ufind_lin2.c
-
enumerator ERR_GEN_UFIND_MEM
C functions implementing the group \(N_{0}\)
We describe an implementation of the subgroup \(N_{0}\) of the monster group.
The subgroup \(N_{0}\) of the monster group of structure
\(2^{2+11+2\cdot 11}.(\mbox{Sym}_3 \times\mbox{M}_{24})\) has been
described in [Con85]. Theorem 5.1 in [Sey20] reduces the
group operation in \(N_{0}\) to easy calculations in the Parker loop
\(\mathcal{P}\), the Colay cocode \(\mathcal{C}^*\), and the group
\({{\rm Aut}_{{\rm St}} \mathcal{P}}\) of standard automorphisms of
\(\mathcal{P}\). The loops \(\mathcal{P}\), \(\mathcal{C}^*\),
and \({{\rm Aut}_{{\rm St}} \mathcal{P}}\) are described in section
Basic structures. Module mat24_functions.c provides the required
functions for computing in these loops.
Using the notation in section The Monster group we may describe an element of \(N_{0}\) as a product:
This representation is unique if we require \(f\) to be in a transversal of \(\mathcal{P} / Z(\mathcal{P})\) and \(\pi\) to be a standard representative in \({{\rm Aut}_{{\rm St}} \mathcal{P}}\) as described in section Automorphisms of the Parker loop.
We store an element of \(N_{0}\) an a quintuple
\(t, f, e, \delta, \pi\) of five integers of type uint32_t.
For \(f, e\) we use the numbering in class PLoop in module
mmgroup; for \(\delta\) we use the numbering in class
Cocode in module mmgroup. Here \(\pi\) refers to a standard
representative in \({{\rm Aut}_{{\rm St}} \mathcal{P}}\). These
standard representatives correspond to the elements of the Mathieu
group \(\mbox{M}_{24}\); and we use the numbering of the elements
of \(\mbox{M}_{24}\) described in class AutPL| in module
mmgroup.
Most functions in module mm_group_n.c take a pointer to a 5-tuple
\((t, f, e, \delta, \pi)\) representing an element \(g\)
of the \(N_{0}\) as their first argument. Then the tuple
representing \(g\) is modified to a tuple representing an
element \(g_2 = g \cdot g_1\), with the element \(g_1\) of
\(N\) given by one or more subsequent arguments of the function.
The functions in module mm_group_n.c may cause some overhead due
to the fact that element of the Mathieu group \(\mbox{M}_{24}\)
is represented as an integer. But compared to an operation of the
monster group on its 196884-dimensional that overhead is negligible.
C interface for file mm_group_n.c
The functions in file mm_group_n.c implement the subgroup \(N_0\) of structure \(2^{2+11+2\cdot11}.(\mbox{Sym}_3 \times \mbox{Mat}_{24})\) on the monster group. Elements of \(N_0\) are represented as arrays of five integers of type uint32_t as described in the document The C interface of the mmgroup project.
Functions
-
void mm_group_n_mul_delta_pi(uint32_t *g, uint32_t delta, uint32_t pi)
Multiply \(g \in N_{0}\) with \(x_\delta x_\pi\).
Put \(g = g x_\delta x_\pi\). Here the integer \(\delta\) represents an element of the Golay cocode and \(\pi\) is the number of an element of \(M_{24}\) corresponding to a standard representative in the automorphism group \(\mbox{AUT}{(\mbox{PL})}\) of the Parker loop.
\(g\) is given as an array of five 32-bit integers.
-
void mm_group_n_mul_inv_delta_pi(uint32_t *g, uint32_t delta, uint32_t pi)
Multiply \(g \in N_{0}\) with \((x_\delta x_\pi)^{-1}\).
Put \(g = g \cdot (x_\delta x_\pi)^{-1}\). Here \(g\), \(x_\delta\), and \(x_\pi\) are as in function
mm_group_n_mul_delta_pi.
-
void mm_group_n_mul_x(uint32_t *g, uint32_t e)
Multiply \(g \in N_{0}\) with \(x_e\).
Put \(g = g \cdot x_e\). Here the integer \(e\) represents an element of the Parker loop.
\(g\) is given as an array of five 32-bit integers.
-
void mm_group_n_mul_y(uint32_t *g, uint32_t f)
Multiply \(g \in N_0\) with \(y_f\).
Put \(g = g \cdot y_f\). Here the integer \(f\) represents an element of the Parker loop.
\(g\) is given as an array of five 32-bit integers.
-
void mm_group_n_mul_t(uint32_t *g, uint32_t t)
Multiply \(g \in N_0\) with the triality element.
Put \(g = g \cdot \tau^t\), where \(\tau\) is the triality element. \(g\) is given as an array of five 32-bit integers.
-
void mm_group_n_clear(uint32_t *g)
Set \(g \in N_0\) to the value of the neutral element.
Put \(g = 1\). Element \(g\) of \(N_0\) is given as an array of five 32-bit integers.
-
void mm_group_n_copy_element(uint32_t *g_1, uint32_t *g_2)
Copy the element \(g_1\) of \(N_0\) to \(g_2\).
Elements \(g_1, g_2\) of \(N_0\) are given as arrays of five 32-bit integers.
-
void mm_group_n_mul_element(uint32_t *g_1, uint32_t *g_2, uint32_t *g_3)
Multiply elemnts of the group \( N_0\).
Put \(g_3 = g_1 \cdot g_2\). Elements \(g_1, g_2, g_3\) of \(N_0\) are given as an array of five 32-bit integers.
These arrays may overlap.
-
void mm_group_n_mul_inv_element(uint32_t *g_1, uint32_t *g_2, uint32_t *g_3)
Multiply \(g_1 \in N_0\) with \(g_2^{-1} \in N_0\).
Put \(g_3 = g_1 \cdot g_2^{-1}\). Elements \(g_1, g_2, g_3\) of \(N_0\) are given as arrays of five 32-bit integers.
These arrays may overlap.
-
void mm_group_n_inv_element(uint32_t *g_1, uint32_t *g_2)
Invert an element \(g_1\) of \(N_0\).
Put \(g_2 = g_1^{-1}\). Elements \(g_1, g_2\) of \(N_0\) are given as arrays of five 32-bit integers.
These arrays may overlap.
-
void mm_group_n_conjugate_element(uint32_t *g_1, uint32_t *g_2, uint32_t *g_3)
Conjugate \(g_1 \in N_0\) with \(g_2 \in N_0\).
Put \(g_3 = g_2^{-1} \cdot g_1 \cdot g_2\). Elements \(g_1, g_2, g_3\) of \(N_0\) are given as arrays of five 32-bit integers.
These arrays may overlap.
-
uint32_t mm_group_n_mul_word_scan(uint32_t *g, uint32_t *w, uint32_t n)
Multiply \(g \in N_0\) with an element of the monster.
Let
wbe a word of generators of the monster group of lengthn. Letkbe the greatest number such that all prefixes ofwof length at mostkare in the group \(N_{0}\). Let \(a\) be the element of \(N_{0}\) corresponding to the prefix ofwof lengthk.Let \(g \in N_{0}\) is given as an array
gof five 32-bit integers.Then the function replaces the value \(g\) in the array
gby \(g \cdot a\). It returns the numberkof atoms of the wordwprocessed.
-
uint32_t mm_group_n_mul_atom(uint32_t *g, uint32_t atom)
Multiply \(g \in N_{0}\) with an atom.
Put \(g = g \cdot a\). Here \(a\) is the generator of the group \(N_0\) given by parameter
atomas described in the header filemmgroup_generators.h.\(g\) is given as an array of five 32-bit integers.
The function returns 0 in case of success and the (possibly simplified) atom in case of failure.
-
uint32_t mm_group_n_scan_word(uint32_t *w, uint32_t n)
Scan word of generators of the monster for membership in \(N_{0}\).
Let
wbe a word of generators of the monster group of lengthn. The function returns the greatest numberksuch that all prefixes ofwof length at mostkare in the group \(N_{0}\).
-
uint32_t mm_group_n_conj_word_scan(uint32_t *g, uint32_t *w, uint32_t n)
Conjugate \(g \in N_0\) with an element of the monster.
Let
wbe a word of generators of the monster group of lengthn. Letkbe the greatest number such that all prefixes ofwof length at mostkare in the group \(N_{0}\). Let \(a\) be the element of \(N_{0}\) corresponding to the prefix ofwof lengthk.Let \(g \in N_{0}\) is given as an array
gof five 32-bit integers.Then the function replaces the value \(g\) in the array
gby \(a^{-1} \cdot g \cdot a\). It returns the numberkof atoms of the wordwprocessed.
-
uint32_t mm_group_n_reduce_element(uint32_t *g)
Reduce \(g \in N_0\) to a standard form.
The representation of \(g\) is reduced to a standard form.
Technically, we reduce the product \(y_f x_e\) to \(y_{f'} x_{e'}\), such that \(0 \leq f' < \mbox{0x800}\) holds. If \(x_e\) is in the center of the Parker loop, but \(x_f\) is not in that center then we put \(x_{e'}=0\).
\(g\) is given as an array of five 32-bit integers.
-
uint32_t mm_group_n_reduce_element_y(uint32_t *g)
Reduce \(g \in N_0\) to a standard form.
The representation of \(g\) is reduced to a standard form.
Here we reduce the product \(y_f x_e\) to \(y_{f'} x_{e'}\), such that \(0 \leq f' < \mbox{0x800}\) always holds.
\(g\) is given as an array of five 32-bit integers.
-
uint32_t mm_group_n_to_word(uint32_t *g, uint32_t *w)
Convert \(g \in N_0\) to a word of generators.
The representation of \(g\) is converted to a word of generators of the monster group. The entries of that word are stored in the buffer referred by parameter
w. The entries of that word are encoded as described in filemmgroup_generators.h. Wordwmay have up to five entries. The function returns the length of the wordw.\(g\) is given as an array of five 32-bit integers.
The element \(g\) is reduced with function
mm_group_n_reduce_element.It is legal to put
w=g.
-
uint32_t mm_group_n_right_coset_N_x0(uint32_t *g)
Map \(g \in N_0\) to an element of \(N_{x0}\).
The function changes the element \(g\) of \(N_0\) to an element \(g'\) of \(N_{x0}\) and returns an exponent \(0 \leq e < 3\) such that \(g = g' \cdot \tau^e\).
-
uint32_t mm_group_n_to_word_std(uint32_t *g, uint32_t *w)
Convert \(g \in N_0\) to a standard word of generators.
The representation of \(g\) is converted to a word of generators of the monster group in the standard order. The entries of that word are stored in the buffer referred by parameter
w.The standard order of the generators of the monster group in the reduced representation of an element of \(N_0\) differs from the order of the generators returned by function
mm_group_n_to_word. Apart from this difference the action of this function is the same as in that function.It is legal to put
w=g.
-
int32_t mm_group_n_conj_to_Q_x0(uint32_t *g)
Transform element of \(N_0\) to an element of \(Q_{x0}\).
Let \(g \in N_x0\) be stored in the array
gof five 32-bit integers.The function tries to calculate a number \(0 \leq e < 3\) and an element \(q\) of the subgroup \(Q_{x0}\) of \(N_0\) with \(g = \tau^{-e} q \tau^e\). Here \(\tau\) is the triality element in \(N_0\).
In case of succes we return the element \(q\) in bits 24,…,0 of the return value in Leech lattice encoding and we return the number \(e\) in bits 26,…,25 of the return value. In case of failure we return -1.
-
uint32_t mm_group_split_word_n(uint32_t *word, uint32_t length, uint32_t *g)
Split an element of \(N_0\) from a word of generators.
Given a array
wordof generators of the monster group of a givenlength, that word is split into a possibly shorter wordword1and an elementgof the group \(N_0\) such thatword=word1*g. Thenword1is a prefix ofword. The function returns the length of the prefixword1ofword. It does not changeword. Here we just scan thewordfrom the right, checking for atoms ordered in a way compatible to our representation of \(N_0\).Words of generators of the monster are implemented as described in file
mmgroup_generators.h. Output \(g\) is given as an array of five 32-bit integers.
-
uint32_t mm_group_mul_words(uint32_t *w1, uint32_t l1, uint32_t *w2, uint32_t l2, int32_t e)
Multiply a word of generators of the monster.
Given a word
w1of lengthl1and a wordw2of lengthl2of generators of the monster group, we compute the productw3=w1 * w2**e. Here**means exponentiation; negative exponents are supported. The wordw1is replaced by the wordw3. The funcion returns the length of the wordw3.A word representing
w2**eis appended to wordw1and then the result is simplified using the relations inside the group \(N_0\). The resultw3is reduced (with respect to these relations) if inputw1is reduced.Caution!
The buffer for the word
w1referred by pointerw1must be able to store at leastl1 + 2 * abs(e) * l2entries of typeuint32_t. Here the user must provide sufficient space!Words of generators of the monster are implemented as described in file
mmgroup_generators.h.
-
void mm_group_invert_word(uint32_t *w, uint32_t l)
Invert a word of generators of the monster.
Given a word
wof lengthlthe function changes the word in the bufferwto its inverse in place.Words of generators of the monster are implemented as described in file
mmgroup_generators.h.
-
uint32_t mm_group_check_word_n(uint32_t *w1, uint32_t l1, uint32_t *g_out)
Check if a words of generators of the monster is in \(N_0\).
We check if the word
w1of lengthl1of generators of the monster group is in the subroup \(N_0\). If this is the case then we store the wordw1as an element of \(N_0\) in the arrayg_outof five 32-bit integers as desribed above. The function returns the following status information:0:
w1is the neutral element the monster group1:
w1is in \(N_0\), but not the neutral element2:
w1is not in \(N_0\)3: Nothing is known about
w1We check the relations in the generators \(N_0\) only. The output in
g_outis valid only if the function returns 0 or 1.Words of generators of the monster are implemented as described in file
mmgroup_generators.h.
-
uint32_t mm_group_words_equ(uint32_t *w1, uint32_t l1, uint32_t *w2, uint32_t l2, uint32_t *work)
Check if two word of generators of the monster are equal.
We check if the word
w1of lengthl1of generators of the monster group is equal to the wordw2of lengthl2of generators. The function returns the following status information:0:
w1==w21:
w1!=w2Greater than 1: equality of
w1andw2is not knownIf the function cannot check the equality of
w1andw2then it computes a wordw3of lengthl3of generators of the monster group such thatw1==w2if and only ifw3is the neutral element. Then the function stores the wordw3in the bufferworkand it returnsl3 + 2.Buffer
workmust have size at leastmax(2 * l1, l1 + 2 * l2).Words of generators of the monster are implemented as described in file
mmgroup_generators.h.
C functions for the operation of \(G_{x0}\) on the Leech lattice
The functions in file gen_leech.c implement the operation of the
subgroup \(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\))
of the monster group on its extraspecial subgroup \(Q_{x0}\)
(of structure \(2^{1+24}\)) by conjugation.
Here an element of the group \(Q_{x0}\) is given as a 25-bit integer in Leech lattice encoding. From that encoding we obtain an encoding of \(\Lambda / 2 \Lambda\) (where \(\Lambda\) is the Leech lattice) by dropping the most significant bit. This corresponds to the isomorphism \(Q_{x0} / \{\pm1\} \cong \Lambda / 2 \Lambda\).
An element of the group \(G_{x0}\) is encoded as an array of
32-bit integers, where each integer corresponds to a generator of
the group, as described in the documentation of the header file
mmgroup_generators.h.
A vector in the Leech lattice modulo 2 has a type and also a subtype
as described in The mmgroup guide for developers, section
Computations in the Leech lattice modulo 2. Here the subtype is a two-digit decimal
number, where the first digit is the type. Function
gen_leech2_subtype returns the subtype as a BCD-coded integer.
E.g. the subtype 46 is returned as the hexadecimal integer 0x46.
So the type can be obtained from the subtype via a shift operation.
For computations in the group \(G_{x0}\) or \(\mbox{Co}_1\)
it is important to find an element of \(G_{x0}\) that maps an
arbitrary type-4 vector in \(\Lambda / 2 \Lambda\) to the unique
type-4 vector \(\Omega\), see Computations in the Leech lattice modulo 2.
Function gen_leech2_reduce_type4 performs this task.
The construction of the group \(G_{x0}\) also requires some
computations in the automorphism group \(\mbox{Co}_0\)
(of structure \(2.\mbox{Co}_1\)) of \(\Lambda\), see
[Con85], section 9 or [Sey20], section 9. The group
\(\mbox{Co}_0\) acts faithfully on \(\Lambda / 3 \Lambda\).
Therefore file gen_leech.c also provides some functions for
dealing with vectors in the Leech lattice modulo 3.
For any \(w \in \Lambda\) the vector
\(v = \sqrt{8} \cdot w\) has integral coordinates. We
represent a vector \(w \in \Lambda / 3 \Lambda\) by the vector
\(v = \sqrt{8} \cdot w\), with the coordinates of \(v\)
taken modulo 3. We represent each coordinate
\(v_i, 0 \leq i < 24\) as a two-bit integer;
so all 48 bits of \(v\) fit into the a 64-bit integer. Let
\(v_{i,1}, v_{i,0}\) be the bits of \(v_{i}\) of
valence \(2^1\) and \(2^0\), respectively. Then we
encode \(v\) as an 48-bit integer \(x\) so that bit
\(24 \cdot j+i\) of \(x\) is equal to \(v_{i,j}\).
This encoding looks peculiar, but it greatly simplifies the
interaction with the functions in file mat24_functions.c. We
call this encoding the Leech lattice mod 3 encoding.
On input, both bits \(v_{i,1}, v_{i,0}\) may be equal to 1;
but on output, at most on of these bits is equal to 1.
In [Sey20], section 9.3, the generators \(x_d, x_\delta, y_\delta, x_\pi, \xi\) of \(G_{x0}\) are also defined as generators of a group \(G_{x1}\) with \(|G_{x1}:G_{x0}| = 2\). The group \(G_{x1}\) operates on \(\Lambda\), but the group \(G_{x0}\) does not. So we take these generators as generators of \(G_{x1}\). The kernel of the operation of \(G_{x1}\) on \(\Lambda\) is the group \(Q_{x0}\) generated by the elements \(x_d, x_\delta, y_{-1}, d \in \mathcal{P}, \delta \in \mathcal{C}\). Here the element \(y_{\Omega}\) acts as the central element \(-1\).
C interface for file gen_leech.c
The functions in file gen_leech.c implement operations on the vectors of the Leech lattice modulo 2 and on the subgroup \(Q_{x0}\). We use the terminology defined in the document The C interface of the mmgroup project, section Description of the mmgroup.generators extension.
Functions
-
uint32_t gen_leech2_mul(uint32_t x1, uint32_t x2)
Return product of two elements the group \(Q_{x0}\).
Here all elements of the group \(Q_{x0}\) are encoded in Leech lattice encoding. The function returns the product of the elements
x1andx2of \(Q_{x0}\).
-
uint32_t gen_leech2_pow(uint32_t x1, uint32_t e)
Return power of element the group \(Q_{x0}\).
Here all elements of the group \(Q_{x0}\) are encoded in Leech lattice encoding. The function returns the power
x1**eof the elementx1of \(Q_{x0}\).
-
uint32_t gen_leech2_scalprod(uint32_t x1, uint32_t x2)
Return scalar product in the Leech lattice modulo 2.
Here all elements of Leech lattice modulo 2 are encoded in Leech lattice encoding**. The function returns the scalar product of the vectors
x1andx2in the Leech lattice modulo 2, which may be 0 or 1.
-
uint32_t gen_leech2_op_word(uint32_t q0, uint32_t *g, uint32_t n)
Perform operation of \(G_{x0}\) on \(Q_{x0}\).
The function returns the element \(g^{-1} q_0 g\) for \(q_0 \in Q_{x0}\) and \(g \in G_{x0}\). Here \(g\) is given as a word of genenators of length \(n\) in the array
g. Each atom of the word \(g\) is encoded as defined in the header filemmgroup_generators.h. Parameter \(q_0\) and the result are encoded in Leech lattice encoding.The function succeeds also in case \(g \notin G_{x0}\) if \(h^{-1} q_0 h \in G_{x0}\) for all prefixes \(h\) of \(g\).
-
uint32_t gen_leech2_op_atom(uint32_t q0, uint32_t g)
Atomic operation of \(G_{x0}\) on \(Q_{x0}\).
Equivalent to
gen_leech2_op_word(q0, &g, 1).
-
uint32_t gen_leech2_prefix_Gx0(uint32_t *g, uint32_t len_g)
Scan prefix in \(G_{x0}\) of a word in the monster group.
Let \(g \in G_{x0}\) be stored in the array
gof lengthlen_gas a word of generators of the subgroup \(G_{x0}\) of the monster. The function returns the maximum lengthlen_gsuch that every prefix of the word ingof length<= len_gis in the group \(G_{x0}\).
-
uint32_t gen_leech2_op_word_many(uint32_t *q, uint32_t m, uint32_t *g, uint32_t n)
Perform operation of \(G_{x0}\) on elements of \(Q_{x0}\).
Let
qbe an array ofmelements \(q_j\) of the group \(Q_{x0}\) in Leech lattice encoding. Let \(g\) be an element of the group \(G_{x0}\) encoded in the arraygof lengthnas in functiongen_leech2_op_word.The function computes the elements \(q'_j = g^{-1} q_j g\) for \(0 \leq j < m\) and stores \(q'_j\) in
q[j].The function applies the same prefix of the word in the array
gto all entries ofq. It stops if the application of any prefix of the word ingto any element \(q_j\) fails; and it returns the length of the prefix ofgthat has been applied to all elements \(q_j\). Hence the function returnsnin case of success and a number0 \leq k < nif not all atoms ofqcould be applied to all entries ofq.The function succeeds on an individual entry \(q_j\) if and only if function
gen_leech2_op_wordsucceeds on the same value.
-
uint32_t gen_leech2_op_word_leech2(uint32_t l, uint32_t *g, uint32_t n, uint32_t back)
Perform operation of \(G_{x0}\) on Leech lattice mod 2.
Let \(g_0 \in G_{x0}\) be stored in the array referred by
gas a word of generators of the subgroup \(G_{x0}\) of the monster. Here \(g_0\) is given as a word of generators of length \(n\) in the arrayg. Each atom of the word \(g\) is encoded as defined in the header filemmgroup_generators.h. Put \(g = g_0\) ifback == 0and \(g = g_0^{-1}\) otherwise.The function returns the element \(l \cdot g\) for a vector \(l\) in the Leech lattice mod 2.
Parameter \(l\) is encoded in Leech lattice encoding, igoring the sign. The function returns \(l \cdot g\), in Leech lattice encoding, with the sign bit set to zero.
The function is optimized for speed. It returns garbage if any generator in the buffer
gis not in \(G_{x0}\).
-
int32_t gen_leech2_op_word_leech2_many(uint32_t *a, uint32_t m, uint32_t *g, uint32_t n, uint32_t back)
Perform operation of \(G_{x0}\) on elements ofLeech lattice mod 2.
Let
abe an array ofmelements \(l_j\) of the Leech lattice mod 2 in Leech lattice encoding. Let \(g_0\) be an element of the group \(G_{x0}\) encoded in the arraygof lengthnas in functiongen_leech2_op_word. Put \(g = g_0\) ifback == 0and \(g = g_0^{-1}\) otherwise.The function replaces each element \(l_j\) in the array
mby \(l_j \cdot g\). Elements \(l_j\) are encoded in Leech lattice encoding, igoring the sign.The function is optimized for speed. It returns zero in case of success. It stores garbage in the array
mand returns a negative value if any generator in the buffergis not in \(G_{x0}\).
-
int32_t gen_leech2_op_word_matrix24(uint32_t *g, uint32_t n, uint32_t back, uint32_t *a)
Convert operation of group \(G_{x0}\) to 24 times 24 bit matrix.
Let \(g_0 \in G_{x0}\) be stored in the array referred by
gas a word of generators of the subgroup \(G_{x0}\) of the monster. Here \(g_0\) is given as a word of generators of length \(n\) in the arrayg. Each atom of the word \(g\) is encoded as defined in the header filemmgroup_generators.h. Put \(g = g_0\) ifback == 0and \(g = g_0^{-1}\) otherwise.The function converts \(g\) to a \(24 \times 24\) bit matrix \(a\) acting on the vectors of the Leech lattice mod 2 (encoded in Leech lattice encoding) by right multiplication. Such matrices form a natural representation of the Conway group \(\mbox{Co}_1\).
The function returns 0 in case of success and a negative value in case of error.
-
void gen_leech2_op_mul_matrix24(uint32_t *a1, uint32_t n, uint32_t *a)
Multiply an n times 24 bit matrix with a 24 times 24 bit matrix.
The function multiplies the
ntimes 24 bit matrixa1with the 24 times 24 bit matrixaand stores the result in matrixa1.Thus array
a1must have lengthn; and arraya1must have length 24.
-
int32_t gen_leech2_map_std_subframe(uint32_t *g, uint32_t len_g, uint32_t *a)
Transform the standard subframe of Leech lattice mod 2
A frame in the Leech lattice \(\Lambda\) is a maximal set of pairwise orthogonal vectors of type 4. In \(\Lambda / 2 \Lambda\) (which is the Leech lattice mod 2) a frame is mapped to a unique vector of type 4. The standard frame \(\Omega\) in \(\Lambda\) consists of the type-8 vectors parallel to the basis vectors in \(\Lambda\).
The subframe \(S(F)\) of a frame \(F\) in \(\Lambda\) is the set \(\{ (u + v)/2 \mid u, v \in F, u \neq \pm v\}\). Any frame \(S(F)\) in \(\Lambda\) contains \(48\) type-4 vectors, and its subframe contains \(48 \cdot 46\) type-2 vectors.
The image of \(S(F)\) in \(\Lambda / 2 \Lambda\) spans a 12-dimensional maximal isotropic subpace \(\langle S(F) \rangle\) of \(\Lambda / 2 \Lambda\), and the type-2 vectors in \(\langle S(F) \rangle\) are precisely images of \(S(F)\).
Then for the standard frame \(\Omega\) we have
\( \langle S(\Omega) \rangle = \{ \lambda_\delta, \lambda_\Omega + \lambda_\delta \mid \delta \in \mathcal{C}^*, \delta \, \mbox{even} \} \) .
Here \(\mathcal{C}^*\) is the Golay cocode, and and \(\lambda_c\) is the element of \(\Lambda / 2 \Lambda\) corresponding to the Golay code or cocode element \(c\).
Then \(\langle S(\Omega) \rangle\) is spanned by \(\lambda_\Omega\) and \(\lambda_{\{0,j\}}, 1 \leq j < 24\). Here \(\{i,j\}\) is the Golay cocode word corresponding to the sum of basis vectors \(i\) and \(j\) of \(\mbox{GF}_2^{24}\).
The elements \(x_\Omega\) and \(x_{\{0,j\}}\) of the group \(Q_{x0}\) are preimages of \(\lambda_\Omega\) and \(\lambda_{\{0,j\}}\) under the natural homomorphism from \(Q_{x0}\) to \(\Lambda / 2 \Lambda\). These elements of \(Q_{x0}\) play an important role in the representation \(196883_x\) of the monster group. For computations in the subgroup \(G_{x0}\) of the monster we sometimes want to compute the images of these elements of \(Q_{x0}\) under conjugation by an element \(g\) of \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
gof lengthlen_gas a word of generators of the subgroup \(G_{x0}\) of the monster. Then this function computes the following 24 elements of \(Q_{x0}\):\( x_\Omega^g, x_{\{0,1\}}^ g, \ldots, x_{\{0,23\}}^g\).
The function stores these 24 elements in the array
a(in that order) in Leech lattice encoding.In case of success the function returns the number of entries of the word
gbeing processed. It returns a negative value in case of failure.
C interface for file gen_leech_type.c
The functions in file gen_leech_type.c implement operations for detecting the type of a vector in the Leech lattice modulo 2.
We use the terminology defined in the document The C interface of the mmgroup project, section Description of the mmgroup.generators extension.
Functions
-
uint32_t gen_leech2_subtype(uint64_t v2)
Return subtype of vector in Leech lattice mod 2.
The function returns the subtype of the vector \(v_2\) in the Leech lattice modulo 2 as a BCD-coded two-digit integer. \(v_2\) must be given in Leech lattice encoding.
The subtype of a vector in the Leech lattice mod 2 is defined in The mmgroup guide for developers, section Computations in the Leech lattice modulo 2.
-
uint32_t gen_leech2_coarse_subtype(uint32_t v2)
A fast, but coarser version of function gen_leech2_subtype.
Let t = gen_leech2_subtype(v2). Then this function returns
0 if t = 0x00
1 if t = 0x48
2 if t = 0x20, 0x40
3 if t = 0x22, 0x42, 0x44
4 if t = 0x46
5 if t = 0x21, 0x43
6 if t = 0x34
7 if t = 0x36
8 if t = 0x31, 0x33
-
uint32_t gen_leech2_type(uint64_t v2)
Return type of a vector in the Leech lattice mod 2.
This function returns the type of the vector \(v_2\) in the Leech lattice modulo 2. That type may be 0, 2, 3, or 4.
This function is a bit faster than function
gen_leech2_subtype().
-
uint32_t gen_leech2_type2(uint64_t v2)
Compute subtype if vector in Leech lattice mod 2 is of type 2.
This function returns the subtype of the vector \(v_2\) in the Leech lattice modulo 2 if \(v_2\) is of type 2 and 0 otherwise.
It is faster than function
gen_leech2_type().
-
uint32_t gen_leech2_count_type2(uint32_t *a, uint32_t n)
Count type-2 vectors in an affine subspace of the Leech lattice mod 2.
This function returns the number of type-2 vectors in an affine subspace \(V\) of the Leech lattice mod 2. Subspace \(V\) is defined by an array \(a\) of length \(n\) of bit vectors. If \(a_1,\ldots,a_{n-1}\) are linear independent then \(V\) is given by:
\(V = \{a_0 + \sum_{i=1}^{n-1} \lambda_i a_i \mid \lambda_i=0,1\}\).
-
int32_t gen_leech2_start_type24(uint32_t v)
Auxiliary function for function gen_leech2_reduce_type4.
The function returns the subtype of a vector \(v\) of type 2 in the Leech lattice modulo 2, provided that \(v + \beta\) is of type 4. It returns 0 in the special case \(v = \beta + \Omega\) and a negative value if \(v\) is not of type 2 or \(v + \beta\) is not of type 4.
It is used for rotating a type-4 vector \(v\) which is orthogonal to \(\beta\) (in the real Leech lattice) into the \(v + \Omega\). That rotation will fix the special short vector \(\beta\).
-
int32_t gen_leech2_start_type4(uint32_t v)
Auxiliary function for function gen_leech2_reduce_type4.
The function returns the subtype of a vector \(v\) of type 4 in the Leech lattice modulo 2. Parameter \(v\) must a vector of type 4 in Leech lattice encoding. The function returns the subtype of \(v\) that will be used for reduction in function
gen_leech2_reduce_type4.This function takes care of the special vectors \(\Omega\) and \(\beta\) the Leech lattice modulo 2.
It is used for rotating a type-4 vector \(v\) into \(\Omega\). If this is possible, that rotation will fix the special short vector \(\beta\).
Therefore the function returns 0 in case \(v = \Omega\). It returns the subtype of \(v + \beta\) if \(\beta\) and \(v + \beta\) are of type 2 and orthogonal in the real Leech lattice.
The function returns a negative value if \(v\) is not of type 4.
C interface for file gen_leech3.c
The functions in file gen_leech3.c implement operations on the vectors of the Leech lattice modulo 3 and on the subgroup \(Q_{x0}\). We use the terminology defined in the document The C interface of the mmgroup project, section Description of the mmgroup.generators extension.
Functions
-
uint64_t gen_leech3_reduce(uint64_t v3)
Return reduced form of a vector in the Leech lattice mod 3.
-
uint32_t gen_leech3_scalprod(uint64_t v3_1, uint64_t v3_2)
Scalar product of two vectors in the Leech lattice mod 3.
The function returns the scalar product of the vectors \(v_{3,1}, v_{3,2}\). The parameters are given in Leech lattice mod 3 encoding. The result is between 0 and 2.
-
uint64_t gen_leech3_add(uint64_t v3_1, uint64_t v3_2)
Add two vectors in the Leech lattice mod 3.
The function returns the sum of the vectors \(v_{3,1}, v_{3,2}\). The parameters and the result are given in Leech lattice mod 3 encoding.
-
uint64_t gen_leech3_neg(uint64_t v3)
Negate a vector in the Leech lattice mod 3.
The function returns the negated vector \(v_{3}\). The parameter and the result are given in Leech lattice mod 3 encoding.
-
uint64_t gen_leech2to3_short(uint64_t v2)
Map short vector from \(\Lambda/2\Lambda\) to \(\Lambda/3\Lambda\).
Here parameter \(v_2\) is a short vector (i.e. a vector of type 2) in \(\Lambda/2\Lambda\) in Leech lattice encoding.
The function returns a short vector in \(\Lambda/3\Lambda\) corresponding to \(v_2\) in Leech lattice mod3 encoding.
The result is unique upto sign only. The function returns 0 if \(v_2\) is not short.
-
uint64_t gen_leech2to3_abs(uint64_t v2)
Map vector from \(\Lambda/2\Lambda\) to \(\Lambda/3\Lambda\).
Here parameter \(v_2\) is a short vector of type 2 or 3. in \(\Lambda/2\Lambda\) in Leech lattice encoding.
The function returns a vector in \(\Lambda/3\Lambda\) corresponding to \(v_2\) in Leech lattice mod3 encoding.
The result is unique upto sign only. The function returns 0 if \(v_2\) is not of type 2 or 3.
-
uint64_t gen_leech3to2_short(uint64_t v3)
Map short vector from \(\Lambda/3\Lambda\) to \(\Lambda/2\Lambda\).
Here parmeter \(v_3\) is a short vector (i.e. a vector of type 2) in \(\Lambda/3\Lambda\) in Leech lattice mod 3 encoding.
The function returns a short vector in \(\Lambda/2\Lambda\) corresponding to \(v_3\) in Leech lattice encoding.
The result is unique. The function returns 0 if \(v_3\) is not short. This function is an inverse of function
gen_leech2to3_short.
-
uint64_t gen_leech3to2(uint64_t v3)
Map vector from \(\Lambda/3\Lambda\) to \(\Lambda/2\Lambda\).
Here parameter \(v_3\) is a vector in \(\Lambda/3\Lambda\) in Leech lattice mod 3 encoding.
If a shortest preimage \(v\) of \(v_3\) in \(\Lambda\) if of type \(t\) with \(t \leq 4\) then the function computes the (unique) vector \(v_2\) in \(\Lambda/2\Lambda\) that has the same preimage \(v\) in \(\Lambda\). Otherwise the function fails.
In case of success the function returns \(2^{24} \cdot t + v_2\), with \(v_2\) given in Leech lattice encoding. The function returns
uint64_t(-1)in case of failure.
-
uint64_t gen_leech3to2_type4(uint64_t v3)
Map type-4 vector from \(\Lambda/3\Lambda\) to \(\Lambda/2\Lambda\).
Here parameter \(v_3\) must be a type-4 vector in \(\Lambda/3\Lambda\) in Leech lattice mod 3 encoding.
The function returns a type-4 vector in \(\Lambda/2\Lambda\) corresponding to \(v_3\) in Leech lattice encoding.
The result is unique. The function returns 0 if \(v_3\) is not of type 4.
-
uint64_t gen_leech3_op_xi(uint64_t v3, uint32_t e)
Special case of function
gen_leech3_op_vector_wordFor internal purposes only. This is equivalent to
gen_leech3_op_vector_word(v3, g), wheregencodes the element \(\xi^e\) of \(G_{x1}\).Parameter \({v_3}\) and the result are given Leech lattice mod 3 encoding.
-
uint64_t gen_leech3_op_vector_word(uint64_t v3, uint32_t *pg, uint32_t n)
Operation of \(G_{x1}\) on the Leech lattice mod 3.
The function returns the element \(v_3 g\) for \(v_3 \in \Lambda/3\Lambda\) and \(g \in G_{x0}\). Here \(g\) is given as a word of genenators of length \(n\) in the array
pg. Each atom of the word \(g\) is encoded as defined in the header filemmgroup_generators.h.Parameter \({v_3}\) and the result are given Leech lattice mod 3 encoding.
-
uint64_t gen_leech3_op_vector_atom(uint64_t v3, uint32_t g)
Atomic operation of \(G_{x1}\) on the Leech lattice mod 3.
Equivalent to
gen_leech3_op_vector_word(v3, &g, 1).Parameter \({v_3}\) and the result are given Leech lattice mod 3 encoding.
C interface for file gen_leech_reduce.c
The functions in file gen_leech_reduce.c implement the transformation of vectors of the Leech lattice modulo 2 to a standard form by applying an element of the subgroup \(G_{x0}\) of the monster.
We use the terminology defined in the document The C interface of the mmgroup project, section Description of the mmgroup.generators extension.
Functions
-
int32_t gen_leech2_reduce_type2(uint32_t v, uint32_t *pg_out)
Map short vector in Leech lattice to standard vector.
Let \(v \in \Lambda / 2 \Lambda\) of type 2 be given by parameter
vin Leech lattice encoding. Then the function constructs a \(g \in G_{x0}\) that maps \(v\) to the standard short vector \(v_0\). Here \(v_0\) is the short vector the Leech lattice propotional to \(e_2 - e_3\), where \(e_i\) is the \(i\)-th basis vector of \(\{0,1\}^{24}\).The element \(g\) is returned as a word in the generators of \(G_{x0}\) of length \(n \leq 6\). Each atom of the word \(g\) is encoded as defined in the header file
mmgroup_generators.h.The function stores \(g\) as a word of generators in the array
pg_outand returns the length \(n\) of that word. It returns a negative number in case of failure, e.g. if \(v\) is not of type 2.Caution:
An input vector allows several outputs. Changing the implementation of this function such that the same input leads to a different output destroys the interoperability between different versions of the project!!
-
int32_t gen_leech2_reduce_type2_ortho(uint32_t v, uint32_t *pg_out)
Map (orthogonal) short vector in Leech lattice to standard vector.
Let \(v \in \Lambda / 2 \Lambda\) of type 2 be given by parameter
vin Leech lattice encoding.In the real Leech lattice, (the origin of) the vector \(v\) must be orthogonal to the standard short vector \(v_0\). Here \(v_0\) is the short vector in the Leech lattice propotional to \(e_2 - e_3\), where \(e_i\) is the \(i\)-th basis vector of \(\{0,1\}^{24}\).
Let \(v_1\) be the short vector in the Leech lattice proportional to \(e_2 + e_3\). Then the function constructs a \(g \in G_{x0}\) that maps \(v\) to \(v_1\) and fixes \(v_0\).
The element \(g\) is returned as a word in the generators of \(G_{x0}\) of length \(n \leq 6\). Each atom of the word \(g\) is encoded as defined in the header file
mmgroup_generators.h.The function stores \(g\) as a word of generators in the array
pg_outand returns the length \(n\) of that word. It returns a negative number in case of failure, e.g. if \(v\) is not of type 2, or not orthogonal to \(v_0\) in the real Leech lattice.Caution:
An input vector allow several outputs. Changing the implementation of this function such that the same input leads to a different output destroys the interoperability between different versions of the project!!
-
int32_t gen_leech2_reduce_type4(uint32_t v, uint32_t *pg_out)
Map a frame in the Leech lattice to the standard frame.
A frame in the Leech lattice \(\Lambda\) is a maximal set of type-4 vectors which are equal modulo \(2 \Lambda\). A frame is equivalent to a type-4 vector in \(\Lambda / 2 \Lambda\).
Let \(v \in \Lambda / 2 \Lambda\) of type 4 be given by parameter
vin Leech lattice encoding. Then the function constructs a \(g \in G_{x0}\) that maps \(v\) to the standard frame \(\Omega\). The standard frame \(\Omega\) consists of the type-4 vectors parallel to the coordinate axes.The element \(g\) is returned as a word in the generators of \(G_{x0}\) of length \(n \leq 6\). Each atom of the word \(g\) is encoded as defined in the header file
mmgroup_generators.h. Let \(H\) be the stabilizer of \(\Omega\). We choose a representative \(g\) in the coset \(gH\) such that the inverse \(g^{-1}\) is a short as possible.The function stores \(g\) as a word of generators in the array
pg_outand returns the length \(n\) of that word. It returns a negative number in case of failure, e.g. if \(v\) is not of type 4.The function uses the method described in the
The mmgroup guide for developers, sectionComputations in the Leech lattice modulo 2.We make one additional assertion.
Let \(v_0\) be the standard short vector in the Leech lattice proportional to \(e_2 - e_3\), where \(e_i\) is the \(i\)-th basis vector of \(\{0,1\}^{24}\). If \(v_0 + v\) is of type 2 then this function computes the same result as function
gen_leech2_reduce_type2_orthoapplied to the vector \(v_0 + v\). In this case the result of this function centralizes \(v_0\). This convention greatly simplifies computations in the baby monster group.Caution:
An input vector allow several outputs. Changing the implementation of this function such that the same input leads to a different output destroys the interoperability between different versions of the project!!
-
uint32_t gen_leech2_type_selftest(uint32_t start, uint32_t n, uint32_t *result)
Test functions
gen_leech2_subtypeandgen_leech2_reduce_type4Function
gen_leech2_subtypemay tested as follows:We compute the subtypes of all \(2^{24}\) vectors \(v \in \Lambda / 2 \Lambda\) and we count the obtained subtypes in an array
resultof length 0x50. The sizes of the orbits of each subtype are known form [Iva99], so a high-level test routine may check the arrayresult.During that process we may also test function
gen_leech2_reduce_type4. Whenever vector of type-4 vector \(v\) occurs, we compute ag \in G_{x0}that maps \(v\) to the standard frame using functiongen_leech2_reduce_type4; and we check the correctness of that mapping using functiongen_leech2_op_word. We return the number of successful such operations. This number must be equal to the number of type-4 vectors in \(\Lambda / 2 \Lambda\).Since this test takes a long time, a high-level function might want to distribute it over several processes. So this function acccumulates the test results for the vectors \(v\) with \(\mbox{start} \leq v < \mbox{start} + \mbox{n}\) only.
-
int32_t gen_leech2_pair_type(uint64_t v1, uint64_t v2)
Isomorphsim type of pair of vectors in Leech lattice mod 2.
Let \(v_1\) and \(v_2\) be two vectors in the Leech lattice mod 2 and put \(v_3 = v_1 + v_2\). Let \(t_i, i = 1,2,3\) be the type of \(v_i\). Then the triple \((t_1, t_2, t_3)\) depends on the isomorphism type of the pair \((v_1, v_2)\).
If one or three of the vectors \((v_1, v_2, v_3)\) are of type 4 then there may be several isomorphism types of pairs \((v_1, v_2)\) with the same triple \((t_1, t_2, t_3)\). In this case we define a subtype \(s\) as follows. We map one of the vectors \(v_i\) of type 4 to the standard frame \(\Omega\). Let \(w\) be the image of any of the vectors \(v_j, j \neq i\) under any such mapping. Then we compute the subtype of \(w\) with function
gen_leech2_subtype, and we let \(s\) be the last hexadecimal digit of the computed subtype. The result \(s\) does not depend on the choices made in the description given above.After reordering \(t_1, t_2, t_3\), the possibilties for tuples \((t_1, t_2, t_3, s)\) with a relevant component \(s\) are (4,2,2,0), (4,3,3,4), (4,3,3,6), (4,4,4,0), (4,4,4,4), (4,4,4,6).
If none of the vectors \((v_1, v_2, v_3)\) is of type 4 then all the shortest corresponding vectors in the Leech lattice are defined up to sign. Then these vectors may span a space of dimension 2 or 3; and we put \(s = 1\) if that dimension is equal to 3, and \(s = 0\) otherwise. The case \(s = 1\) may occur if and only if at least two of the vectors \((v_1, v_2, v_3)\) are of type 3 and none is of type 4.
In all other cases there is at most one such isomorphism type; and we put \(s = 0\).
The function takes \(v_1\) and \(v_2\) as parameters
v1andv2in Leech lattice encding. It returns\( 2^{12} \cdot t_1 + 2^8 \cdot t_2 + 2^4 \cdot t_3 + s .\)
We sketch a proof that the returned result actually describes the isomorphism type of the pair \((v_1, v_2)\). If one of the vectors \((v_1, v_2, v_3)\) is of type 4 then may map that vector to the standard frame \(\Omega\) and check the possible subtypes of the other vectors. These subtypes are described in subsection Computations in the Leech lattice modulo 2 of The guide for developers, or in
[Iva99], Section 4.4 ff.Otherwise the shortest preimages \(v'_1, v'_2, v'_3\) of \(v_1, v_2, v_3\) in the Leech lattice are defined up to sign. The cases where these preimages span a subspace of dimension 2 of the Leech lattice are well known, see e.g.
[CS99]or[CCN+85]. If \(v'_1, v'_2, v'_3\) span a 3-dimensional space, then it is easy to see that at least two of these vectors must be of type 3, and that all vectors \((v'_1 \pm v'_2 \pm v'_3)/2\) (with all possible combinations of signs) are in the Leech lattice and of type at most 3. The 3-dimensional lattices satifying these properties can be shown to be S-lattices, as defined in[CCN+85]. Note that the S-lattices are also known.Warning: This function has not yet been tested!
C interface for file gen_leech_reduce_n.c
Given a vector \(v\) in the extraspecial group \(Q_{x0}\), the functions in this module compute a transformation from \(v\) to a standard representative of the class \(v^N\).
Here \(Q_{x0}\) and \(N = N_{x0}\) are as in the project documentation.
We use the terminology defined in the document The C interface of the mmgroup project, section Description of the mmgroup.generators extension.
Functions
-
int32_t gen_leech2_reduce_n(uint32_t v, uint32_t *pg_out)
Reduce Leech lattice vector modulo the group N_x0.
Given a vector \(v\) in the extraspecial group \(Q_{x0}\), we want to find a standard representative of the class \(v^N\), where \(Q_{x0}\) and \(N = N_{x0}\) are as in the project documentation. Here \(v\) is given in parameter
vin Leech lattice encoding.This function computes such a representative \(v_1 \in Q_{x0}\). It returns an element \(r\) of \(N_{x0}\) with \(v_1 = v^r\) as a word of length three in the generators of \(N_{x0}\). That word is stored in the buffer referred by
pg_outas an array of 3 integers of typeuint32_tas described in section The monster group in the API reference.The user may call function
gen_leech2_op_wordin filegen_leech.cfor computing \(v_1 = v^r\). There is a faster alternative for computing \(v_1\) described in the documetnation of functiongen_leech2_reduce_n.The representative \(v_1\) depends on the subtype of \(v\) only, with one exception listed below. Here the subtype can be also computed by function
gen_leech2_subtypein filegen_leech.c; it is explained in The mmgroup guide for developers in section Computations in the Leech lattice modulo 2.If the subtype of \(v\) is
00then we have \(v_1 =v\) for the two vectors \(v = x_{\pm 1}\) of that subtype.We compute a mapping \(r = x_\pi y_e x_f\), where \(r\) is an automorphism of the Parker loop, \(e\) is in the Parker loop, and \(f\) is either in the Parker loop or in the Golay cocode.
The result \(r\) is in the even subgroup of \(N_{x0}\) except in case \(v = x_{-\Omega}\), where this is not possible.
See section Orbits of the group N_x0 in the group Q_x0 in The mmgroup guide for developers for our choice of the representative of the \(N_{x0}\) orbits.
-
int32_t gen_leech2_reduce_n_rep(uint32_t subtype)
Compute standard representative of Q_x0 modulo the group N_x0.
Given a subtype
subtypein the Leech lattice modulo 2, the function returns a representative of a nonzero orbit of \(Q_{x0}\) under the action of \(N_{x0}\).See the table in section Orbits of the group N_x0 in the group Q_x0 in The mmgroup guide for developers for our choice of such a representative.
C interface for file gen_leech_reduce_22.c
Let \(\Lambda / 2\Lambda\) be the Leech lattice modulo 2. Let \(v_2, v_3 \in \Lambda / 2\Lambda\) with \(\mbox{type}(v_2) = 2\) and \(\mbox{type}(v_3) = \mbox{type}(v_2 + v_3) = t\) for \(2 \leq t \leq 3\). We want to compute the set of all vectors \(v_4 \in \Lambda / 2\Lambda\) of type 4 with \(\mbox{type}(v_2 + v_4) = \mbox{type}(v_3 + v_4) = \mbox{type}(v_2 + v_3 + v_4) = 2\). There are 891 or 100 such vectors in case \(t = 2\) or \(t = 3\), respectively. Function gen_leech2_u4_2xx in this module computes the list of all such vectors.
We motivate this (rather complicated) computation as follows. The main algorithm for the reduction of an element of the Monster in Version v1.0.0 the mmgroup package works in the representation \(\rho_{15}\) of the monster, with coefficients taken mod 15. In future versions it would be faster to work in representation \(\rho_{3}\) instead. For the reduction algorithm we have to compute certain sets \(U_4(v)\) for axis \(v\) in the representation of the Monster as defined in [Sey22]. This computation is considerably more difficult for \(v \in \rho_3\) than for \(v \in \rho_{15}\). It turns out that for \(t = 2,3\) the sets computed above are just the sets \(U_4(v)\) when \(v\) is in the orbit called ‘6A’ or ‘10A’ in [Sey22]. Given an axis \(v \in \rho_3\) in one of these orbits, we can effectively compute suitable vectors \(v_2, v_3\) as discussed above.
For that computation we need a function that maps vectors \(v_2, v_3\) to fixed vectors \(w_2, w_{3t} \in \Lambda / 2\Lambda\). Function gen_leech2_reduce_2xx essentially performs this task; see the documentation of that function for details.
The group fixing \(v_2\) and \(v_3\) is the unitary group \(\mbox{PSU}_6(2)\) in case \(t = 2\), and the Higman-Sims group in case \(t = 3\), see [CS99], Ch. 10.3.4. A detailed discussion of the case \(t = 3\) is given in [CS99], Ch. 10.3.5.
We use the terminology defined in the document The C interface of the mmgroup project, Section Description of the mmgroup.generators extension. Vectors in \(\Lambda / 2\Lambda\) are given in Leech lattice encoding; the sign bit is ignored on input and set to zero on output.
Functions
-
int32_t gen_leech2_n_type_22(uint32_t n)
Generate certain type-2 vectors in the Leech lattice.
The function maps the integers \( 0 \leq n < 4600\) to the 4600 type-2 vectors \(v\) in the Leech lattice mod 2, such that that \(v+w\) is also of type 2 in the Leech lattice mod 2. Here \(w\) is the standard type-2 vector \((0, 0, 4, -4, 0, \ldots, 0)\). Such a vector \(v\) is returned in Leech lattice encoding.
The function returns a negative value in case of failure; e.g. if \(n \geq 4600\).
-
int32_t gen_leech2_find_v4_2xx(uint32_t v2, uint32_t v3, uint64_t *seed)
Support for reducing a certain pair of vectors in the Leech lattice.
Let
v2be a vector of type 2 in the Leech lattice mod 2, and letv3be a vector of type t in the Leech lattice mod 2, with 2 <= t <= 3, such thatv2 + v3is also of type t. Herev2andv3must be given in Leech lattice encoding.The function computes a vector
v4of type 4 such thatv2 + v4, v3 + v4, andv2 + v3 + v4are all of type 2. Vectorv4can be used in functiongen_leech2_find_v4_2xxfor reducing the pair(v2, v3)to a standard pair of vectors.The function returns the value
t * 0x1000000 + v4in case of succcess, with t as above. Parameterseedis a seed for a random generator as described in modulegen_random.c. The function returns a negative value in case of failure.The function tries to find random vectors
vxof type 2 in the Leech lattice mod 2 such that both,vx + v2, andvx + v3are of type 2. Then the vectorv4 = v2 + v3 + vxsatifies the required conditions.For finding
vxwe transformv2to the standard type-2 vector with a transformationtf. Then we generate random type-2 vectors with functiongen_leech2_n_type_22. These random type-2 vectors are interpreted as transformed vectorstf(vx); and we will check the required conditions on the transformed vectorstf(v2),tf(v3), andtf(vx).
-
int32_t gen_leech2_reduce_2xx(uint32_t v2, uint32_t v3, uint32_t v4, uint32_t *g)
Reduce a certain pair of vectors in the Leech lattice.
Let
v2be a vector of type 2 in the Leech lattice mod 2, and letv3be a vector of type t in the Leech lattice mod 2, with 2 <= t <= 3, such thatv2 + v3is also of type t. Herev2andv3must be given in Leech lattice encoding.The function computes an element
gof the Conway group \(\mbox{Co}_1\) such thatv2 * g = w2andv3 * g = w3withw2 = (0, 0, 4, -4, 0, ..., 0). Here we havew3 = (0, 4, -4, 0, ..., 0)ift == 2andw3 = (1, 1, 5, 1, ..., 1)ift == 3.The function stores
gin the arraygas a word of lengthkof generators of the subgroupG_x0of the Monster. These generators are encoded as described in filemmgroup_generators.h. We havek <= 8; so the arraygmust have size at least 8.The function returns the value
k >= 0in case of succcess, and a negative value in case of failure.Parameter
v4must be a type-4 vector satisfying certain conditions as described in de documentation of functiongen_leech2_find_v4_2xx. That function computes a suitable random vectorv4.Internally, we use function
gen_leech2_reduce_type4to find an elementg_0of \(\mbox{Co}_1\) that mapsv4to the standard type-4 vectorOmega. To finish up, we just have to calculate an elementg_1of the subgroup \(2^{11}.M_{24}\) of \(\mbox{Co}_1\) such thatg = g_0 * g_1satisfies the required conditions.
-
int32_t gen_leech2_map_2xx(uint32_t *g, uint32_t n, uint32_t t, uint32_t *a)
Auxiliary function for function
gen_leech2_u4_2xxLet
v2,v3be as in functiongen_leech2_reduce_2xx. Letgbe an element of the groupG_x0of lengthnthat mapsv2andv3tow2andw3, withw2,w3as in functiongen_leech2_reduce_2xx. Heregshould have been computed by that function.The function computes all vectors
v4of type 4 in the Leech lattice mod 2 such thatv2 + v4, v3 + v4, andv2 + v3 + v4are of type 2. It stores the list of these vectors in the arrayaand returns the length of that list.Array
amust have length 891 in caset == 2and length 100 in caset == 3. Other values oftare illegal.
-
int32_t gen_leech2_u4_2xx(uint32_t v2, uint32_t v3, uint64_t *seed, uint32_t *a)
Compute a certain set of type-4 vectors in the Leech lattice mod 2.
Let
v2be a vector of type 2 in the Leech lattice mod 2, and letv3be a vector of type t in the Leech lattice mod 2, with 2 <= t <= 3, such thatv2 + v3is also of type t. Herev2andv3must be given in Leech lattice encoding.The function computes all vectors
v4of type 4 in the Leech lattice mod 2 such thatv2 + v4, v3 + v4, andv2 + v3 + v4are of type 2. There are 891 such vectors in caset = 2and 100 such vectors in caset = 3. The list all these vectors is stored in the arrayain Leech lattice encoding in an undefined order. Thus arrayamust have length at least 891.The function uses a random generator. Parameter
seedis a seed for a random generator as described in modulegen_random.c.The function returns the length of the array
ain case of succcess, and a negative value in case of failure.
C interface for file gen_leech_reduce_mod3.c
The orbits of the automorphism group \(2.\mbox{Co}_{1}\) of the Leech lattice \(\Lambda\) on the vectors of norm up to 22 are described in [CS99], Ch. 10.3.3. There the type of a vector is its halved norm; and a more specific type (e.g. type \(9_{33}\)) is is assigned to each orbit of type 11 or smaller.
Let \(\Lambda / 3\Lambda\) be the Leech lattice mod 3. The automorphism group of \(\Lambda / 3\Lambda\) is also \(2.\mbox{Co}_{1}\). A vector \(v\) in \(\Lambda / 3\Lambda\) has a preimage in \(\Lambda\) of type at most 9; and all shortest preimages of \(v\) in \(\Lambda\) are in the same \(2.\mbox{Co}_{1}\) orbit. So the \(2.\mbox{Co}_{1}\) orbit of a vector in \(\Lambda / 3\Lambda\) may be described by the type of the orbit of its shortest preimage in \(\Lambda\).
Then main function gen_leech3_reduce_leech_mod3 in this module maps a vector in the Leech lattice modulo 3 to a representative of its \(2.\mbox{Co}_{1}\) orbit.
In the following table the first three columns describe the orbits of \(2.\mbox{Co}_{1}\) on \(\Lambda / 3\Lambda\).
Column 1 is the name of the orbit, using the terminoloy in [CS99], Ch. 10.3.3.
Column 2 describes the automorphism group of the orbit.
Column 3 contains the number of shortest vectors of \(\Lambda\) in the orbit.
A vector \(v\) in \(\Lambda / 3\Lambda\) is described by the entries (modulo 3) of any preimage of \(v\) in \(\Lambda\), using the natural co-ordinate frame of \(\Lambda\). The support of vector \(v\) is the set of the nonzero co-ordiantes of \(v\). The support of \(v\) has a natural interpretation as a bit vector in the underlying space \(\mbox{GF}_2^{24}\) of the Golay code used in the construction of \(\Lambda\). The orbits of the automorphism group \(\mbox{M}_{24}\) of the Golay code on \(\mbox{GF}_2^{24}\) are described in [CS99], Ch. 10.2.6. In all but one case all coordinates of our chosen representative of an orbit of \(\Lambda / 3\Lambda\) are 0 or 1.
The last three columns of the table describe our chosen representative \(v\) of an orbit of \(2.\mbox{Co}_{1}\) on \(\Lambda / 3\Lambda\).
Column 4 contains the name of the orbit of the support of \(v\) under the action of \(\mbox{M}_{24}\), as described in [CS99], Ch. 10.2.6.
Column 5 contains the suport of \(v\) as a bit vector. Here we use the basis of the natural co-ordinate frame of \(\Lambda\). This basis corresponds to the basis of \(\mbox{GF}_2^{24}\) described in the mmgroup API reference, section The basis of the Golay code and of its cocode. We adopt the hexadecimal notation for bit vectors in \(\mbox{GF}_2^{24}\) from that section.
Column 6 contains the list of the indices of the coordinates of \(v\) that are equal to -1 (if any).
Leech type |
Aut |
n |
\(\mbox{M}_{24}\) set |
support |
neg |
|---|---|---|---|---|---|
\(0\) |
\(2.\mbox{Co}_{1}\) |
1 |
\((0)\) |
|
|
\(2\) |
\(\mbox{Co}_2\) |
1 |
\(S_2\) |
|
|
\(3\) |
\(\mbox{Co}_3\) |
1 |
\(S_9\) |
|
|
\(4\) |
\(2^{11}.\mbox{M}_{23}\) |
1 |
\(S_1\) |
|
|
\(5\) |
\(\mbox{McL}\) |
1 |
\(T_8\) |
|
|
\(6_{23}\) |
\(\mbox{M}_{24}\) |
1 |
\(U_6\) |
|
|
\(6_{22}\) |
\(\mbox{PSU}_6(2):S_3\) |
3 |
\(S_3\) |
|
|
\(7\) |
\(\mbox{HS}:{2}\) |
2 |
\(U_7\) |
|
|
\(8_{42}\) |
\(2^{1+8}.\mbox{A}_{9}\) |
9 |
\(S_5\) |
|
|
\(9_{33}\) |
\(3^6:2.\mbox{M}_{12}\) |
36 |
\(U_9\) |
|
The group \(\mbox{Co}_{1}\) and its double cover \(2.\mbox{Co}_{1}\)
The action of the generators \(x_d, x_\delta, y_d, x_\pi\), and \(\xi^e\) of the subgroup \(G_{x0}\) of the Monster (given in [Seysen20]) on the Leech lattice \(\Lambda\) is well defined. In other words, these generators are well defined as elements of the automorphism group \(2.\mbox{Co}_{1}\) of \(\Lambda\). Function gen_leech3_reduce_leech_mod3 returns a word in these generators that maps a vector in \(\Lambda / 3\Lambda\) precisely to one of the representatives given in the table above. In the mmgroup package the group generated by these generators is implemented as the subgroup \(G_{x0}\) of structure \(2^{1+24}.\mbox{Co}_1\) of the Monster. Note that \(G_{x0}\) has \(\mbox{Co}_{1}\) as a factor group, but not its double cover \(2.\mbox{Co}_{1}\). As a consequence, the functions in the mmgroup package processing words in \(G_{x0}\) may change the sign of a vector in \(\Lambda / 3\Lambda\). It is easy to recover the sign of a (possibly negated) representative of a \(2.\mbox{Co}_{1}\) orbit in \(\Lambda / 3\Lambda\); so in practice we do not expact any problems here.
How to map a vector in \(\Lambda / 3\Lambda\) to a representative of its orbit
Let the weight of a vector \(v\) in \(\Lambda / 3\Lambda\) be the number of its noznero entries in the natural co-ordiante frame. Here the key idea for finding a representative is to reduce the weight of \(v\) by a sequence of transformations with elements in the group \(2.\mbox{Co}_{1}\), until no further weight reduction is possible. Then we use a transformation in the subgroup \(2^{11}.\mbox{M}_{24}\) of \(2.\mbox{Co}_{1}\) to map the support of the transformed vector \(v\) into a suitable position, as indicated in Column 5 of the table above. Finally, we use a transformation in the subgroup \(2^{11}\) to correct the signs.
An orthogonal transformation does not change the weight of \(v\) modulo 3. The transformation \(\xi\) in \(\mbox{Co}_{1}\) operates orthogonally on each tetrad of the standard sextet. So it does not change the weight (modulo 3) of the projection of \(v\) to any of the tetrads of the standard sextet. Here a tetrad has a natural interpretation a four-dimensional space spanned by the 4 unit vectors corresponding to the entries of the tetrad. Assign a weight \(4^+\) to a tetrad containing four nonzero entries and an even number of entries -1, and a weight \(4^-\) to such a tetrad containing an odd number of entries -1. It is easy to show that the transformation \(\xi\) interchanges the weights 1 and \(4^{\pm 1}\) of a tetrad in the standard sextet as follows:
So in principle we may run through all 1771 sextets, and check if an operation \(\xi^{\pm1}\) applied to \(v\) (after mapping that sextet to the standard sextet via an operation in \(2^{11}.\mbox{M}_{24}\)) will reduce the weight of \(v\). The auxiliary function gen_leech3_find_tetrad_leech_mod3 uses a faster method for finding a suitable sextet, based on the orbit of the support of \(v\) under the action of \(2^{11}.\mbox{M}_{24}\). These orbits are described in [CS99], Ch. 10.2.6.
Here the case that the support of \(v\) is an umbral undecad (in the sense of [CS99], Ch. 10.2.6) requires special attention. Then we have to map \(v\) to a non-umbral undecad (i.e. to a vector of the same weight in a different \(2^{11}.\mbox{M}_{24}\) orbit), before we can reduce the weight of \(v\) any further.
After applying a suitable sequence of such transformation steps, we will obtain a vector with support in one of the \(2^{11}.\mbox{M}_{24}\) orbits mentioned in Column 4 of the table above.
A reference implementation of this procedure is given in the python module mmgroup.dev.generators.gen_leech_reduce_mod3.
Functions
-
int32_t gen_leech3_find_tetrad_leech_mod3(uint64_t a)
Auxiliary function for function
gen_leech3_reduce_leech_mod3This function is not for public use! It tries to find tetrad suitable for reducing a vector in the Leech lattice mod 3.
Let
abe a vector in the Leech lattice mod 3 given in Leech lattice mod 3 encoding. Let thevbe the support ofa, i.e. the bit vector containing the the nonzero entries ofa.The function returns a tetrad
tthat may be used by functionreduce_tetrad_leech_mod3to find an elementgof the group \(\mbox{Co}_1\) such that the support ofa * ghas bit weight less than the weight ofv. The function returns 0 if no such tetrad can be found.This procedure reduces the bit weight of
vbyat least 12 if
vhas bit weight 20, 22, 23, or 24at least 6 if
vhas bit weight 19 or moreat least 3 except in the following cases:
vhas bit weight 5 or less than 4vis an umbral hexad, heptad, nonad or undecadvis a transversal octadvis a special nonad and the unique octad contained invcontains an odd number of entries -1.
For characterizing the bit vector
vwe use the termminology in [CS99], Ch. 10.2.6.If
ais an umbral undecad then the function returns a tetradtsuch thataintersects withtin 3 points, and with all other tetrads in the same sextet in 0 or 2 points. In this special case bit 24 of the return value will be set.The function returns 0 if the bit weight of
vcannot be reduced and a negative value in case of failure.
-
int64_t gen_leech3_reduce_leech_mod3(uint64_t v3, uint32_t *g)
Find orbit of a vector in the Leech lattice mod 3.
This function maps a vector
v3in the Leech lattice (given in Leech lattice mod 3 encoding) to the representativev3'of its orbit under the action of the group \(2.\mbox{Co}_1\). That representative is defined as described in the header of this file. The function also computes an elementgof the group \(2.\mbox{Co}_1\) withv3 * g = v3'.The function stores the group element
gin the buffer referred by the pointergas a word of generators of the group \(G_{x0}\), encoded as described in filemmgroup_generators.h. It returns the value(len_g << 48) + v3', wherelen_gis the length of the word in bufferg, andv3'is also given in Leech lattice mod 3 encoding. The buffer referred bygmust have size at least 12.
C functions for computing with binary matrix groups
C interface for file gen_union_find.c
The functions in file gen_union_find.c implement a union-find algorithm. These function are used in module gen_ufind_lin2.c.
Functions
-
int32_t gen_ufind_init(uint32_t *table, uint32_t length)
Initialize table for union-find algorithm.
The function initializes an array referred by parameter
tablefor performing a union-find algorithm on the setS(length)of integersiwith0 <= i < length. Arraytablemust have sizelength. Here0 <= length <= 0x40000000must hold.Then
tablewill store a partition of the setS(length)in an internal format. Initially, that partition consists of singletons. One may use functiongen_ufind_unionfor joining two sets of that partition. Any set in the partition is represented by an element of that set. The rules for computing a representative of a set are not disclosed to the user. You may use functiongen_ufind_findfor finding the representative of a set. After calling functiongen_ufind_find_all_mineach set is represented by its smallest element. The representative of a set may change after calling functiongen_ufind_union.The function returns 0 in case of success, and a negative value in case of failure (e.g. if
lengthis too big.)
-
int32_t gen_ufind_find(uint32_t *table, uint32_t length, uint32_t n)
The find function for the union-find algorithm.
Let
S(length)be the set of integersiwith0 <= i < length; and let a partition ofS(length)be stored in the arraytable(of sizelength) as described in functiongen_ufind_init.The function returns the representative of the set containing the integer
n. It returns a negative number in case of failure, e.g. ifn >= length.
-
uint32_t gen_ufind_union(uint32_t *table, uint32_t length, uint32_t n1, uint32_t n2)
The union function for the union-find algorithm.
Let
S(length)be the set of integersiwith0 <= i < length; and let a partition ofS(length)be stored in the arraytable(of sizelength) as described in functiongen_ufind_init.The function joins the sets in the partition containg the elements
n1andn2.The function returns 1 if the function unites two dijoint sets, 0 if not, and 0x80000001 in case of any error. So we may ‘or’ the return values to several calls to this function to check if the partition has been changed or an error has occurred.
-
int32_t gen_ufind_find_all_min(uint32_t *table, uint32_t length)
Choose smallest representatives for sets in union-find algorithm.
Let
S(length)be the set of integersiwith0 <= i < length; and let a partition ofS(length)be stored in the arraytable(of sizelength) as described in functiongen_ufind_init.The function chooses the smallest element of a set in a partition as the representative of the set. Thus a subsequent call to function
gen_ufind_findwith parameternreturns the smallest element of the set containgn.The function returns the number of the sets in the partition. A negative return value indicates a error the array
table.After a call to this function entry table[i] is interprated as follows:
if (table[i] & 0x80000000) then the representative of i is i; else if (table[i] < length) then the representative of i is table[i]; else the status of i is erroneous. The case table[i] == i does not occur.
-
int32_t gen_ufind_make_map(uint32_t *table, uint32_t length, uint32_t *map)
Map entries of the partition to their representatives.
Let
S(length)be the set of integersiwith0 <= i < length; and let a partition ofS(length)be stored in the arraytable(of sizelength) as described in functiongen_ufind_init.Function
gen_ufind_find_all_minmust be called before calling this function. Then this function computes an arraymapof the same length as arraytablethat maps each entry of the setS(length)to the smallest element of the partition stored in the arraytable.Output array
mapfor storing that mapping must have sizelength.The function returns 0 in case of success and a negative value in case of failure.
-
int32_t gen_ufind_partition(uint32_t *table, uint32_t l_t, uint32_t *map, uint32_t *ind, uint32_t l_ind)
Output the partition computed by the union-find algorithm.
Let
S(l_t)be the set of integersiwith0 <= i < l_t; and let a partition ofS(l_T)be stored in the arraytable(of sizel_t) as described in functiongen_ufind_init.We assume that the partition stored in the array
tablecontainsn_setssets. Then we store a list of lists in the arraymap, where each list corresponds to a set in the partition. We write some index infomation for interpreting these lists into the arrayindof ll_ind.Array
mapwill contain thel_telements of the setS(l_t)in such a way that for0 <= i < n_setsthei-th set in the partition is equal to the set of integers given bymap[ind[i]], ..., map[ind[i+1] - 1].So the array
indmust have size at leastn_sets + 1; i.e. we must havel_ind > n_sets. Arraymapmust have sizel_t; it may overlap with arraytable. Functiongen_ufind_find_all_minmust be called before calling this function. Note that functiongen_ufind_find_all_minreturnsn_setsin case of success.The entries
map[ind[i]], ..., map[ind[i+1] - 1]corresponding to set in the partition are sorted. The sets of the partition are sorted by their smallest elements.The function returns
n_setin case of success and a negative value in case of failure.
-
int32_t gen_ufind_union_affine(uint32_t *table, uint32_t n, uint32_t *g, uint32_t b)
Perform union-find algorithm in
GF(2)^nLet
S(n)be the set of integersvwith0 <= v < 1 << n; and let a partition ofS(n)be stored in the arraytable(of size1 << n) as described in functiongen_ufind_init.In this function the entries of
S(n)are interpreted as bit vectors. The function joins the set containingvwith the set containingv * g + bfor allvinS(n). Heregis anntimesnbit matrix over GF(2) stored in the array referred byg. Rowjof bit matrixgis stored ing[j]as an integer encoding a bit vector. All bit vector arithmetic is done over GF(2).Thus the array referred by
tablemust have length1 << n; and the array referred bygmust have lengthlen_g * n.The function returns 0 in case of success and -1 in case of error.
C interface for file gen_ufind_lin2.c
The functions in file gen_ufind_lin2.c deal with the operation of a group \(G\) as a permutation group on the vector space \(V = \mbox{GF}_2^n\) for \(n \leq 24\). Such a group is generated by a set of \(n \times n\) bit matrices acting on \(V\) by right multiplication. The functions in this module can compute orbits on \(V\) under the action of \(G\), and representatives and sizes of these orbits. They can also compute Schreier vectors for these orbits, so that we can find an element of \(G\) mapping a vector in an orbit to any other vector in the same orbit.
Function gen_ufind_lin2_init creates an (opaque) array a that will be used for storing information about the action of a group on a vector space \(V = \mbox{GF}_2^n\). Such an array will be called an orbit array. If a function uses an orbit array, this will always be the first parameter of the function; and that parameter will have the name a. The user may add generators of the group \(G\) to orbit array a by calling function gen_ufind_lin2_add.
Once all generators have been added, users may e.g. call function gen_ufind_lin2_rep_v for finding the chosen representative \(w\) of the orbit of a vector \(v \in V\). Then they may then function gen_ufind_lin2_map_v for finding a \(g \in G\) with \(v g = w\).
The functions in this module may be used e.g. for computing the orbits of the Leech lattice mod 2 under the action of (a subgroup of) the Conway group \(\mbox{Co}_1\).
The internal structure of the opaque array a is not described in the public documentation. For details we refer to the explanations in file gen_ufind_lin2_aux.h.
Functions
-
uint32_t gen_ufind_lin2_mul_affine(uint32_t v, uint32_t *m, uint32_t n)
Transform a vector with an affine transformation
Let \(V = GF_2^n\). We store an affine mapping \(V \rightarrow V\) given by \(v \mapsto v \cdot A + b, v, b \in V\), \(A\) an \(n \times n\) bit matrix, in an array
mof \(n + 1\) unsigned 32-bit integers as follows. Rowi,0 <= i < nof matrix \(A\) is stored inm[i]as a bit vector; bit vectorbis stored inm[n].The function returns the bit vector \(v \cdot A + b\).
-
int32_t gen_ufind_lin2_size(uint32_t n, uint32_t k)
Size of a structure for finding orbits in
GF(2)^n.For details we refer to function
gen_ufind_lin2_init.
-
int32_t gen_ufind_lin2_init(uint32_t *a, uint32_t l_a, uint32_t n, uint32_t n_g)
Initialize orbit array for a group acting on
GF(2)^nLet \(G\) be a group acting on a vector space \(V = \mbox{GF}_2^n\). That group is generated by generators \(g_i, 0 \leq i < k\). We store the group (given by its generators) in an opaque orbit array
a. This module provides functions for computing orbits on \(V\) under the action of the group \(G\) from the information stored in the orbit arraya. It also provides a function for finding an element of \(G\) that maps a vector in \(V\) to a (chosen) representative of its orbit.You may use function
gen_ufind_lin2_addto add generatorsg_i, 0 <= i < kto the arrraya. These generators are sored asntimesnbit matrices acting on \(V\) by right multiplication. The maximum number of generators allowd is given by parametern_g.The required length of the orbit array
amay be computed by calling functiongen_ufind_lin2_size(n, n_g). At present the length of ofais approximately2 << nplus the space for storing the generators of the group and their inverses. Limitations aren <= 24andn_g <= 127.Note that \(G\) acts on row vectors in \(\mbox{GF}_2^n\). Such a row vector is encoded in the same way as a row of a matrix
g_i.The function returns 0 in case of success and a negative value in case of error.
-
int32_t gen_ufind_lin2_dim(uint32_t *a)
Given a group acting on
GF(2)^nthe function returnsnLet
abe an orbit array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. The function returns the dimension of the vector space.
-
int32_t gen_ufind_lin2_n_gen(uint32_t *a)
Return number of generators of a group acting on
GF(2)^nLet
abe an orbit array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. The function returns the number of generators of the group.
-
int32_t gen_ufind_lin2_n_max_gen(uint32_t *a)
Return max number of generators of a group acting on
GF(2)^nLet
abe an orbit array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. The function returns the maximum number of generators of the group that can be stored in arraya.
-
int32_t gen_ufind_lin2_pad(uint32_t *a, uint32_t len_a, uint32_t n_max_g)
Increase max number of generators of a group acting on
GF(2)^nThe function tries to pad an orbit array
aas described in functiongen_ufind_lin2_init. Herelen_ais the allocated laength of the orbit arraya, andn_max_gis the requested number of generators group generators to be stored ina.The function returns the new maximum allowed number of generators of the group. It returns a negative value in case of a error.
-
int32_t gen_ufind_lin2_gen(uint32_t *a, uint32_t i, uint32_t *g, uint32_t l_g)
Return a generator of a group acting on
GF(2)^nLet
abe an orbit array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. The function reads a (possibly inverted) generator of the group fromaand writes it into the arraygof lengthl_g. On inputi = 2 * kit stores generatork; and on inputi = 2 * k + 1it stores the inverted generatork. Here0 <= k < gen_ufind_lin2_n_gen(a)must hold.The generator is returned as an integer array of length
n, withn = gen_ufind_lin2_dim(a), encoded as anntimesnbit matrix as \(A\) specified in functiongen_ufind_lin2_init. That function also supports generators \(v \mapsto v \cdot A + b\). In case \(b \neq 0\) we requirel_g > nand store \(b\) ing[n].The function returns
nin case of success and a negative value in case of error; e.g. if the arraygis too short.
-
int32_t gen_ufind_lin2_add(uint32_t *a, uint32_t *g, uint32_t l_g)
Add a generator of a group to an orbit array.
Let
abe an orbit array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. Functiongen_ufind_lin2_addextends the group stored in the orbit array by adding a generator \(g\) to the group.Let \(G\) be the group acting on a vector space \(V = \mbox{GF}_2^n\) stored in the orbit array
a. The group is generated by generators \(g_i, 0 \leq i < k\). We store these generators in the arrayathat must have been initialized with functiongen_ufind_lin2_init. Functiongen_ufind_lin2_addadds a generator \(g\) to the array. Generator \(g\) must given as anntimesnbit matrix \(A\) acting on \(V\) by right multiplication. Herenis given byn = gen_ufind_lin2_dim(). Rowj(with 0 <= j < n) of bit matrix \(A\) must be encoded as a bit vector in the entryg[j]of the array referred by parmametergin the usual way. The lengthl_gof the array referred bygmust be at leastn.Groups acting on \(V\) by an affine transformation are supported. In case
l_g > nthe generator \(g\) acts as the transformation \(v \mapsto v \cdot A + b\), where \(A\) is as above, and \(b\) is the bit vector stored ing[n].Caution: The case \(b \neq 0\) has not yet been tested.
All generators should be added to the orbit array
aimmediately after initialization. Any function retrieving orbit information from that array may trigger a lengthy calculation that makes adding more generators impossible.The function returns 0 in case of success, and a negative value in case of error. An error occurs e.g. if the generator is not invertible.
-
int32_t gen_ufind_lin2_transform_v(uint32_t *a, uint32_t v, uint8_t *b, uint32_t l_b)
Transform a vector by a group element.
Here
arefers to an orbit arrayaencoding a group \(G\) (given by generators) acting on a space of bit vectors. A group element \(g\) is stored as a word of generators of \(G\) of lengthl_bin the array referred byb. An entryiin the arraybcorresponds to the generator given bygen_ufind_lin2_gen(a, i, ...).The function returns the bit vector
vtransformed by the group element \(g\).A negative return value indicates an error.
-
int32_t gen_ufind_lin2_compressed_size(uint32_t *a, uint32_t *o, uint32_t l_o)
Compute size of buffer for compressing an orbit array.
We may compress an orbit array
ato an orbit arrayccontaining not all orbits of arraya, by calling functiongen_ufind_lin2_compress(a, o, l_o, c, l_c). Hierois a list ofl_obit vectors, such that the orbits of these vectors will be added to the orbit arrayc. Functiongen_ufind_lin2_compress_size(a, o, l_o)returns the numberl_cof entries required for the arrayc.
-
int32_t gen_ufind_lin2_compress(uint32_t *a, uint32_t *o, uint32_t l_o, uint32_t *c, uint32_t l_c)
Compress an orbit array.
Let
abe an array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. Here orbit arrayaencodes a group \(G\) acting on a space \(V\) of bit vectors. This function extracts a set of orbits of \(G\) on \(V\) and stores the orbit array containing these orbits in the buffercof lengthl_c. Most of the functions in this module can be applied to the orbit arraycin the same way as to orbit arraya. An error occurs if the buffer is too short. The required buffer length can be computed with functiongen_ufind_lin2_compressed_size. Arrayoof lengthl_ois a list of vectors in \(V\). The orbits of the vectors in that list will be stored in the bufferc.A typical use case is the action of a group on the Leech lattice mod 2. The functions in this module may compute orbits and Schreier vectors for that group. If we are only interested in the action of the group on short vectors only, then we might restrict the orbit array of orbits short vectors. This will save space.
The function returns the actual length of the computed array
cin case of success, and a negative value in case of an error.
-
int32_t gen_ufind_lin2_n_orbits(uint32_t *a)
Return number of orbits a group acting on
GF(2)^nLet
abe an orbit array as described in functiongen_ufind_lin2_init. The function returns the number of orbits (on the vector space under the action of the group) stored in that array.
-
int32_t gen_ufind_lin2_rep_v(uint32_t *a, uint32_t v)
Return representative of orbit of bit vector
vLet
abe an orbit array as described in functiongen_ufind_lin2_init, and letvbe a vector in that space. The function returns a representative of the orbit ofvunder the action of the group. Here vectors are encoded as integers as described in functiongen_ufind_lin2_init.A negative return value indicates an error.
-
int32_t gen_ufind_lin2_len_orbit_v(uint32_t *a, uint32_t v)
Return length of orbit of bit vector
vLet
abe an orbit array as described in functiongen_ufind_lin2_init, and letvbe a vector in that space. The function returns the length of the orbit ofvunder the action of the group. Here vectors are encoded as integers as described in functiongen_ufind_lin2_initA negative return value indicates an error.
-
int32_t gen_ufind_lin2_orbit_v(uint32_t *a, uint32_t v, uint32_t *r, uint32_t l_r)
Return orbit of bit vector
vas an array.Let
abe an orbit array as described in functiongen_ufind_lin2_init, and letvbe a vector in that space. The function writes the orbit ofvunder the action of the group into the arrayrof lengthl_r. Here vectors are encoded as integers as described in functiongen_ufind_lin2_init.The function returns the length of the orbit in case of success. It returns a negative value in case of failure, e.g. if the array
ris too short. One may use functiongen_ufind_lin2_len_orbit_vfor determining the length of the orbit in advance.
-
int32_t gen_ufind_lin2_representatives(uint32_t *a, uint32_t *r, uint32_t l_r)
Return representatives of orbits under the action of a group.
Let
abe an orbit array as described in functiongen_ufind_lin2_init. The function writes a list of representatives of all orbits stored inainto the arrayrof lengthl_r. Here vectors are encoded as integers as described in functiongen_ufind_lin2_init.The function returns the number of these orbits in case of success. It returns a negative value in case of failure, e.g. if the array
ris too short. One may use functiongen_ufind_lin2_n_orbitsfor determining the number of orbits in advance.
-
int32_t gen_ufind_lin2_orbit_lengths(uint32_t *a, uint32_t *r, uint32_t l_r)
Return lengths of orbits under the action of a group.
Let
abe an orbit array as described in functiongen_ufind_lin2_init. Then functiongen_ufind_lin2_representativescomputes a list of representatives of all orbits under the action of the group. This function computes the list of the lengths of all these orbits (in the same order as in functiongen_ufind_lin2_representatives) and writes that list into arrayrof lengthl_r. Parameters and return value are as in functiongen_ufind_lin2_representatives.
-
int32_t gen_ufind_lin2_map_v_gen(uint32_t *a, uint32_t v)
Return entry of Schreier vector for bit vector
vA Schreier vector is a (partial) mapping from a space \(V\) of bit vectors associated with an orbit array
ato the set of generators stored in that array. The image of a bit vector may also beNUL, indicating that the bit vector is the representative of its orbit. For background we refer to [HEOBrien05], Section 4.1.1.A return value
i < 0xferefers to the generator given bygen_ufind_lin2_gen(a, i, ...).Return value
0xfemeans thatNUL, i.e. inputvis the representative of its orbit.Return value
0xffmeans that the Schreier vector forvhas not been computed.A negative return value indicates an error.
-
int32_t gen_ufind_lin2_map_v(uint32_t *a, uint32_t v, uint8_t *b, uint32_t l_b)
Return group element mapping
vto orbit representative.Here
arefers to an orbit arrayaencoding a group \(G\) (given by generators) acting on a space \(V\) of bit vectors. The function computes an element \(g\) of \(G\) that maps the bit vectorvto the representative of its orbit.Element \(g\) is computed as a word of generators of \(G\) of length
l_band stored in the array referred byb. An entryiin the arraybto the generator given bygen_ufind_lin2_gen(a, i, ...).A negative return value indicates an error.
-
int32_t gen_ufind_lin2_finalize(uint32_t *a)
Compute all possible information about orbits.
Let
abe an array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. Some information to be stored inais computed on demand only. Before writing the arrayato a file, it may be useful to store the maximum possible amount of infomation ina. This function performs that task.
-
int32_t gen_ufind_lin2_check(uint32_t *a, uint32_t len_a)
Check an array representing a group acting on
GF(2)^nLet
abe an orbit array as described in functiongen_ufind_lin2_init. This function performs some checks on the arraya. It returns an nonnegative value if the data inaappear to be consistent, and negative value otherwise. In case of a negative return value the arrayamay not be used!
-
int32_t gen_ufind_lin2_check_finalized(uint32_t *a, uint32_t len_a)
Check if an orbit array has been finalized.
Let
abe an orbit array as described in functiongen_ufind_lin2_init. This function checks if the arrayaof lengthlen_ahas been finalized by calling functiongen_ufind_lin2_finalize. The function returns the actual size of the arrayaif this is the case and a negative otherwise. Note the a finalized array contains an internal checksum.
-
int32_t gen_ufind_lin2_get_map(uint32_t *a, uint32_t *map, uint32_t l_map)
Output mapping computed by the union-find algorithm.
Let
abe an orbit array that stores a group acting on a vector spacevoverGF(2)as described in functiongen_ufind_lin2_init. Letnbe the dimension of that vector space as returned by functiongen_ufind_lin2_dim. The function computes a mapping from the vectors inVto a set of representatives of the orbits onVunder the action of the group. The function writes this mapping into the arraymapof sizel_map.Thus
l_map >= 1 << nmust hold. The function returns the actual length1 << nof the arraymap. It returns a negative value in case of failure, e.g. if the arraymapis too short.
-
int32_t gen_ufind_lin2_get_table(uint32_t *a, uint32_t *t, uint32_t l_t)
Output main table computed by the union-find algorithm.
Let
abe an orbit array that stores a group acting on a vector spacevoverGF(2)as described in functiongen_ufind_lin2_init. Letnbe the dimension of that vector space as returned by functiongen_ufind_lin2_dim. The function copies the main table from the arrayato the arraytof lengthl_tas is. Herel_t >= 1 << nmust hold. The function returns the actual length1 << nof the arrayt. It returns a negative value in case of failure, e.g. if the arraytis too short.
-
int32_t gen_ufind_lin2_orbits(uint32_t *a, uint32_t *t, uint32_t l_t, uint32_t *x, uint32_t l_x)
Output the partition computed by the union-find algorithm.
Let
abe an orbit array that stores a group acting on a vector space as described in functiongen_ufind_lin2_init. Arrayacontains the set of orbits in the vector space under the action of the group.Alternatively, this set of orbits could be computed with the union-find algorithm described in function
gen_ufind_lin2_init. Assume thattableis a table generated with the union-find algorithm corresponding to the set of orbits in the arrayagenerated by functiongen_ufind_lin2_init.Then
gen_ufind_lin2_orbits(a, map, l_map, ind, l_ind)is equivalent togen_ufind_partition(table, l_t, map, ind, l_ind)Here the length of that table is
l_t = 1 << gen_ufind_lin2_dim(a). The length of the arraymapis equal tol_map = l_t. The length of the arrayindis equal tol_ind = gen_ufind_lin2_n_orbits(a) + 1.
C functions for the generator \(\xi\) of the monster group
Reference implementation for module gen_xi_functions.c
The methods in class GenXi in this module are a reference
implementations of the functions in module gen_xi_functions.c.
These functions deal with the operation of the generator
\(\xi\) of the monster defined in [Sey20],
Section 9, on a subgroup \(Q_{x0}\), and also with the monomial
part of that operation on the 196884-dimensional representation
\(\rho\) of the monster.
Generator \(\xi\) is an element of the subgroup
\(G_{x0}\) of the monster. It operates on the normal subgroup
\(Q_{x0}\) of \(G_{x0}\) of structure \(2^{1+24}\)
by conjugation as described in cite:Seysen20, Lemma 9.5.
Method gen_xi_op_xi of class GenXi implements the
operation of the generators \(\xi^e\) on the group
\(Q_{x0}\). Here the elements of \(Q_{x0}\) are given
in Leech lattice encoding, as described in
The C interface of the mmgroup project, Section
Description of the mmgroup.generators extension.
Representation \(\rho\) has a subspace \(98280_x\) of dimension 98280 on which \(G_{x0}\) operates monomially in the same way as it operates on the short elements of \(Q_{x0}\). Here the basis vectors of \(98280_x\) (together with their opposite vectors) can be identified with the short elements of \(Q_{x0}\).
For a fast implementation of the operation of \(\xi^e\) on \(98280_x\) we precompute tables as described in the mmgroup guide for developers, Section Some mathematical aspects of the implementation, Subsection Implementing generators of the Monster group, Subsubsection Monomial operation of the generators xi^e. We adopt the terminology from that subsection.
In that subsection the basis vectors of \(98280_x\) are subdivided into five boxes, so that \(\xi\) acts as a permutation on these boxes. Within each of these boxes the basis vectors of \(98280_x\) are numbered in a natural way as described in that subsection. Operator \(\xi\) permutes the five boxes 1,…,5 as follows:
1 -> 1, 2 -> 2, 3 -> 4 -> 5 -> 3 .
For each short vector in \(Q_{x0}\) we encode the number of the box containing the vector, the position of the vector inside the box, and and the sign of the vector in the lowest 19 bits of a 32-bit integer as follows:
Bit 18…16: number of the box, running from 1 to 5.
Bit 15: sign bit
Bit 14…0: Entry inside the box
We call this encoding the Short vector encoding of a short vector in \(Q_{x0}\).
Methods gen_xi_short_to_leech and
gen_xi_leech_to_short in class GenXi convert elements of
\(Q_{x0}\) from Leech lattice encoding to
Short vector encoding and vice versa.
Method gen_xi_op_xi_short uses these two methods together with
method gen_xi_op_xi in order to compute the operation of
\(\xi^e\) on a vector in \(98280_x\) encoded in
Short vector encoding.
Using method gen_xi_op_xi_short we may easily compute tables for
the operation of \(\xi\) and \(\xi^2\) on a specific box.
Method gen_xi_make_table computes an array containing the lower
16 bits of the images of the entries of a box under the operation
\(\xi^e\). Bits 18…16 of these images can be reconstructed
from the permutation of the boxes given above.
C interface for file gen_xi_functions.c
The functions in file gen_xi_function.c correspond to the python functions in class mmgroup.dev.generators.gen_xi_ref.GenXi. They are used for computing the tables required for implementing the operation of generator \(\xi\) on the representation \(\rho_p\) of the Monster.
Functions
-
uint32_t gen_xi_g_gray(uint32_t v)
Compute function \(\gamma\) on a Golay code element.
Here parameter \(v\) is encoded in
gcoderepresentation, and the return value \(\gamma(v)\) is encoded incocoderepresentation. These representations are defined in the Description of the mmgroup.mat24 extension.
-
uint32_t gen_xi_w2_gray(uint32_t v)
Compute function \(w_2\) on a Golay code element.
Here parameter \(v\) is encoded in
gcoderepresentation as defined in the Description of the mmgroup.mat24 extension. The function returns \(w_2(v)\), which may be 0 or 1.
-
uint32_t gen_xi_g_cocode(uint32_t c)
A kind of an inverse of function \(\gamma\).
Given a cocode element \(c\) in
cocoderepresentation, the function returns the unique grey Golay code vector \(v\) such that \(\gamma(v)\) is equal to the grey part of \(c\). \(v\) is returned ingcoderepresentation, see the Description of the mmgroup.mat24 extension.
-
uint32_t gen_xi_w2_cocode(uint32_t v)
Compute function \(w_2\) on a Golay cocode element.
Here parameter \(v\) is encoded in
cocoderepresentation as defined in the Description of the mmgroup.mat24 extension. The function returns \(w_2(v)\), which may be 0 or 1.
-
uint32_t gen_xi_op_xi(uint32_t x, uint32_t e)
Conjugate an element of the group \(Q_{x0}\) with \(\xi^e\).
The function returns \(\xi^{-e} x \xi^e\) for an element \(x\) of the group \(Q_{x0}\). Input \(x\) and the return value are encoded in Leech lattice encoding as described above.
-
uint32_t gen_xi_op_xi_nosign(uint32_t x, uint32_t e)
Similar to function
gen_xi_op_xi, ingoring sign.The function returns \(\xi^{-e} x \xi^e\) for an element \(x\) of the group \(Q_{x0}\). Input \(x\) and the return value are encoded in Leech lattice encoding as described above. This function computes the result up to sign only.
-
uint32_t gen_xi_leech_to_short(uint32_t x)
Convert the encoding of an element of the group \(Q_{x0}\).
The function converts an element \(x\) of the group \(Q_{x0}\) from Leech lattice encoding to Short vector encoding and returns the converted element.
-
uint32_t gen_xi_short_to_leech(uint32_t x)
Convert the encoding of an element of the group \(Q_{x0}\).
The function converts an element \(x\) of the group \(Q_{x0}\) from Short vector encoding to Leech lattice encoding and returns the converted element.
An invalid value \(x\) is converted to 0.
-
uint32_t gen_xi_op_xi_short(uint32_t x, uint32_t u)
Conjugate an element of the group \(Q_{x0}\) with \(\xi^e\).
The function returns \(\xi^{-e} x \xi^e\) for an element \(x\) of the group \(Q_{x0}\). In contrast to function gen_xi_op_xi, the input \(x\) and the return value are encoded in short vector encoding as described above.
Any invalid element \(x\) is converted to \(x\).
-
uint32_t gen_xi_make_table(uint32_t b, uint32_t e, uint16_t *ptab)
Create table for operation of \(\xi^e\),.
The function creates a table
ptabsuch thatptab[i]encodes \(\xi^{-e} x \xi^e\), where \(x = 2^{16} \cdot b + i\) encodes a short vector in \(Q_{x0}\) in Short vector encoding. The length of the gererated table is \(l(b) = 2496, 23040, 24576, 32768, 32768\) for \(b = 1,2,3,4,5\).Here
ptab[i]contains the lower 16 bits of the table entry only, with bit 15 equal to the sign bit. The upper 3 bits ofptab[i]depend onbonly; they can be deduced from the permutation of the boxesb = 1,...,5by \(\xi\) described above.Not all table indices
icorrespond to short vectors. We putp[i] = ifor all invalid indicesi.
-
void gen_xi_invert_table(uint16_t *ptab, uint32_t len, uint32_t ncols, uint16_t *pres, uint32_t len_res)
Invert a table created by function
gen_xi_make_tableThe function computes the inverse table of a table
ptabof lengthlencreated by functiongen_xi_make_tableand stores the inverse table in the buffer referred bypres.Parameter
len_resis the length of the returned table. Parameterncolsmust be 24 or 32. This means that only entriesptab[32*i + j]with0 <= j < ncolsare valid.The details of the inversion of such a table are rather tricky; they are coded in class
mmgroup.dev.mm_basics.mm_tables_xi.Pre_MM_TablesXi. The purpose of this function is to speed up the calculations in that class.
-
void gen_xi_split_table(uint16_t *ptab, uint32_t len, uint32_t mod, uint32_t *psign)
Split a table created by function
gen_xi_invert_tableThe function splits the sign bit from a table
ptabof lengthlencreated by functiongen_xi_invert_tableand replacesptab[i]by(ptab[i] & 0x7fff) % mod. The sign bitptab[32*i+j] >> 15is stored in bitjof entrypsign[i].The purpose of this function is to speed up the computations in class
mmgroup.dev.mm_basics.mm_tables_xi.Pre_MM_TablesXi.
C functions implementing a random generator
The python extension mmgroup.generators provides a random
generator. Its main purpose is the very fast generation of
a vector of integers modulo \(p\) for the representation
\(\rho_p\) of the monster group for small numbers \(p\).
The internal operation of the random generator is described in
file gen_random.c. Here we describe the python interface
of the random generator.
This interface is given by a set of functions that can be
imported from python module mmgroup.generators.
A python function dealing with the randon generator requires
a seed. Here a seed is either an object returned by function
rand_make_seed or None (default).
The default seed is (hopefully) thread save, and it is initialized from volatile sources such as the time, the process and the thread id, etc.
A seed created by function rand_make_seed is initalized
from a fixed source (which is a 64-bit integer).
Each seed may be used by one thread only. In python a seed is crreated for each thread whenever needed.
Python functions in module mmgroup.generators
The following functions should be imported from
module mmgroup.generators.
- .rand_get_seed()
Return the seed associated with the current thread
This function is used for obtaining a suitable python object for calling a C function that deals with the random generator. The user must not modify that seed!
- .rand_make_seed(valu)
Create a deterministic seed object for the random generator
The function creates a seed object and returns that object. It is intialized with parameter
value, which must be an unsigned 64-bit integer.
- .rand_bytes_modp(p, num_bytes, seed=None)
Return a random array of integers mod p
The function returns a one-dimensional numpy array of uniform distributed random integers
xwith0 <= x < p. That array has lengthnum_bytesand hasdtype = numpy.uint8.Parameter
seedmust be eitherNone(default, referring to the default seed) or a seed object created by functionrand_make_seed.
- .rand_fill_bytes_modp(p, array_bytes, seed=None)
Fill an existing array with random integers mod p
The function fills the one-dimensional numpy array
array_byteswith uniform distributed random integersxwith0 <= x < p. That array must havedtype = numpy.uint8.Parameter
seedmust be eitherNone(default, referring to the default seed) or a seed object created by functionrand_make_seed.
- .rand_gen_modp(p, seed=None)
Return random integer
xwith0 <= x < p.Here 1 <= p <= 2**32 must hold.
Parameter
seedmust be eitherNone(default, referring to the default seed) or a seed object created by functionrand_make_seed.
C interface for file gen_random.c
File gen_random.c provides a fast random generator for creating random vectors in the representations of the monster group. This generator supports very fast generation of long random vectors of integers modulo p for p <= 256.
The seed for such a random generator is given by an array of type uint64_t seed[MM_GEN_RNG_SIZE]. In this version we have MM_GEN_RNG_SIZE = 4.
The function gen_rng_seed(uint64_t *seed) fills an existing array seed of that type with random seed data. See description of that function for details. The idea is that in a mulithreading environment every thread has its own random generator. There is also a function gen_rng_seed_no for a determistic intialization of the seed. The user should call function gen_rng_seed_init for initialization.
The function gen_rng_bytes_modp(uint32_t p, uint8_t *out, uint32_t len, uint64_t *seed) writes len uniform random numbers x_i with 0 <= x_i < p to the array referred by the pointer out. Here 1 < p <= 256 must hold.
This function is optimized for generating large random vectors with, say, len >= 1000, as required for the representation of the monster.
Function gen_rng_modp generates a single random number x with 0 <= x < p for a 32-bit number p.
Internal operation.
We use the xoshiro256** pseudo random number generator, see
https://bashtage.github.io/randomgen/bit_generators/xoshiro256.html
We seed a master generator from various external random sources, e.g. the system time, the process id, etc. We use xoshiro256** for both, the master and the user generator. We shift the master generator by 2**128 steps for seeding a user generator.
Functions
-
void gen_rng_seed_init(void)
Seed the master random generator with random data.
Here
seedis an array of 4 integers of typeuint64_t.The function fills the
seedwith random data, using various sources, e.g. the system time, the process id, etc.
-
void gen_rng_seed_no(uint64_t *seed, uint64_t seed_no)
Seed a user random generator deterministically.
Here
seedis an array of 4 integers of typeuint64_t.The function fills the
seedwith data depending on the numberseed_no.
-
void gen_rng_seed(uint64_t *seed)
Seed a user random generator from the master random generator.
Here
seedis an array of 4 integers of typeuint64_t.The function seeds the user generator with the seed
seedfrom the master random generator. The function is thread-safe if functiongen_rng_seed_init()has been called before.Each thread must use its own seed.
-
int32_t gen_rng_bytes_modp(uint32_t p, uint8_t *out, uint32_t len, uint64_t *seed)
Generate random integers modulo a small number
pGenerate an array of length
lenof random 8-bit integersxwith0 <= x < p. Here1 < p <= 256must hold.These random integers are written to the array referred by
out.Parameter
seedpoints to the seed for the random generator. That seed must have been created by functiongen_rng_seed_rndor by a similar function.The function returns zero in case of success and a nonzero value otherwise.
-
uint32_t gen_rng_modp(uint32_t p, uint64_t *seed)
Generate one random integer modulo a number
pGenerate an integer
xwith0 <= x < p. Here0 <= p < 2**32must hold.p = 0is interpreted asp = 2**32.Parameter
seedpoints to the seed for the random generator. That seed must have been created by functiongen_rng_seed_rndor by a similar function.The function returns the random number
x.
-
uint64_t gen_rng_bitfields_modp(uint64_t p, uint32_t d, uint64_t *seed)
Generate random bit field of integers modulo a number
pGenerate integers
x_i,0 <= i < 64 / dwith0 <= x < p. Here parameterdis the with of a bit field. The function reuturns an unsigned 64-bit integerxwith the random valuex_istored in bitsi*d + d - 1,..., i *dofx. In cased = 0we generate one random number inx.Here
1 <= p < 2**dmust hold.p = 0is interpreted asp = 2**64.Parameter
seedpoints to the seed for the random generator. That seed must have been created by functiongen_rng_seed_rndor by a similar function.
-
double gen_rng_uniform(uint64_t *seed)
Return a uniform random number 0 <= x < 1.
Parameter
seedpoints to the seed for the random generator. That seed must have been created by functiongen_rng_seed_rndor by a similar function.
-
uint32_t gen_rng_uniform_to_dist(double x, uint32_t n, double *dist)
Convert real number to an index with a given distibution.
Given a uniform random number
0 <= x < 1, the function returns an integer0 <= i <= nwith a distribution specifed by parameterdist. Heredistmust be an array of lengthn, wheredist[j]is the probability thati > jholds. Thus the sequence of the entries of arraydistmust be increasing.
-
void gen_rng_int_dist(uint64_t *seed, uint32_t n, double *dist, uint32_t *a, uint32_t l_a)
Sample array of integers according to a given distibution.
Let
abe an array of integers of lengthl_a. The function fills the arrayawith random integers0 <= i <= naccording to a given distibution. That distribution is described by parametersdistandnin the same way as in functiongen_rng_uniform_to_dist.Parameter
seedpoints to the seed for the random generator. That seed must have been created by functiongen_rng_seed_rndor by a similar function.
Description of the mmgroup.clifford12 extension
Quadratic state vectors
The C functions in modules qstate.c and qsmatrix.c perform
operations on quadratic state matrices given by triples
\((e, A, Q)\) as described in API reference the section
Long-term stable storage of vectors of the representation.
A quadratic state vector \(v\) of type
qbstate12_type with component ncols = n models a complex
vector in a vector space \(V\) of dimension \(2^n\),
or an \(2^{n-k} \times 2^k\) matrix.
The basis of vector space \(V\) is labelled by the elements of the Boolean vector space \(\mathbb{F}_2^n\). In C and python programs we represent the element \((x_{n-1}, \ldots, x_{0})\) of \(\mathbb{F}_2^n\) by the integer \(\sum_{0 \leq i < n} 2^i \cdot x_i\). This leads to a natural representation of a vector \(v \in V\) as a one-dimensional complex array of length \(2^n\), starting with index \(0\).
A quadratic state matrix is a quadratic shape vector augmented
by an information about its matrix shape. For more details we
refer to the description of struct qbstate12_type in file
clifford12.h.
Header file clifford12.h
File
clifford.his the header file for shared librarymmgroup_clifford12.Defines
- QSTATE12_UNDEF_ROW
Marker for an undefined row index in function qstate12_row_table()
- QSTATE_SUPPORT_MAXCOLS
Max No of columns allowed for matrix in struct qstate12_support_type
Enums
- enum qstate12_error_type
Error codes for functions in this module.
Unless otherwise stated, the functions in modules
qstate.c,qmatrix.c, andxsp2co1.creturn nonnegative values in case of success and negative values in case of failure. Negative return values mean error codes as follows:Values:
- enumerator ERR_QSTATE12_NOTFOUND
No object with the requested property found.
- enumerator ERR_QSTATE12_INCONSISTENT
State is inconsistent.
- enumerator ERR_QSTATE12_QUBIT_INDEX
Qubit index error.
- enumerator ERR_QSTATE12_TOOLARGE
State is too large for this module.
- enumerator ERR_QSTATE12_BUFFER_OVFL
Buffer overflow; usually there are now enough rows available.
- enumerator ERR_QSTATE12_Q_NOT_SYMM
Bit matrix part Q is not symmetric.
- enumerator ERR_QSTATE12_BAD_ROW
Bad row index for bit matrix.
- enumerator ERR_QSTATE12_INTERN_PAR
Internal parameter error. Usually a bad row has been requested.
- enumerator ERR_QSTATE12_SCALAR_OVFL
Overflow or underflow in scalar factor.
- enumerator ERR_QSTATE12_CTRL_NOT
Bad control_not gate. A qubit in a ctrl-not gate cannot control itself.
- enumerator ERR_QSTATE12_SHAPE_COMP
Shape mismatch in comparing matrices.
- enumerator ERR_QSTATE12_SCALAR_INT
Scalar factor is not an integer.
- enumerator ERR_QSTATE12_PARAM
Parameter error.
- enumerator ERR_QSTATE12_DOMAIN
Matrix is not is the expected domain.
- enumerator ERR_QSTATE12_SHAPE_OP
Shape mismatch in matrix operation.
- enumerator ERR_QSTATE12_MATRIX_INV
Matrix is not invertible.
- enumerator ERR_QSTATE12_PAULI_GROUP
Matrix is not in the Pauli group.
- enumerator ERR_QSTATE12_NOT_MONOMIAL
Matrix is not monomial.
- enumerator ERR_QSTATE12_LEECH_OP
Internal error in operation of group Co_0.
- enumerator ERR_QSTATE12_REP_GX0
Error in operation of group 2^{1+24}.Co_1.
- enumerator ERR_QSTATE12_NOTIN_XSP
Element of G_x0 not in 2^{1+24}.
- enumerator ERR_QSTATE12_GX0_TAG
Bad tag for atom in group G_x0.
- enumerator ERR_QSTATE12_GX0_BAD_ELEM
Bad element of group G_x0.
- enumerator ERR_QSTATE12_LEECH_SHORT
Vector in Leech lattice must be short.
- struct qstate12_type
#include <clifford12.h>Description of a quadratic state matrix.
More precisely, a variable of this type decribes the representation \((e', A, Q)\) of a quadratic mapping \(f(e', A, Q)\). Here \(A\) is an \((1+m) \times n\) bit matrix. \(Q\) is a symmetric \((1+m) \times (1+m)\) bit matrix representing an symmetric bilinear form. We always have \(Q_{0,0}=0\). Then the quadratic mapping \(f(e', A, Q): \mathbb{F}_2^n \rightarrow \mathbb{C} \) is given by
\[ f(e',A,Q)(x) = e' \cdot \sum_{{\{{y = (y_0,\ldots,y_m) \in \mathbb{F}_2^{m+1} \mid y_0 = 1, y \cdot A = x\}}}} \exp \left( \frac {\pi \sqrt{{-1}}}{2} \sum_{j,k=0}^m Q_{j,k} y_j y_k \right) \, . \]Matrices \(A\) and \(Q\) are concatenated to an \( (m+1) \times (n+m+1)\) matrix \(M\) such that \(M_{i,j} = A_{i,j}\) for \(j < n\) and \(M_{i,j} = Q_{i-n,j}\) for \(j \geq n\). Matrix \(M\) is encoded in a one-dimensional array of unsigned 64-bit integers. Here bit \(j\) of entry \(i\) of the array corresponds to \(M_{i,j}\), with bit \(0\) the least significant bit.
We do not update column \(0\) of matrix \(Q\). \(Q_{j,0}\) is inferred from \(Q_{0,j}\) for \(j>0\) and we always have \(Q_{0,0} = 0.\)
We also interpret a quadratic mapping \( f \) from \(\mathbb{F}_2^n\) to \(\mathbb{C}\) as a complex \(2^{n-k} \times 2^k\) matrix \(U\) with entries \(U[i,j] = f(b_0,\ldots,b_{n-1})\), where \((b_{n-1},...,b_0)_2\), is the binary representation of the integer \(i \cdot 2^k + j\), and \(k\) is given by component
shape1of the structure.The current implementation requires \(n + m <= 63\), so that all columns of the bit matrix \(M\) fit into a 64-bit integer. With this restriction we may still multiply \(2^{12} \times 2^{12}\) matrices \(U\) given as quadratic mappings.
A quadratic mapping may be reduced with function qstate12_reduce() without notice, whenever appropriate.
Warning:
If an external function changes any component of a structure
qsof typeqstate12_type(or the content ofqs.data) then it must setqs.reducedto zero. The onlylegal way to
set
qs.reducedto a nonzero value is to call functionqstate12_reduce. The functions in this module assume thatqsis actually reduced ifqs.reducedis not zero.Public Members
- uint32_t maxrows
No of entries of type
uint64_tallocated to componentdata
- uint32_t nrows
No \(m + 1\) of rows of bit matrix \(A\) The value
nrows = 0encodes the zero mapping.
- uint32_t ncols
No \(n\) of columns of bit matrices \(A\) and \(Q\).
- int32_t factor
A integer \(e\) encoding the complex scalar factor \(e'=\) \(\exp(e \pi \sqrt{-1}/4) \cdot 2^{\lfloor e/16 \rfloor / 2}\)
- uint32_t shape1
Describes the shape of the quadratic state matrix as explained above.
- uint32_t reduced
This is set to 1 if the state is reduced and to 0 otherwise.
- uint64_t *data
Pointer to the data bits of the matrix \(M = (A,Q)\).
- struct qstate12_support_type
#include <clifford12.h>Structure
qstate12_support_typefor reading data a state.This structure is created by function
qstate12_support_initin fileqstateio.cfor traversing the support (i.e. the set of nonzero entries) of a quadratic state. For details we refer to the documentation of fileqstateio.c.Public Members
- uint32_t size
Total size of the quadratic state; a power of 2.
- uint32_t weight
No of nonzero entries of of matrix; 0 or a power of 2.
- int32_t factor
Scalar factor, encoded as in the structure
qstate12_type
- uint32_t factor_new
1 if factor has changed, 0 otherwise
- uint32_t batchlength
Size of a batch; 0 or a power of 2.
- uint32_t n_batches
Total number of batches.
- uint32_t indices[64]
Indices contained in the current batch.
- uint8_t signs[64]
Signs of entries of the current batch.
Private Members
- uint32_t lb_batchlength
binary logarithm of member batchlength
- qstate12_type qs
Copy of state to be processed.
- uint64_t buf[30 + 1]
Buffer for member pqs.
- uint64_t qf
Current value of high part of quadratic form.
- uint64_t assoc
Current value of linear part for quadratic form.
- uint32_t i
Current (high) index of iterator.
- uint32_t c_weight
Value of i where to switch imaginary part.
C functions in bitmatrix64.c
File
bitmatrix64.ccontains functions for computing with bit matrices. A bit matrix of up to 64 columns is stored in an array of integers of typeuint64_t. If matrixmis stored in the arrayathen entrym[i,j]is given by bitjof the entrya[i]of the arraya. Here bitjhas valence \(2^j\).In functions dealing with bit matrices we always give the number of rows as a parameter. In some functions we also give the number of columns. In other functions we assume that there are 64 columns, with unused columns ignored.
Functions
- uint32_t uint64_parity(uint64_t v)
Returns the parity of a 64-bit integer
v.
- uint32_t uint64_low_bit(uint64_t v)
Returns position of lowest bit of a 64-bit integer
v.In case
v = 0the function returns 64.
- uint32_t uint64_bit_len(uint64_t v)
Returns the bit length of a 64-bit integer
v.
- uint32_t uint64_bit_weight(uint64_t v)
Returns the bit weight of a 64-bit integer
v.
- uint32_t uint64_to_bitarray(uint64_t v, uint8_t *bl)
Convert 64-bit integer
vto a bit list.Return the (sorted) array
blof the positions of all bits set in the integerv. The function returns the length of the computed array, which is equal to the bit weight ofv. Arrayblshould have length at least 64. The function is optimized for integersvof low bit weight.
- void bitmatrix64_add_diag(uint64_t *m, uint32_t i, uint32_t j)
Add a diagonal matrix to a bit matrix.
Here bit matrix
mhasirows.We add one to all entries
m[k, j+k]for0 <= k < i.
- void bitmatrix64_mask_rows(uint64_t *m, uint32_t i, uint64_t mask)
Mask rows of a bit matrix.
Here bit matrix
mhasirows.We replace all rows
m[k]ofmbym[k] & mask. So we zero the entriesm[i,j]for alljwhere bitjis zero in parametermask.
- int32_t bitmatrix64_find_masked_row(uint64_t *m, uint32_t i, uint64_t mask, uint64_t v)
Find (masked) row of a bit matrix with a certain value.
Here bit matrix
mhasirows.The function returns the lowest index
ksuch thatm[k] & mask == vholds. The function returns ERR_QSTATE12_NOTFOUND if no suchkexists.
- int32_t bitmatrix64_to_numpy(uint64_t *m, uint32_t rows, uint32_t cols, uint8_t *a)
Convert bit matrix to numpy array.
Here bit matrix
mhasrowsrows andcolscolumns.Then
abust be an array ofrows * colsbytes length. The function writes the bitm[i,j]toa[i * cols + j].The function returns rows * cols in case of success and ERR_QSTATE12_NOTFOUND in case of failure, e.g. if
cols > 64.
- void bitmatrix64_from_32bit(uint32_t *a32, uint32_t n, uint64_t *a64)
Copy array of 32-bit integers to array of 64-bit integers.
Copy the array
a32ofn32-bit integers to the arraya64ofn64-bit integers. Entries of the array are zero extended.
- void bitmatrix64_to_32bit(uint32_t *a32, uint32_t n, uint64_t *a64)
Copy array of 64-bit integers to array of 32-bit integers.
Copy the array
a64ofn64-bit integers to the arraya32ofn32-bit integers. Upper 32 bits of the entries are dropped.
- uint32_t bitmatrix64_find_low_bit(uint64_t *m, uint32_t imin, uint32_t imax)
Find position of lowest bit in a bit matrix.
The function returns the lowest position
kof a bit in the bit matrixm, which is set to one. It scans only the bits at positionsimin <= k < imax. If all bits at these positions are zero then the function returnsimax.Here bit
jofm[i]is considered at position64*i + j. Bit matrixmshould have at least(imax + 63) >> 6entries.
- void bitmatrix64_mul(uint64_t *m1, uint64_t *m2, uint32_t i1, uint32_t i2, uint64_t *m3)
Bit matrix multiplication.
Here
m1andm2havei1andi2rows, respectively. Only the lowesti2columns ofm1are inspected. Matrixm2may have any number of columns, up to 64.The function computes the matrix product
m1 * m2in the arraym3. Matrixm3hasi1rows and the same number of columns asm2.Array
m3may be equal to arraym1; but it may not overlap withm2.
- uint64_t bitmatrix64_vmul(uint64_t v, uint64_t *m, uint32_t i)
Multiplication of a vector with a bit matrix.
Here matrix
mhasirows; andvis a bit vector. The function returns the product of the bit vectorvwith the bit matrixm. If bit vectorvhaskleading zero bits then only the lowest64 - krows of matrixmare inspected.
- int32_t bitmatrix64_rot_bits(uint64_t *m, uint32_t i, int32_t rot, uint32_t nrot, uint32_t n0)
Rotate columns of a bit matrix.
Here bit matrix
mhasirows.For
n0 <= j < n0 + nrotwe map columnjof matrixmto columnn0 + (j + rot) % nrot. E.g.nrot = 3, rot = 1, n0 = 0means that columns are mapped as0->1, 1->2, 2->0.The function returns 0 in case of success and a negative value if any column with index >= 64 is involved in the rotation.
- int32_t bitmatrix64_xch_bits(uint64_t *m, uint32_t i, uint32_t sh, uint64_t mask)
Exchange columns of a bit matrix.
Here bit matrix
mhasirows.Exchange column
jwith columnj + shof the bit matrixm, if bitjofmaskis set. If bitjofmaskis set then bitj + shofmaskmust not be set. No bit ofmaskat position greater or equal to64 - shmay be set.E.g.
qstate12_xch_bits(m, 1, 0x11)maps columns (…,6,5,4,3,2,1,0) to columns (…,6,4,5,3,2,0,1).The function returns 0 in case of success and a negative value if any column with index >= 64 is involved in the operation.
- int32_t bitmatrix64_reverse_bits(uint64_t *m, uint32_t i, uint32_t n, uint32_t n0)
Reverse columns of a bit matrix.
Here bit matrix
mhasirows.The function reverses
ncolumns of the bit matrixmstarting at columnn0. So it exchanges bitm[k, n0 + j]with bitm[k, n0 + n - 1 - j]for0 <= j < nand0 <= k < i.The function returns 0 in case of success and a negative value if any column with index >= 64 is involved in the operation.
- int32_t bitmatrix64_t(uint64_t *m1, uint32_t i, uint32_t j, uint64_t *m2)
Transpose a bit matrix.
Here
m1is anitimesjbit matrix. Here bitm1[m,n]is given by(m1[m] >> n) & 1. The function writes the transposed bit matrix ofm1tom2.
- uint32_t bitmatrix64_echelon_h(uint64_t *m, uint32_t i, uint32_t j0, uint32_t n)
Convert bit matrix
mto reduced row echelon form.Matrix
mhasirows. Here we assume that the leading bit of a row of matrixmis the most significant bit in that row. For echelonizingm, we pivot over nolumnsj0-1,...,j0-nin that order, ignoring the other columns. We perform row operations (on all possible columns 0,…,63) for changing matrixm.The function returns the number of rows in the (echelonized) matrix
mthat have a nonzero bit in at least one of the pivoted columns.
- uint32_t bitmatrix64_echelon_l(uint64_t *m, uint32_t i, uint32_t j0, uint32_t n)
Convert bit matrix
mto reduced row echelon form.Matrix
mhasirows. Here we assume that the leading bit of a row of matrixmis the least significant bit in that row. For echelonizingm, we pivot over columnsj0,...,j0+n-1in that order, ignoring the other columns. We perform row operations (on all possible columns 0,…,63) for changing matrixm.The function returns the number of rows in the (echelonized) matrix
mthat have a nonzero bit in at least one of the pivoted columns.
- int32_t bitmatrix64_cap_h(uint64_t *m1, uint64_t *m2, uint32_t i1, uint32_t i2, uint32_t j0, uint32_t n)
Compute intersection of row spaces of two bit matrices.
Bit matrix
m1hasi1rows, and bit matrixm2hasi2rows. Both matrices,m1andm2, must be given in reduced echelon form in the sense of functionbitmatrix64_echelon_h.The function changes
m1andm2using row operations in such a way that the lower rows ofm1andm2contain the intersection of the rows spaces of the two matrices. For computing that intersection we consider only columnsj0-1,...,j0-nof matricesm1andm2. However, we do each row operation on all possible columns63,...,0.The function returns the dimension
n_capof the intersection of the row spaces ofm1andm2, ignoring all columns except for columnsj0-1,...,j0-n.Assume that the echelonized input matrices
m1(andm2) haver1(andr2) leading rows that have at least one nonzero bit in columnsj0-1,...,j0-n, respectively. Then the function changes the leadingr1rows ofm1and the leadingr2rows ofm2only. These rows are changed in such a way that the lastn_capof these rows of the two matrices are equal in columnsj0-1,...,j0-n. So these last rows contain the intersection of the row spaces ofm1andm2, ignoring all columns butj0-1,...,j0-n.Parameters
j0andnmust be the same in this function, and in the previous two calls to functionbitmatrix64_echelon_hused for echelonizing matricesm1andm2. This function computes garbage in the arraysm1andm2, unless both matrices,m1andm2, have been echelonized in that way before calling this function.A negative return value
n_capmeans that at least one of the input matricesm1andm2has not been echelonized correctly. This function may or may not detect an incorrect echelonization of an input matrix.
- int32_t bitmatrix64_inv(uint64_t *m, uint32_t i)
Bit matrix inversion.
Here
mhasirows andicolumns.i <= 32must hold. The function inverts matrixmin place.It returns 0 in case of success and
ERR_QSTATE12_MATRIX_INVifmis not invertible.
- int64_t bitmatrix64_solve_equation(uint64_t *m, uint32_t i, uint32_t j)
Solve a linear bit equation.
Let
Mbe the bit matrix withirows andjcolumns stored in the arraymin the usual way. Letvbe the column bit vector stored in columnjof the arraym.Then the function tries to solve the equation
m * x = vfor a column vectorx. If such a solutionxexists then the function returns the transposed vector of the column vectorxas a nonnegative integer.The function returns
ERR_QSTATE12_MATRIX_INVif no solutionxexists. As a side effect, it echelonizes the lowestj + 1columns of matrixmwith functionbitmatrix64_echelon_l.
C functions in uint_sort.c
File
uint_sort.ccontains functions for sorting arrays of unsigned 32-bit and 64-bit integers.Functions
- void bitvector32_copy(uint32_t *a_src, uint32_t n, uint32_t *a_dest)
Copy an array to type
uint32_t[]Copy the array
a_srcof lengthntoa_dest. Any kind of overlap is supported.
- void bitvector32_heapsort(uint32_t *a, uint32_t n)
Sort an array
aof lengthnwith heap sort.Here
ais an array ofnintegers of typeuint32_t. The array is sorted in place. The function is exported for debuging. You should use functionbitvector32_sort.
- void bitvector32_sort(uint32_t *a, uint32_t n)
Sort an array
aof typeuint32_t[]of lengthnHere
ais an array ofnintegers of typeuint32_t. The array is sorted in place.We use quicksort as the main sorting algorithm. If quicksort reaches a certain recursion level then we switch to heap sort. This guarantees a run time of \(O(n \mathop{log}(n))\). For small arrays we use insert sort.
- uint32_t bitvector32_bsearch(uint32_t *a, uint32_t n, uint32_t v)
Binary search in a sorted array of type
uint32_t[]Here
ais a sorted array ofnintegers of typeuint32_t.Given a vector
vto be searched in the arraya, the function returns the lowest indexiwith0 <= i < nsuch thatv <= a[i]holds. The function returnsn-1in casev > a[n-1]. It returns0in casen = 0.This function can e.g. be used for searching in an array where a key is stored in the high bits, and the value for that key is stored in the low bits of an entry of the (sorted) array:
uint32_t key; // Key to search in array ``a`` of length ``n`` #define V_BITS 8 // Lower 8 bits are value, upper bits are key uint32_t x = a[bitvector32_bsearch(a, n, key << V_BITS)]; if ((x >> V_BITS) == key) print("value for key %d is %d", key, x & ((1 << V_BITS) - 1)); else print("key %d not found", key);
- void bitvector64_copy(uint64_t *a_src, uint32_t n, uint64_t *a_dest)
Copy an array to type
uint64_t[]Copy the array
a_srcof lengthntoa_dest. Any kind of overlap is supported.
- void bitvector64_heapsort(uint64_t *a, uint32_t n)
Sort an array
aof lengthnwith heap sort.Here
ais an array ofnintegers of typeuint64_t. The array is sorted in place. The function is exported for debuging. You should use functionbitvector64_sort.
- void bitvector64_sort(uint64_t *a, uint32_t n)
Sort an array
aof typeuint64_t[]of lengthnHere
ais an array ofnintegers of typeuint64_t. The array is sorted in place.We use quicksort as the main sorting algorithm. If quicksort reaches a certain recursion level then we switch to heap sort. This guarantees a run time of \(O(n \mathop{log}(n))\). For small arrays we use insert sort.
- uint32_t bitvector64_bsearch(uint64_t *a, uint32_t n, uint64_t v)
Binary search in a sorted array of type
uint64_t[]Here
ais a sorted array ofnintegers of typeuint64_t.Given a vector
vto be searched in the arraya, the function returns the lowest indexiwith0 <= i < nsuch thatv <= a[i]holds. The function returnsn-1in casev > a[n-1]. It returns0in casen = 0.This function can e.g. be used for searching in an array where a key is stored in the high bits, and the value for that key is stored in the low bits of an entry of the (sorted) array:
uint64_t key; // Key to search in array ``a`` of length ``n`` #define V_BITS 8 // Lower 8 bits are value, upper bits are key uint64_t x = a[bitvector64_bsearch(a, n, key << V_BITS)]; if ((x >> V_BITS) == key) print("value for key %d is %d", key, x & ((1 << V_BITS) - 1)); else print("key %d not found", key);
C functions in qstate12.c
File
qstate12.ccontains functions for quadratic state matrices as described in the API reference in section Computation in the Clifford group.C functions in this module are prefixed with
qbstate12_. Unless otherwise stated, these functions return anint32_t, where a nonegative value is interpreted as success, and a negative value is intepreted as failure. Error codes are documented in fileclifford12.h.Typical names for parameters of functions in this module are:
Name | Parameter type -------------- | ---------------------------------------------- pqs, pqs1, ... | Pointer to structure of type qbstate12_type nqb | Number of qubits, i.e. of columns of matrix | A in a structure of type qbstate12_type. nrows | Number of rows of matrix A or Q | in a structure of type qbstate12_type. i, i1, ... | Index of a row of matrix A or Q , | starting with 0. j, j1, ... | Index of a column of matrix A , with a | column of A , corrsesponding to a qubit, | starting with j = 0. | If appropriate, an index j >= ncols refers | to column (j - ncols) of matrix Q . pv, pv1,... | Pointer to a row or column vector of matrix | A, Q or M .Functions
- int32_t qstate12_check(qstate12_type *pqs)
Check a structure of type
qstate12_type.Return 0 if ok, or an error code if there is any error in the structure referred by
pqs. PartQ[i,0]is set toQ[0, i]. PartQ[0,0]is set ot 0. Irrelevant data bits in valid data rows are zeroed.
- int32_t qstate12_set_mem(qstate12_type *pqs, uint64_t *data, uint32_t size)
Assign memory to a structure of type
qstate12_type.Assign the array
dataofsizeintegers of typeuint64_tas memory to structure of typeqstate12_typereferred bypqs.
- int32_t qstate12_zero(qstate12_type *pqs, uint32_t nqb)
Set a structure of type
qstate12_typeto a zero vector.Set the structure referrred by
pqsto a zero column vector of length2**nqb, corresponding to the zero state ofnqbqubits.
- int32_t qstate12_vector_state(qstate12_type *pqs, uint32_t nqb, uint64_t v)
Set a structure of type
qstate12_typeto a state vector.Set the structure referrred by
pqsto a unit column vector|v>of length2**nqb. Thus for the quadratic mappingqsreferred bypqswe haveqs(x) = 1ifxis equal to the bit vectorvandqs(x) = 0otherwise.
- int32_t qstate12_set(qstate12_type *pqs, uint32_t nqb, uint32_t nrows, uint64_t *data, uint32_t mode)
Set a data in a structure of type
qstate12_typeSet
pqs->nqb = nqbso that the stateqsreferred bypqscorresponds to a column vector of length2**nqb. Setpqs->nrows = nrows, and copynrowsrows of the arraydatatopqs->data.If
mode == 1then copy the upper triangular part of the data bit matrix partQto the lower triangular part.If
mode == 2then copy the lower triangular part of the data bit matrix partQto the upper triangular part.Otherwise the part
Qof the data bit matrix must be symmetric.The resulting state is checked with function qstate12_check().
- int32_t qstate12_copy(qstate12_type *pqs1, qstate12_type *pqs2)
Copy a state of type
qstate12_typeto another state.Copy the data in the state referred by
pqs1to the data in the state referred bypqs2. Memory must have been allocated to the statepqs2with function qstate12_set_mem()
- int32_t qstate12_copy_alloc(qstate12_type *pqs1, qstate12_type *pqs2, uint64_t *data, uint32_t size)
Copy a state of type
qstate12_typeand allocate mamory.Equivalent to
qstate12_set_mem(pqs2, data, size); qstate12_copy(pqs1,pqs2);
- int32_t qstate12_factor_to_complex(int32_t factor, double *pcomplex)
Convert a scalar factor to a complex number.
The function takes a scalar
factor(as given by the componentfactorin the structureqstate12) and converts that factor to a complex number. The real part of the result is returned inpcomplex[0]and the imaginary part inpcomplex[1].Caution:
If bit 3 of
factoris set then the function calculates the complex number 0.The function returns:
4 if the result is complex, but not real. 3 if the result is real, but not rational. 2 if the result is rational, but not integral. 1 if the result is integral, but not zero. 0 if the result is zero. ERR_QSTATE12_SCALAR_OVFL in case of overflow or underflow
- int32_t qstate12_factor_to_int32(int32_t factor, int32_t *pi)
Convert a scalar factor to a 32-bit integer.
The function takes a scalar
factor(as given by the componentfactorin the structureqstate12) and converts that factor to an integer. That integer is stored inpi[0].Caution:
If bit 3 of
factoris set then the function calculates the integer zero.The function returns:
1 if the result is integral, but not zero.
0 if the result is zero.
ERR_QSTATE12_SCALAR_OVFL in case of overflow or underflow
ERR_QSTATE12_SCALAR_INT if the result is not an integer
- int32_t qstate12_conjugate(qstate12_type *pqs)
Conjugate the state referred by
pqsThe function changes the state referred by
pqsto its complex complex state.
- int32_t qstate12_mul_scalar(qstate12_type *pqs, int32_t e, uint32_t phi)
Multiply the state referred by
pqsby a scalar.The function multiplies the state
qsreferred bypqswith the scalar2**(e/2) * exp(phi * pi * sqrt(-1) / 4) .
- int32_t qstate12_abs(qstate12_type *pqs)
Replace entries of a state by their absolute values.
The function replaces the entries of the state referred by
pqsby their absolute values.
- uint64_t qstate12_get_column(qstate12_type *pqs, uint32_t j)
Return column
jof the bit matrixMstored inpqs->dataas a bit vector in an integer of typeuin64_t.
- int32_t qstate12_del_rows(qstate12_type *pqs, uint64_t v)
Delete all rows
i, 1 <= i < pqs->nrows,from the bit matrixMstored inpqs->data, if bitiin the bit vector*pvis set. Here we also adjust the quadratic formQwhich is part of the bit matrixM. Row 0 is never deleted.
- int32_t qstate12_insert_rows(qstate12_type *pqs, uint32_t i, uint32_t nrows)
Insert
nrowszero rows into the bit matrixMstored inpqs->data, starting before rowi. The corresponding zero columns of the quadratic formQ, which is part of the bit matrixM, are also inserted.1 <= i <= nrowsmust hold. This process multiplies the state vector by the scalar2**nrows.
- int32_t qstate12_mul_Av(qstate12_type *pqs, uint64_t v, uint64_t *pw)
Let
Mbe the bit matrix stored inpqs->data. We return the matrix productw = A * Transposed(v), whereAis theApart of the bit matrixM, as a bit vector.
- int32_t qstate12_rot_bits(qstate12_type *pqs, int32_t rot, uint32_t nrot, uint32_t n0)
Rotate qubit arguments of the state
qsreferred bypqs.For
n0 <= i < n0 + nrotwe map qubitito qubitn0 + (i + rot) % nrot. E.g.nrot = 3, rot = 1, n0 = 0means that bits are mapped as0->1, 1->2, 2->0. Letnn1 = pqs->ncols. Then the function changes the quadratic mappingqsto referred bypqstoqs1withqs1(x[nn1-1],...,x[n0+nrot],y[nrot-1],...,y[0],x[n0-1],...,x[0]) = qs(x[nn1-1],...,x[n0+nrot],z[nrot-1],...,z[0],x[n0-1],...,x[0]),where
z[j] = y[j - rot (mod 3)].
- int32_t qstate12_xch_bits(qstate12_type *pqs, uint32_t sh, uint64_t mask)
Exchange qubit arguments of the state
qsreferred bypqs.Exchange qubit
jwith argument bitj + shof the stateqsreferred bypqs, if bitjofmaskis set. If bitjofmaskis set then bitj + shofmaskmust not be set. No bit ofmaskat position greater or equal topqs->ncols - shmay be set.E.g.
qstate12_xch_bits(pqs, 1, 0x11)changes the quadratic mappingqstoqs1withqs1(...,x6,x5,x4,x3,x2,x1,x0) = qs(...,x6,x4,x5,x3,x2,x0,x1) .
- void qstate12_pivot(qstate12_type *pqs, uint32_t i, uint64_t v)
Pivot rows of a state matrix.
Let
Mbe the bit matrix stored inpqs->data. The pivoting process is controlled by the bit vectorv. Ifk < iand bitkofvis set then rowiof bit matrixMis xored to rowkofM. The columns of the partQofMare also adjusted.1 <= i < pqs->nrowsmust hold. Pivoting does not change the state.For internal use only. Input conditions are not checked.
- void qstate12_pivot_rot_rows(qstate12_type *pqs, uint32_t fst, uint32_t last)
Rotate some rows of a state matrix down by one step.
Let
Mbe the bit matrix stored inpqs->data. We move rowiof the bit matrixMto rowi + 1forfst <= i < last; and we move rowlastto rowfst. The columns of the partQofMare also adjusted.1 <= fst <= last < pqs->nrowsmust hold. This rotation does not change the state.For internal use only. Input conditions are not checked.
- int32_t qstate12_sum_up_kernel(qstate12_type *pqs)
Auxiliary function for function qstate12_reduce().
Sum up the kernel of the transformation matrix
A, which is part of the bit matrixM = pqs->data. We assume thatAis echelonized in the sense that all nonzero rows ofAare linear independent and that they occur before the zero rows.
- int32_t qstate12_echelonize(qstate12_type *pqs)
Convert the state represented by
pqsto echelon form.The representation state referred by
pqsis converted to (not necessarily reduced) echelon form, and the kernel of bit matrixA, which is part of the bit matrixM = pqs->datais summed up as described in the guide, section ‘Reducing the representation of a quadratic mapping’. The representation of the state is not changed if this is already the case.This function does not change the state.
- int32_t qstate12_check_reduced(qstate12_type *pqs)
Check if the state represented by
pqsis reduced.The function puts
pqs->reduced = 1if the state is reduced; and it performs no action onpqsotherwise. It returns the updated value ofpqs->reduced(which is 0 or 1) in case of success, and a negative value in case of failure.This check is much faster than actually performing a reduction. The function may perform some easy reduction steps on the state.
- int32_t qstate12_reduce(qstate12_type *pqs)
Reduce the state represented by
pqsThe representation state referred by
pqsis converted to reduced echelon form, and the kernel of bit matrixA, which is part of the bit matrixM = pqs->datais summed up as described in the guide, section ‘Reducing the representation of a quadratic mapping’. The representation of the state is not changed if this is already the case.This function does not change the state.
- int32_t qstate12_row_table(qstate12_type *pqs, uint8_t *row_table)
Compute a certain table for the state referred by
pqsCompute a row table for the state
qsreferred bypqs. Hereqsmust be in (not necessarily reduced) echelon form.The function computes
row_table[j] = iif the leading bit of rowiof partAof the bit matrixM = pqs->datais in columnj, for0 <= j < pqs->ncolsand1 <= i < pqs->nrows. If now such row exists for columnjthen we putrow_table[j] = QSTATE12_UNDEF_ROW.The representation of the state is not changed.
- int32_t qstate12_join_imaginary(qstate12_type *pqs)
Join diagonal nonzero entries quadratic form in a state.
Nonzero diagonal entries in the quadratic form
Qof a state indicate that there are entries in the state with an imaginary ratio. If there are several nonzero diagonal entries inQthen this situation my be difficult to handle in some cases.After calling this function, matrix
Qwill have at most one nonzero diagonal entry in row 1. The function returns 1 ifQhas a nonzero diagonal entry in that row and 0 otherwise.If the function returns 1 then the state may not be reduced. If it returns 0 then the state is reduced.
- int32_t qstate12_equal(qstate12_type *pqs1, qstate12_type *pqs2)
Check equality of two states.
Return 1 if the states referred by
pqs1andpqs2are equal, 0 if not, and a negative number in case of error. Both states are reduced before comparing them.
- int32_t qstate12_extend_zero(qstate12_type *pqs, uint32_t j, uint32_t nqb)
Insert qubits into a state and set them to 0.
We insert
nqbzero qubits into the stateqsreferred bypqsstarting at positionj.Let
n = pqs->ncolsso that the stateqsreferred bypqsdepends onnqubits. We changeqsto the following stateqs1depending onn + nqbqubits:
qs1(x[n-1],...,x[j],y[nqb-1],...,y[0],x[j-1]...,x[0])is equal toqs(x[n-1],...,x[j],x[j-1]...,x[0])ify[0] = ... = y[nqb-1] = 0and equal to zero otherwise. So we incrementpqs->ncolsbynqb.If the input is reduced then the result is also reduced.
pqs->shape1is set to 0, i.e. a column vector is returned.
- int32_t qstate12_extend(qstate12_type *pqs, uint32_t j, uint32_t nqb)
Insert qubits into a state.
We insert
nqbqubits into the stateqsreferred bypqsstarting at positionj.Let
n = pqs->ncolsso that the stateqsreferred bypqsdepends onnqubits. We changeqsto the following stateqs1depending onn + nqbqubits:
qs1(x[n-1],...,x[j],y[nqb-1],...,y[0],x[j-1]...,x[0])is equal toqs(x[n-1],...,x[j],x[j-1]...,x[0]). So we incrementpqs->ncolsbynqb.The result is not reduced.
pqs->shape1is set to 0, i.e. a column vector is returned.
- int32_t qstate12_sum_cols(qstate12_type *pqs, uint32_t j, uint32_t nqb)
Sum up the functional values for some qubits.
We sum up
nqbqubits of the stateqsreferred bypqsstarting at positionj.Let
n = pqs->ncolsso that the stateqsreferred bypqsdepends onnqubits. We changeqsto the following stateqs1depending onn - ncolsqubits:
qs1(x[n-1],...,x[j+nqb],x[j-1],...,x[0])=sum_{x[j+nqb-1],...,x[j]} qs1(x[nn1-1],...,x[0]). So we decrementpqs->ncolsbynqb.The output is not reduced.
pqs->shape1is set to 0, i.e. a column vector is returned.
- int32_t qstate12_restrict_zero(qstate12_type *pqs, uint32_t j, uint32_t nqb)
Restrict
nqbqubits starting at postionjto 0.Let
n = pqs->ncolsso that the stateqsreferred bypqsdepends onnqubits. We changeqsto the following stateqs1depending onnqubits:
qs1(x[n-1],...,x[0])is equal toqs(x[n-1],...,x[0])ifx[j] = ... = x[j+nqb-1] = 0and equal to zero otherwise. We do not change the shape ofqs.The output is reduced if the input is reduced.
- int32_t qstate12_restrict(qstate12_type *pqs, uint32_t j, uint32_t nqb)
Restrict some qubits to 0 and delete them.
Similar to function
qstate12_restrict_zero, but with deleting the restricted qubits.Let
n = pqs->ncolsso that the stateqsreferred bypqsdepends onnqubits. We changeqsto the following stateqs1depending onn1 = n - nqbqubits:
qs1(x[n1-1],...,x[0])is equal toqs(x[n1-1],...,x[j],0,...,0,x[j-1],...,x[0]). So we decrementpqs->ncolsbynqb.The output is not reduced.
pqs->shape1is set to0, i.e. a column vector is returned.In quantum computing theory this operation can be interpreted as measurement of the corresponding qubits with postselection, setting all measured qubits to 0.
- int32_t qstate12_gate_not(qstate12_type *pqs, uint64_t v)
Apply a not gate to a state.
Change the state
qsreferred bypqsto a stateqs1withqs1(x) = qs(x (+) v), where'(+)'is the bitwise xor operation. The result is not reduced.Computing
qstate12_gate_not(pqs, 1 << j)corresponds to negating qubitj.
- int32_t qstate12_gate_ctrl_not(qstate12_type *pqs, uint64_t vc, uint64_t v)
Apply a contol-not gate to a state.
Change the state
qsreferred bypqsto a stateqs1withqs1(x) = qs(x (+) <vc,x> * v), where'(+)'is the bitwise xor operation, and<.,.>is the scalar product of bit vectors. The result is not reduced. The scalar product of the bit vectorsjandjcmust be zero. Otherwise thectrl notoperation is not unitary.Computing
qstate12_gate_ctrl_not(pqs, 1 << jc, 1 << j), forjc != j, corresponds to applying a controlled not gate to qubitj, contolled by qubitjc.
- int32_t qstate12_gate_phi(qstate12_type *pqs, uint64_t v, uint32_t phi)
Apply a phase gate to a state.
Change the state
qsreferred bypqsto a stateqs1withqs1(x) = qs(x) * sqrt(-1)**(phi * <v,x>), where<.,.>is the scalar product of bit vectors and'**'denotes exponentiation. The result is reduced if the input is reduced. Computingqstate12_gate_ph(pqs, 1 << j, phi)corresponds to applying a phase(phi * pi/2)gate to qubitj.
- int32_t qstate12_gate_ctrl_phi(qstate12_type *pqs, uint64_t v1, uint64_t v2)
Apply a controlled phase gate to a state.
Change the state
qsreferred bypqsto a stateqs1withqs1(x) = qs(x) * (-1)**(<v1,x>*<v2,x>), where<.,.>is the scalar product of bit vectors and'**'denotes exponentiation.The result is reduced if the input is reduced. Computing
qstate12_gate_ctrl_phi(pqs, 1 << j1, 1 << j2)corresponds to applying a phasepigate to qubitj2controlled by qubitj1.
- int32_t qstate12_gate_h(qstate12_type *pqs, uint64_t v)
Apply Hadamard gates to a state.
Apply a Hadamard gate to all qubits
jof the stateqs(referred by pqs) withv & (1 << j) == 1. Applying a Hadamard gate to gatejchanges a stateqsto a state1/sqrt(2) * qs1, whereqs1(..,x[j+1],x_j,x[j-1],..)=qs(..,x[j+1],0,x[j-1],..)
(-1)**(x_j) * qs(..,x[j+1],1,x[j-1],..). The result is not reduced.
C functions in qstate12io.c
File
qstate12io.ccontains functions for converting quadratic state matrices (as described in the API reference in section Computation in the Clifford group) to complex numbers.The functions in this module are coded according to the conventions in module
qstate12.c.Some of these functions have to traverse the support (i.e. the set of nonzero entries) of a quadratic state stored in a structure
qsof typeqstate12_type. Such a traversal is a highly non-trivial process. We hide the details of this process in a structure of typeqstate12_support_type.Once that structure has been initialized from the state
qs, we may traverse the support of that state in batches of a fixed size. All entries of the same batch are nonzero and equal up to sign.The basic procedure for traversing the support of state
qsis as follows:qstate12_support_type sup; if (qstate12_support_init(&qs, &sup) < 0) return ERROR; for (int i = 0; i < sup.n_batches; ++i) { if (qstate12_support_next(&sup) < 0) return ERROR; if (sup.factor_new) { // store sup.factor in variable 'factor' } for (int j = 0; j < sup.batchsize; ++j) { // store sup.indices[j] in variable 'index' // store (-1)**sup.signs[j] * factor in variable 'value' // process the entry at index 'index' with value 'value' } }The complex number
sup.factoris encoded as described in functionqstate12_factor_to_complex. The user should convert it to their preferred data type before storing it in the variablefactor.The variable
factorhas to be recomputed after a call toqstate12_support_nextwhenever the valuesup.factor_newis nonzero.After calling that function, a batch of size
sup.batchsizeof entries ofqstogether with the corresponding indices is available inside the structuresupas shown in the program code above. The size of a batch never exceeds 64.Functions
- int32_t qstate12_support_init(qstate12_type *pqs, qstate12_support_type *psup)
Initialize structure
qstate12_support_typefor reading a state.The function initializes a stucture of type
qstate12_support_typefrom a state of typepqs. Then the nonzero matrix entries of that state may be obtained by subsequent calls to functionqstate12_support_next.
- int32_t qstate12_support_next(qstate12_support_type *psup)
Read nonzero entries of a state in batches.
We assume that a structure of type
qstate12_support_typehas been initialized from a state by functionqstate12_support_init. Then batches of nonzero values of that state are obtained by repeated calls to this function.Each call to this function returns a batch of pairs
(index, value)of lengthpsup->batchlength. Altogether there arepsup->n_batchesof these batches. Indices are given as integer indices of a column vector, ignoring the shape of the state matrix. The i-th index if a batch is contained inpsup->indices[i].The value of the i-th index is obtained as
psup->factor * (-1) ** psup->signs[i].Here the factor is encoded in
psup->sfactoras described in the C functionqstate12_factor_to_complex. That factor must be (re-)calculated ifpsup->factor_newis nonzero; otherwise the factor from the previous batch can be kept.After calling this function
psup->n_batchestimes with the argumentpsup, the data in this structure are used up and should be considered as garbage.
- int32_t qstate12_support_adjust(qstate12_support_type *psup, uint32_t flags)
Check and adjust structure of type
qstate12_support_typeWe assume that a structure of type
qstate12_support_typehas been initialized from a state by functionqstate12_support_initand not yet been used by functionqstate12_support_next. So it encodes a certain quadratic stateqs.Then this function checks the data in the structure for certain properties (possibly modifying the data), depending of the bits of parameter
flagsas follws:Bit 0 set: Return an error if not all entries of
qsare real.Bit 1 set: Return an error if not all entries of
qsare rational.Bit 2 set: Return an error if not all entries of
qsare integral and fit into an integer of typeint32_t.Bit 3 set: Reduce all rational entries of
qsmodulo 3 and return an error if any of them is not rational.Depending on parameter
flags, we assert the following in case of success:In any of the bits 0, 1, 2, 3 has been set then
psup->factoris positive and will not be changed by functionqstate12_support_next.If bit 3 has been set then
psup->factoris equal to 1.The function returns 0 in case of success and a negative value in case of failure.
- int32_t qstate12_complex(qstate12_type *pqs, double *pc)
Expand a state to an array of complex numbers.
Expand the state
qsreferred bypqsto the array referred by the pointerpc. The real part ofqs[i]is stored inpc[2*i]and the imaginary part ofqs[i]is stored inpc[2*i+1]. The function reducesqs. Here the integeriis interpreted as a bit vector as usual.Member
pqs->shape1is ignored. The user has to care for the shape of the returned array. The stateqsis reduced.Caution: The function sets
2 * 2**pqs->ncolsentries in the arraypc.Return value is as in function
qstate12_entries.This function traverses the support of a state without using a structure of type
qstate12_support_type. Such kind of a traversal is now deprecated. Here we keep this function for testing newer functions dealing with that structureqstate12_type.
- int32_t qstate12_entries(qstate12_type *pqs, uint32_t n, uint32_t *v, double *pc)
Convert entries of a state to complex numbers.
The function computes the entries
qs[v[i]]of the stateqsreferred bypqsfor0 <= i < nand stores these entries in the arraypc. The real part ofqs[v[i]]is stored inpc[2*i]and the imaginary part is stored inpc[2*i+1]. The stateqsis reduced.Caution: The function sets
2 * nentries in the arraypc.Depending on the computed matrix entries, the function returns
4 if all entries are complex, but not all are real. 3 if all entries are real, but not all are rational. 2 if all entries are rational, but not all are integers. 1 if all entries are integers, but not all are zero. 0 if all entries are zero.A negative return value indicates an error.
- int32_t qstate12_int32(qstate12_type *pqs, int32_t *pi)
Expand a state to an array of 32-bit integers.
Expand the state
qsreferred bypqsto the array of integers (of typeint32_t) referred by the pointerpi. Hereqs[i]is stored inpi[i]. The function reducesqs. The integeriis interpreted as a bit vector as usual.
pqs->shape1is ignored. The user has to care for the shape of the returned array. The stateqsis reduced.Caution: The function sets
2**pqs->ncolsentries in the arraypc.The function returns 0 in case of success, and a negative value in case of error, e.g. if
qsis not integral or in case of integer overflow.
- static int32_t subbatch_length(qstate12_support_type *psup)
- int32_t qstate12_to_signs(qstate12_type *pqs, uint64_t *bmap)
Store the signs of a real quadratic state in an array.
Let
qsbe the quadratic state matrix referred bypqs. Assume thatqsis real and has shape(I, J). Lett[i * 2**J + j] = 0, 1, or 3, if entryqs[i, j]is zero, positive, or negative, respectively. Then we storet[k]in bits2 * l + 1, 2 * lofbmap[k >> 5], withl = k & 0x1f.The function returns 0 in case of success, and a negative value in case of error, e.g. if
qsis not a real matrix.
- int32_t qstate12_compare_signs(qstate12_type *pqs, uint64_t *bmap)
Compare signs of a real quadratic state with an array.
Let
qsandbmapas in functionqstate12_to_signs. The function returns 1 if the signs ofqsare stored in inbmapas described in functionqstate12_to_signs. Otherwise the function returns 0. The function also returns 0 if matrixqsis not real. It returns a negative value in case of an error.
- int32_t qstate12_from_signs(uint64_t *bmap, int32_t n, qstate12_type *pqs)
Construct a state vector from a sign matrix.
Let
bmapbe an array with2**nentries representing 0 or (positive or negative) signs as in functionqstate12_to_signs. Thenbmapmay correspond to a quadratic state vector with entries 0, 1, and -1.If these entries correspond to a quadratic state vector
V(with entries 0, 1, and -1) then the function storesVin the quadratic state vectorqsreferred bypqsand returns 0. The returned stateqsis a (column) vector of shape(0, n). If the arraybmapdoes not correspond to any quadtatic state vector then the function setsqsto the zero vector of shape(0, n)and returns -1.The function returns negative value less than -1 in case of an error.
- int32_t qstate12_mul_matrix_mod3(qstate12_type *pqs, uint64_t *v, uint64_t w)
Compute a certain product modulo 3 with a state matrix.
Let
qsbe the quadratic state matrix referred bypqs. Assume thatqsis rational and has shape(I, J). Letqbe the row vector of length2**(I+J)withq[i * 2**J + j] = qs[i, j].We consider
vas a2**(I+J)times32matrixMof integers modulo 3 withM[k,l]stored in bits2*l+1and2*lof entryv[k]. We considerwas a column vector of32integers mod 3 withw[l]stored in bits2*l+1and2*lof the variablew.Then the function returns the matrix product
q * M * v(modulo 3) as a nonnegative integer less than 3. It returns a negative value in case of error, e.g. ifqsis not rational.This function is deprecated and will be removed!
C functions in qmatrix12.c
File
qmatrix12.ccontains basic functions for quadratic
state matrices as described in the
API reference in section Computation in the Clifford group. The functions is this module are based on the functions in moduleqstate.cand on the data structures defined in moduleclifford12.h.C functions in this module are prefixed with
qbstate12_. Unless otherwise stated, these functions return anint32_t, where a nonegative value is interpreted as success, and a negative value is intepreted as failure. Error codes returned by functions in this module are documented in fileclifford12.h.A structure
qsof typeqstate12_typedefines a function \(f: \mathbb{F}_2^n \rightarrow \mathbb{C}\) and also a \(2^{n-k} \times 2^k\) matrix \(M\) with entries \(M[i,j] = f(2^k \cdot i+j)\). Here we idenitfy the nonegative integers \( < 2^n\) with the bit vectors given by their binary representation. For the shape parameters \(n, k\) of a stateqswe have \(n\) =qs.ncols, \(k\) =qs.qstate1. Thus indices of vectors and matrices start with 0, as usual in C and python.While the functions in module
qstate.cmostly ingnore the shape parameter \(k\), the functions in this module use that shape parameter for determining the shape of a matrix.Functions
- int32_t qstate12_std_matrix(qstate12_type *pqs, uint32_t rows, uint32_t cols, uint32_t rk)
Create a standard matrix with entries 1 in the diagonal.
Create a standard matrix
qswith2**rowsrows and2**colscolumns as an object of typeqstate12_type, and store the result in*pqs. Diagonal entriesqs[i,i]are equal to one forì < 2**rk. All other entries of the matrix are zero.0 <= rk < min(nows, cols)must hold.
- int32_t qstate12_unit_matrix(qstate12_type *pqs, uint32_t nqb)
Create a unit matrix.
Create a unit matrix with
2**nqbrows and2**nqbcolumns as an object of typeqstate12_type, and store the result in*pqs.
- int32_t qstate12_monomial_column_matrix(qstate12_type *pqs, uint32_t nqb, uint64_t *pa)
Create matrix with one nonzero entry in each column.
Create a matrix
Twith2**nqbrows and2**nqbcolumns as an object of typeqstate12_type, and store the result in*pqs.Matrix
Tis a real2**nqbtimes2**nqbtransformation matrix which is monomial in the sense that each column contains exactly one nonzero entry 1 or -1. So left multiplication withTmaps unit vectors to (possibly negated) unit vectors. It transforms a complex column vectorwof length2**nqbto a vectorT * w.
parefers to an array a of integersa[i]of lengthnqb + 1. Each integera[i]is interpreted as a bit field via its binary representation. Soa[i,j]means(a[i] >> j) & 1.a[i, j1:j2]means the bit fielda[i,j1],...,a[i,j2-1].For any bit vector
vof lengthnqblet|v>be the unit vector with indexv. For any bit vectorvof lengthnqb + 1let|v>be the (possibly negated) unit vector(-1)**v[nqb] * |v[0:nqb]>.|v1 ^ v2>and|1 << v1>are defined via the corrresponding operators<<and^in C.Then
Tmaps|0> to |a[0, 0:nqb+1]> |1 << i> to |a[0, 0:nqb+1] ^ a[i+1, 0:nqb+1]>
Tmaps unit vectors to (possibly negated) unit vectors, soT(v)is well defined by|T(v)> = T(|v>)for a bit fieldvof lengthnqb + 1. We have|T(v1 ^ v2)> = (-1)**Q(v1,v2) * |T(v1) ^ T(v2) ^ T(0)>,for bit fields
v1, v2of lengthnqb + 1and an alternating bilinear formQdepending on the lowestnqbbits ofv1andv2only. ThusTis defined by the above equation andQ. The bilinear formQis defined by:Q(v1, v2) = Q(v2, v1), Q(v1, v1) = 0, and Q(1 << i, 1 << j) = a[i + 1, j + nqb + 1], for ``0 <= j < i < nqb``.
- int32_t qstate12_monomial_row_matrix(qstate12_type *pqs, uint32_t nqb, uint64_t *pa)
Create matrix with one nonzero entry in each row.
Similar to qstate12_monomial_column_matrix(); but we create a matrix
Twhich is monomial in the sense that each row contains exactly one nonzero entry1or-1.qstate12_monomial_row_matrix(*pqs, nqb, *pa)creates the transposed matrix ofqstate12_monomial_column_matrix(*pqs, nqb, *pa).
- int32_t qstate12_monomial_matrix_row_op(qstate12_type *pqs, uint32_t *pa)
Obtain operation of a monomial quadratic state matrix.
A monomial matrix maps unit vectors to unit vectors, if we ignore scalar factors. Let
qsbe the matrix referred bypqs. We assume thatqshas exactly one nonzero entry in each row. Then right multiplication withqsmaps unit vectors to unit vectors, up to a scalar factor. Otherwrise the function returns ERR_QSTATE12_NOT_MONOMIAL.If we label each unit vector by a bit vector then the operation of
qson these bit vectors labels is affine. Ifqshas shape(r,c)then we compute anr+1timescbit matrixain the array referred bypawith the following property:Label
(b[0],...,b[r-1])is mapped to label(1, b[0],...,b[r-1]) * a.The function returns the number
r+1of rows ofa.From bit matrix
awe can construct a unique matrixqs1, of the same shape asqs, that maps unit vectors to unit vectors as given by the mapping of the labels. In caser == cthis can be done by callingqstate12_monomial_row_matrix(pqs1, r, pa), wherepqs1points to a buffer forqs1.Then
qscan be obtained by multiplyingqs1with a diagonal matrix.
- int32_t qstate12_mat_reshape(qstate12_type *pqs, int32_t rows, int32_t cols)
Change the shape of a matrix.
Reshape the matrix
Treferred bypqswill be a2**rowstimes2**colsmatrix.The old shape of the matrix is
(n-k, k)withn, kgiven byn = pqs->ncols,k = pqs->shape1. Reshaping must not change the number of entries, sorows + cols == nmust hold. We follow the convention in the python numpy package for reshaping matrices. Thus index[i,j]of a matrix with shape(I,J)corresponds to the indexi * 2**J + jin the one-dimensional array storing that matrix.If
rowsorcolsis -1 then it is calculated from the old shape of the matrix. If both,rowsandcols, are -1 thenrowsis set to0andcolsis calculated.
- int32_t qstate12_mat_t(qstate12_type *pqs)
Transpose a matrix in place.
The quadratic state matrix
qsreferred bypqsis transposed in place. The result is not reduced.
- int32_t qstate12_mat_trace(qstate12_type *pqs, double *p_trace)
Compute the trace of a quadratic state matrix.
The function computes the trace of the quadratic state matrix
qsreferred bypqs. The real part of the trace is stored inp_trace[0]and the imaginary part is stored inp_trace[1]. The stateqsis reduced.Return value is as in function
qstate12_factor_to_complex.
- int32_t qstate12_mat_itrace(qstate12_type *pqs, int32_t *p_itrace)
Compute the trace of a quadratic state matrix.
Similar to function
qstate12_mat_trace, buth the trace is stored as an integer inp_itrace[0].Return value is as in function
qstate12_factor_to_int32.
- int32_t qstate12_prep_mul(qstate12_type *pqs1, qstate12_type *pqs2, uint32_t nqb)
Auxiliary low-level function for function qstate12_product()
Prepare the states
qs1andqs2referred bypqs1andpqs2for matrix multiplication. Here the summation in that operation runs over firstnqbqubits ofqs1andqs2, regardless of the shape of the input matrices. The function returns a numberrow_pos, so that, after preparation, the firstnqbcolumns of submatricesA1andA2of the bit matricesM1andM2corresponding toqs1andqs2will be equal in the following sense:A1[i,j] = A2[i,j] for i < 'row_pos', j < 'nqb' , A1[i,j] = A2[i,j] = 0 for i >= 'row_pos', j < 'nqb' .Also, matrices
A1andA2will both have rankrow_pos - 1, when excluding row 0 of the two matrices. Some rows ofA1orA2may be deleted to achieve this situation. The result of the summation of the matrix products ofqs1andqs2over the firstnqbcolumns (which is used by the matrix multiplication procedure) is not changed by this operation. Apart from this assertion, both states are changed, and they may have less rows than before. They may even be changed to zero, if the result of the multiplication is zero.The algorithm used here is explained in the API reference in section Multiplication of quadratic mappings. In the notation in that section the algorithm computes states \(\mbox{qs1}', \mbox{qs2}'\) with \( (\mbox{qs1}' \odot \mbox{qs2}')_n = (\mbox{qs1} \odot \mbox{qs2})_n, \), where \( n\) =
nqb.
pqs1->shape1andpqs2->shape1are ignored.
- int32_t qstate12_product(qstate12_type *pqs1, qstate12_type *pqs2, uint32_t nqb, uint32_t nc)
Compute a certain product of two states.
Compute a certain product
qs3of the statesqs1andqs2referred bypqs1andpqs2and store the (reduced) result in*pqs1. Overlap betweenpqs1andpqs2is possible.qs2is not changed.Let
n1 = pqs1->ncols, n2 = pqs2->ncols. Putqs1a = qstate12_extend(qs, n1, n2-nqb),qs2a = qstate12_extend(qs, nqb, n1-nqb). Thenqs1aandqs2aare complex functions on(nn1 + nn2 - nqb)bits. Letqs3abe the complex function which is the product of the functionsqs1aandqs2a. Then we haveqs3 = qstate12_sum_cols(qs3a, 0, nc).E.g.
qstate12_product(pqs1, pqs2, nc, nc)is the tensor contraction over the firstncqubits ofqs1andqs2. In casepqs1->ncols = pqs2->ncols = nthe functionqstate12_product(pqs1, pqs2, n, 0)returns the product ofqs1andqs2(considered as functions). Furthermore, andqstate12_product(pqs1, pqs2, n, n)returns the scalar product ofqs1andqs2(considered as vectors).In general,
qstate12_product(pqs1, pqs2, n, 0)corresponds to the function \( (\mbox{qs1}' \odot \mbox{qs2}')_n \) defined in section Products and tensor products of quadratic mappings of the API reference.
pqs1->shape1is set to 0. The user should setpqs1->shape1to a reasonable value.
- int32_t qstate12_matmul(qstate12_type *pqs1, qstate12_type *pqs2, qstate12_type *pqs3)
Compute the matrix product of two matrices.
Compute the matrix product
qs3of the maticesqs1andqs2referred bypqs1andpqs2and store the (reduced) result in*pqs3. Overlap betweenpqs1, pqs2, pqs3is possible.If
qs1has shape(r1,c1)andqs2has shape(r2,c2)thenc1 == r2must hold, andqs3has shape(r1,c2)Note that a shape
(r,c)of a matrixqsmeans a2**rtimes2**cmatrix, wherer+c == qs.ncols,c = qs.shape1.
- int32_t qstate12_pauli_vector(qstate12_type *pqs, uint64_t *pv)
Check if a matrix is in the Pauli group and convert it to a vector.
The Pauli group of \(n\) qubits is the normal subgroup of the Clifford group of \(n\) qubits generated by the not gates, the phase \(\pi\) gates, and by the scalar multiples of the unit matrix by a fourth root of unity.
We represent an element of the Pauli group as a product of \(2n+2\) generators of order 2 or 4. The sequence of these exponents is stored in a bit vector (coded as an integer) as follows:
Bit 2n+1: a scalar factor sqrt(-1) Bit 2n: a scalar factor -1 Bit n+i: a not gate applied to qubit i, 0 <= i < n Bit i: a phase pi gate applied to qubit i, 0 <= i < nSee section The Pauli group in the API reference for details.
If the matrix
qsreferred bypqsis in the Pauli group of \(n\) qubits then the function returns \(n\) and storesqsas an element of the Pauli group in the vectorvreferred bypv. Otherwise the function returns a negative error code.
- int32_t qstate12_pauli_matrix(qstate12_type *pqs, uint32_t nqb, uint64_t v)
Convert element of the Pauli group to a matrix.
Here parameter
vencodes an element of the Pauli group ofnqbqubits as described in function qstate12_pauli_vector(). The function convertsvto a matrix of shape(nqb, nqb)in the Clifford group and stores the result in the state referred bypqs.
- uint64_t qstate12_pauli_vector_mul(uint32_t nqb, uint64_t v1, uint64_t v2)
Multiplication of two elements of the Pauli group.
Here parameters
v1andv2encode two elements of the Pauli group ofnqbqubits as described in function qstate12_pauli_vector().The function returns the product
v1 * v2encoded in the same way.
- uint64_t qstate12_pauli_vector_exp(uint32_t nqb, uint64_t v, uint32_t e)
Exponentiation of an element of the Pauli group.
Here parameter
v1encodes an element of the Pauli group ofnqbqubits as described in function qstate12_pauli_vector().The function returns the power
v1 ** eencoded in the same way.The Pauli group has exponent 4, so
qstate12_pauli_vector_exp(nqb, v1, 3)returns the inverse ofv1.
- int32_t qstate12_reduce_matrix(qstate12_type *pqs, uint8_t *row_table)
Perform a special reduction on a quadratic state matrix.
This function performs a special reduction on the quadratic state matrix
qsreferred bypqs, as described in the API reference, section Reducing a quadratic state matrix.This kind of reduction is different from the reduction in function qstate12_reduce(). It is used internally for computing traces and norms of matrices. It is also used in function qstate12_pauli_conjugate().
The function also computes a table with
pqs->nrows + pqs->ncolsentries in the array referred by parameterrow_tablewhich is used internally for the operations mentioned above.
- int32_t qstate12_mat_lb_rank(qstate12_type *pqs)
compute the rank of a quadratic state matrix
Let
qsbe the quadratic state matrix referred bypqs. The function returns the binary logarithm of the rank of matrixqs, which is an integer in case of the nonzero matrix. It returns -1 ifqsis the zero matrix. A return value less than -1 is an error code. Matrixqsis reduced.
- int32_t qstate12_mat_inv(qstate12_type *pqs)
Compute the inverse of a quadratic state matrix.
Let
qsbe the quadratic state matrix referred bypqs. The function computes the (reduced) inverse of matrixqsin place. It returns ERR_QSTATE12_MATRIX_INV if the matrix is not invertible.
- int32_t qstate12_to_symplectic(qstate12_type *pqs, uint64_t *pA)
Convert quadratic state matrix to a symplectic bit matrix.
Here the quadratic state matrix
qsreferred bypqsmust be of shape(k, k)and invertible. The function computes a2ktimes2kbit matrixA.If
vis a bit vector representing an element of the Pauli group thenv * Arepresents the elementqs * v * qs^{-1}of the Pauli group, up to a scalar factor. Elements of the Pauli group ofkqubits are encoded as in functionqstate12_pauli_vector(), ignoring the bits at positions2kand2k + 1. SopA[i]will contain the image of thei-th basis vector of the Pauli group, with bits2kand2k + 1set to zero.The function returns
2*kin case of success and a negative value in case of an error. In any case it suffices if the array referred bypAhas 32 entries.This function can be considered as a simplified version of function
qstate12_pauli_conjugate. It computes the natural homomorphism from the group of invertible quadratic state matrices shape(k, k)to the symplectic group \(\mbox{S}_{2k}(2)\).
- int32_t qstate12_to_symplectic_row(qstate12_type *pqs, uint32_t n)
Conjugate unit vector in Pauli group by quadratic state matrix.
Here the quadratic state matrix
qsreferred bypqsmust be of shape(k, k)and invertible.Let
vbe the bit vector with bitnset and the other bits cleared. Here elements of the Pauli group ofkqubits are encoded as in functionqstate12_pauli_vector(), ignoring the bits at positions2kand2k + 1.The function returns the element
qs * v * qs^{-1}of the Pauli group, up to a scalar factor as an integer, encoded in the same way as input vectorv, ignoring the scalar factor.Thus in case of success the return value is the same as row
nof the matrix computes by functionqstate12_to_symplectic_row. The function returns a negative value in case of an error.
- int32_t qstate12_pauli_conjugate(qstate12_type *pqs, uint32_t n, uint64_t *pv, uint32_t arg)
Conjugate Pauli group elements with a Clifford group element.
Here the quadratic state matrix
qsreferred bypqsmust be of shape(k,k)and invertible. The arrayvreferred bypvhasnentriesv[0],...,v[n-1]. Each of these entries is interpreted as an element of the Pauli group ofkqubits, encoded as in functionqstate12_pauli_vector().The function replaces
v[i]by the Pauli group elementw[i] = qs * v[i] * qs**(-1)for alli < n.w[i]is encoded in the same way asv[i].Parameter
argshould usually be a nonzero value. In casearg == 0the (complex) argument of the outputsv[i]is not computed.This function uses function
qstate12_reduce_matrix(). The operation of this function is explained in the API reference, section Reducing a quadratic state matrix .
Computing in the subgroup \(G_{x0}\) of the Monster
The functions in file xsp2co1.c implement the group operation
of the subgroup
\(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\))
of the monster.
Represenation of \(G_{x0}\) on the tensor product \(4096_x \otimes \Lambda\)
In [Sey20], section 7.4 and 9, the generators \(x_d, x_\delta, y_\delta, x_\pi, \xi\) of \(G_{x0}\) are also defined as generators of a group \(G_{x1} \subset G(4096_x) \times G(24_x)\). Here \(G(4096_x)\) is a subgroup of the real Clifford group \(\mathcal{C}_{12}\) operating on the 4096-dimensional real vector space \(4096_x\), and \(G(24_x)\) is the automorphism group \(\mbox{Co}_0\) of the Leech lattice \(\Lambda\). \(G_{x1}\) is a preimage of \(G_{x0}\) with \(|G_{x1}:G_{x0}| = 2\), and \(G_{x0}\) operates faithfully on the tensor product \(4096_x \otimes_\mathbb{Z} \Lambda\). Let \((x_g, L_g) \in G_{x1} \subset G(4096_x) \times G(24x)\). Component \(x_g\) determines component \(L_g\) of the pair up to sign. So it suffices to store the image \(v_g = v_0 \cdot L_g\) of a fixed shortest vector \(v_0 \in \Lambda / 3 \Lambda\) instead of the whole automorphism \(L_g\) of \(\Lambda\). We put \(v_0 = (0,0,4,-4,0,...,0)\) in the standard basis of the Leech lattice.
We can reconstruct \(L_g\) from \(x_g\) and
\(v_g\) as follows. \(G(4096_x)\) has an extraspecial
subgroup \(Q_{x1}\) of structure \(2^{1+24}\). The
quotient of \(Q_{x1}\) by its center \(Z(Q_{x1})\) is
isomorphic to \(\Lambda / 2 \Lambda\). By definition of
\(G_{x1}\), the element \(L_g\) operates on
\(\Lambda / 2 \Lambda\) in the same way as \(x_g\)
operates on \(Q_{x1}/Z(Q_{x1})\) by conjugation.
So that operation of \(L_g\) can be reconstructed from
\(x_g\). A short vector in \(\Lambda / 2 \Lambda\)
has precisely two short preimages in \(\Lambda\) which
are opposite. Thus the image of one short vector is known
exactly, and the images of all short vectors are known up to
sign. Since \(L_g\) preserves the scalar product, the
images of all short vectors in \(\Lambda\) can be computed.
Function xsp2co1_elem_to_leech_op in file xsp2co1.c
constructs \(L_g\) from \(x_g\) and \(v_g\).
The functions in file gen_leech.c support operations on
\(\Lambda / 2 \Lambda\) and \(\Lambda / 3 \Lambda\).
The \(G_{x0}\) representation
We actually represent an element of \(G_{x0}\) in G_x0
representation. This is as an array elem of 26 integers
of type uint64_t. That array contains a pair
\((x_g,v_g)\) as described above with \(v_g\) stored
in the first entry elem[0], and \(x_g\) stored in the
remaining 25 entries of array elem.
Vector \(v_g \in \Lambda / 3 \Lambda\) is stored in
elem[0] as a 48-bit integer in Leech lattice mod 3
encoding as described in the documentation of module
gen_leech.c.
We store the inverse \(x_g^{-1}\) of \(x_g\) in
the upper 25 entries of the array elem. The rationale
for storing the inverse is that this simplifies the operation
of \(G(4096)_x\) on \(Q_{x1}\) by conjugation, using
function qstate12_pauli_conjugate in file qmatrix12.c.
Note that \(x_g^{-1} = x_g^\top\), since \(x_g\)
is orthogonal.
In section Long-term stable storage of vectors of the representation an element \(c\)
of \(\mathcal{C}_{12}\) is given as a real
\(2^{12} \times 2^{12}\) matrix stored in a structure
of type qstate12_type. In case \(c \in G(4096_x)\)
that matrix has rational entries, where the denominators are
powers of two. A structure of type qstate12_type
representing a \(c \in G(4096_x)\) contains
a triple \((e,A,Q)\). There \(e\) is a signed integral
power of two, and \((A,Q)\) is a pair of bit
matrices with up to 25 rows and up to 49 colums, where the
first 24 columns belong to matrix \(A\), and the remaining
columns belong to matrix \(Q\).
Changing the sign of \(e\) corresponds to negation of a matrix \(x_g^{-1} \in G(4096_x)\) given by \((e,A,Q)\) or to multiplication by \(x_{-1}\). In the group \(G_{x0}\), changing the sign of \(v_g\) has the same effect as changing the sign of \(x_g\); so \(e\) can always be made positive. The absolute value of \(e\) is just there for scaling the operator norm of a matrix \(c\) to 1, and can be omitted.
So we can represent one of the values \(\pm x_g^{-1}\) as a pair \((A,Q)\) with an implied positive scalar factor \(e\) as above, and negate component \(v_g\) of the pair \((x_g,v_g)\), if necessary.
Assuming that \(x_g^{-1}\) is stored in a structure
qs of type qstate_type, we copy all valid entries
qs.data[i] to elem[i+1]. This amounts to copying the
components \((A,Q)\) of the triple \((e,A,Q)\)
from qs to elem. We always reduce the quadratic
state matrix in qs before copying it, as indicated in
section Long-term stable storage of vectors of the representation. We fill unused entries
and bits in the array elem with zeros. Thus the
representation of a \(g \in G_{x0}\) in memory is unique.
qs can easily be reconstructed from elem, assuming
that the scalar factor \(e\) in the triple
\((e,A,Q)\) is positive, and that trailing zero
entries in the array elem are unused.
A word \(w\) in the generators of the subgroup \(G_{x0}\)
of the monster group can be converted to G_x0 representation
by calling function xsp2co1_set_elem_word in file
xsp2co1.c. Here the word \(w\) must be given as an array `
of unsigned 32-bit integers as described in section
Header file mmgroup_generators.h.
The normal subgroup \(Q_{x0}\) of \(G_{x0}\)
The group \(G_{x0}\) also has an extraspecial normal subgroup \(Q_{x0}\) of structure \(2^{1+24}\). There is a natural isomorphism between the normal subgroup \(Q_{x1}\) of \(G(4096_x)\) and \(Q_{x0}\). Considering \(G(4096_x)\) and \(G(24_x)\) as matrix groups, this isomorphism is given by:
We identify \(Q_{x0}\) with \(Q_{x1}\). Both groups are generated by elements \(x_d, x_\delta\), as described above.
We also represent an element of \(Q_{x0}\) as a 25-bit integer in Leech lattice encoding as described in section Description of the mmgroup.generators extension.
Changing the basis of the space \(4096_x\)
We also use the vectors \((d'), d \in \mathcal{P}\) as basis vectors of \(4096_x\) , where:
The reason for introducing this basis is that the operation of \(G_{x0}\) on \(Q_{x0}\) (by conjugation) is easy when we use this basis. Then we obviously have \((-d)' = -(d)'\). We can transform the coordinates of a vector \(v\) from the basis given by \(d^\pm\) to the basis given by \((d)'\) by multiplying the coordinate vector with a matrix \(H\). Multiplication with matrix \(H\) is equivalent to applying the Hadamard gate to Qubit 11 (i.e. to the bit with valence \(2^{11}\)) of the coordinates of \(v\) . Thus \(H\) is an involution.
The numbering of the 4096 basis vectors \((d)'\) corresponds to the numbering of the positive elemments of \(\mathcal{P}\). We may put \((d \oplus 2^{12})' = -(d)'\), where \(\oplus\) means bitwise addition modulo 2; then that correspondence holds for all values \(0 \leq d < 2^{13}\). The exact defnition of the operator \(\oplus\) on the Parker loop \(\mathcal{P}\) is given in section Implementing generators of the Monster group.
In this basis the operation of the extraspecial group \(Q_{x0}\) is very simple:
\(x_e x_{\theta(e)}\) maps \((d)'\) to \((d \oplus e)'\) for \(e \in \mathcal{P}\). Here \(\theta\) is the cocycle, see section The Parker loop. In the language of quantum computing this corresponds to a sequence of commuting not gates.
\(x_\epsilon\) maps \((d)'\) to \((-1)^{\langle d, \epsilon\rangle}(d)'\) for \(\epsilon \in \mathcal{C}^*\). Here \(\mathcal{C}^*\) is the Golay cocode. In the language of quantum computing this corresponds to a sequence of commuting phase-\(\pi\) gates.
Since \(H\) is in \(\mathcal{C}_{12}\), it operates on
\(Q_{x0}\) by conjugation. The following subtlety has to be
considered in function conv_pauli_vector_xspecial (in
file xsp2cco1.c) implementing that operation.
\(H\) exchanges the anticcommuting
elements of \(Q_{x0}\) of with numbers 0x800 and
0x800000 in Leech lattice encoding. Thus it negates
the element with number 0x800800.
Converting an element in G_x0 representation to a word of generators
Perhaps the most inportant function in this module is function
xsp2co1_elem_to_word. This function converts an element of
the subgroup \(G_{x0}\) from G_x0 representation to a
word \(w\) of generators of the monster group. That word
\(w\) is unique and reduced in the sense explained in the
description of that function.
There is also a companion function xsp2co1_reduce_word that
first converts an arbitrary word in the generators of the
subgroup \(G_{x0}\) of the monster to G_x0 representation.
Then it calls function xsp2co1_elem_to_word to compute
the reduced word equal to the input word.
We briefly explain the implementation of function
xsp2co1_elem_to_word. Let \(g \in G_{x0}\) be given in
G_x0 representation. The function first computes the image
\(g^{-1} x_\Omega g\) of \(x_\Omega\) using function
xsp2co1_xspecial_conjugate, with \(\Omega\) as in
[Sey20]. Using that image and function
gen_leech2_reduce_type4 in file gen_leech.c we can
compute a word \(w_1\) in the generators of \(G_{x0}\)
such that \(g_1 = g \cdot w_1\) stabilizes
\(x_\Omega\) up to sign.
Then \(g_1\) is in the monomial subgroup \(N_{x0}\) of
\(G_{x0}\) of structure \(2^{1+24}.2^{11}.M_{24}\). For any
\(g_1 \in N_{x0}\) function xsp2co1_elem_monomial_to_xsp
computes a word in the generators of the monster that is equal
to \(g_1\).
Given a monomial element \(g_1\) in G_x0 representation,
function xsp2co1_elem_monomial_to_xsp computes a word of
generators equal to \(g_1\) as follows.
Ignoring signs and identifying the basis vector \(d_1^+\) of
\(4096_x\) with the basis vector \(d_1^-\), Table 3 in
[Sey20] states that \(x_\pi y_e x_f\) maps
\(d_1^\pm\) to \((d^\pi e f)_1^\pm\). This corresponds
to an affine mapping \(d \mapsto d^\pi e f\) from
\(\mathcal{C} / \langle \Omega \rangle\) to itself, from which
we can easily compute \(e, f\) (modulo sign and \(\Omega\)),
and also \(\pi\). Thus we can find a word \(w_2\) in the
generators \(x_\pi y_e x_f\), such that \(g_2 = g_1 w_2\)
stabilizes all basis vectors of \(4096_x\) up to sign,
and possibly exchanging \(d_1^+\) with \(d_1^-\).
Then \(g_2\) can easily be converted into a word in
the generators
\(x_{-1}, x_\Omega, x_\delta, \delta \in \mathcal{C}^*\).
We use function qstate12_monomial_matrix_row_op in file
qmatrix12.c for obtaining the affine mapping
\(d \mapsto d^\pi e f\) from the G_x0 representation
of \(g_1\). We use the functions in file mat24_functions.c
for obtaining \(\pi\) from that affine mapping.
C functions in xsp2co1.c
File
xsp2co1.ccontains functions for computing in the subgroup \(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\)) of the monster.Functions
- uint64_t xsp2co1_find_chain_short_3(uint64_t v3_1, uint64_t v3_2)
Find vector not orthogonal to vectors in Leech lattice mod 3.
Given two vectors \(v_{3,1}\) and \(v_{3,2}\) in the Leech lattice mod 3, the function returns a vector \(v_{3,3}\) such that the scalar product \(\langle v_{3,3}, v_{3,i} \rangle\) is not zero for both, \(i = 1, 2\). \(v_{3,3}\) has precisely two nonzero coordinates and is hence short. Such a vector \(v_{3,3}\) exists if none of the vectors \(v_{3,1}, v_{3,2}\) is zero. If no such vector \(v_{3,3}\) exists then the function returns 0.
All vectors \(v_{3,i}\) are in given in Leech lattice mod 3 encoding.
- int32_t xsp2co1_chain_short_3(qstate12_type *pqs, uint32_t n, uint64_t *psrc, uint64_t *pdest)
Apply transformation in \(G_{x0}\) to vectors in Leech lattice mod 3.
Let \(x_g \in G(4096_x)\) be given by the quadratic state matrix referred by
pqs. Letpsrcbe an array \((v_0,\ldots v_{n-1})\) of \(n\) short vectors in the Leech lattice mod 3, given in Leech lattice mod 3 encoding. We try to compute \(w_i = v_i x_g\) for \(0 \leq i < n\) and to store \(w_i\) inpdest[i], also in Leech lattice mod 3 encoding. Unfortunately, the short vector \(w_i\) is defined to sign only. In other words, \(x_g\) may correspond to two different elements \(\pm g\) in the automorphisem group \(\mbox{Co}_0\) of the Leech lattice.To specify the correct \(g \in \mbox{Co}_0\), we must store the correct value \(w_0 = v_0 x_0\) in
pdest[0]and provide short vectors \(v_i\) such that the scalar product \(\langle v_{i-1}, v_i\rangle \) of adjacent vectors is not zero for \(i>0\). The the correct values \(v_i x_i\) are determined by ortohonality of \(g\).The function returns garbage if the input conditions for the \(x_g, v_0, w_0\) are not satisfied. It returns a negative value if two adjacent vectors \(v_0\) are orthognal or not short.
- int32_t xsp2co1_elem_to_qs_i(uint64_t *elem, qstate12_type *pqs)
Get component \(x_g^{-1} \in G(4096_x)\) from \(g \in G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem, in G_x0 representation. This means that \(g\) is given as a pair \((x_g, v_g) \in G(4096_x) \times \Lambda / 3 \Lambda\) . The function stores \(x_g^{-1}\) in the structureqsof typeqstate12_typereferred bypqs.Component \(v_g\) is equal to
elem[0](in Leech lattice mod 3 encoding).Caution:
This is a low-level function. After returning, the structure
qsand the arrayelemshare the same data block.Caution:
Internally, we store the inverse of component \(x_g\) in the element \(g\), and this function also stores that inverse in the structure
qs.
- int32_t xsp2co1_elem_to_qs(uint64_t *elem, qstate12_type *pqs)
Get component \(x_g \in G(4096_x)\) from \(g \in G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem, in G_x0 representation. This means that \(g\) is given as a pair \((x_g, v_g) \in G(4096_x) \times \Lambda / 3 \Lambda\) . The function stores \(x_g\) in the structureqsof typeqstate12_typereferred bypqs. \(x_g\) represents a \(4096 \times 4096\) matrix.Caution:
The structure referred by
pqsmust provide sufficient memory for data, see functionqstate12_set_memin fileqstate12.c; herepqs->datashould be at least 25.
- int32_t xsp2co1_qs_to_elem_i(qstate12_type *pqs, uint64_t v_g, uint64_t *elem)
Construct \(g \in G_{x0}\) from pair \((x_g, v_g)\).
The function constructs a \(g \in G_{x0}\) as a pair \((x_g, v_g) \in G(4096_x) \times \Lambda / 3 \Lambda\) and stores the result in the array
elemin G_x0 representation. The value \(x_g^{-1} \in G(4096_x)\) must be given as a structure of typeqstate12_typereferred bypqs. The value \(v_g \in \Lambda / 3 \Lambda\) must be given by parameterv3in Leech lattice mod 3 encoding.Caution:
As a low-level function, this function may construct a value \(g\) which is not in \(G_{x0}\). Function
xsp2co1_set_elem_wordshould be used for constructing an element of \(G_{x0}\) instead.Caution:
Internally, we store the inverse of component \(x_g\) in the element \(g\), and this function also requires that inverse in the structure referred by
pqs.
- int32_t xsp2co1_reduce_elem(uint64_t *elem)
Reduce an \(g \in G_{x0}\) to a standard form.
Let \(g \in G_{x0}\) be stored in the array
elem, in G_x0 representation. This means that \(g\) is stored as a pair \((x_g, v_g) \in G(4096_x) \times \Lambda / 3 \Lambda\) . The function reduces the components \(x_g\), \(v_g\) to their standard form in place.In functions that construct elements of \(G_{x0}\) these components are reduced automatically.
- void xsp2co1_neg_elem(uint64_t *elem)
Negate an \(g \in G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem, in G_x0 representation. The function negates \(g\) in place.Negation is equivalent to multiplication with the generator \(x_{-1}\), and also to multiplication with the generator \(y_{\Omega}\).
- void xsp2co1_copy_elem(uint64_t *elem1, uint64_t *elem2)
Copy a \(g \in G_{x0}\).
The function copies the element of \(G_{x0}\) stored in the array
elem1(in G_x0 representation) to the arrayelem2.
- int32_t xsp2co1_elem_to_bitmatrix(uint64_t *elem, uint64_t *pA)
Map element of \(G_x0\) to a bit matrix.
The function maps the element of \(G_{x0}\)
stored in
the array
elem(in G_x0 representation) to a \(24 \times 24\) bit matrix \(A\), which will be stored in the array referred bypA. Bit matrix \(A\) operates on a vector on the Leech lattice modulo 2 (in Leech lattice encoding) by right multiplication.So this function computes the homomorphism from the group \(G_{x0}\) onto the group \({Co}_1\).
- int64_t xsp2co1_map_short3(qstate12_type *pqs, uint64_t src1, uint64_t dest1, uint64_t src2)
Image of short vector in Leech lattice under \(G_{x0}\).
Let
pqspoint to a quadratic state matrixqsthat corresponds to an element \(g\) of the factor \(4096_x\) the representation \(24_x \otimes 4096_x\) of \(G_{x0}\). Note that the operation of \(g\) on the Leech lattice (by conjugation) is determined up to sign only.Assuming that
qsmaps the short vectorsrc1in the Leech lattice (modulo 3) todest1, the sign mentioned above is determined. Then we may compute the imagedest2of any short vectorsrc2in the Leech lattice (modulo 3).Given
qs,src1,dest1, andsrc2, the function returns the imagedest2ofsrc2. All short Leech lattice vectors (modulo 3) are given in Leech lattice mod 3 encoding.The function returns a negative value in case of error. If
dest1is not a valid image ofsrc1then the result is undefined. The function may or may not detect such an error.
- int32_t xsp2co1_mul_elem(uint64_t *elem1, uint64_t *elem2, uint64_t *elem3)
Multiply two elements of the group \(G_{x0}\).
Let \(g_1, g_2 \in G_{x0}\) be stored in the arrays
elem1,elem2in G_x0 representation. The function computes \(g_1 \cdot g_2 \) and stores the result in the arrayelem3in G_x0 representation.Any kind of overlapping beween the arrays
elem1,elem2, andelem3is allowed.
- int32_t xsp2co1_inv_elem(uint64_t *elem1, uint64_t *elem2)
Invert an element of the group \(G_{x0}\).
Let \(g_1 \in G_{x0}\) be stored in the array
elem1, in G_x0 representation. The function computes \(g_1^{-1}\) and stores the result in the arrayelem2in G_x0 representation.Any kind of overlapping beween the arrays
elem1andelem2is allowed.
- int32_t xsp2co1_conj_elem(uint64_t *elem1, uint64_t *elem2, uint64_t *elem3)
Conjugate elements of the group \(G_{x0}\).
Let \(g_1, g_2 \in G_{x0}\) be stored in the arrays
elem1,elem2in G_x0 representation. The function computes \(g_2^{-1} \cdot g_1 \cdot g_2 \) and stores the result in the arrayelem3in G_x0 representation.Any kind of overlapping beween the arrays
elem1,elem2, andelem3is allowed.
- int32_t xsp2co1_xspecial_conjugate(uint64_t *elem, uint32_t n, uint64_t *ax, uint32_t sign)
Conjugation of elements of \(Q_{x0}\) with an element of \(G_{x0}\).
Let \(x_0,\ldots,x_{n-1}\) a list of \(n\) elements of \(Q_{x0}\) stored in the the array
axin Leech lattice encoding. Let \(g \in G_{x0}\) be stored in the arrayelemin G_x0 representation.Then the function replaces the element \(x_i\) by \(g^{-1} x_i g\) for \(0 \leq i < n\).
Parameter
signshould usually be a nonzero value. In casesign = 0the signs of the returned vectors are not computed.
- int32_t xsp2co1_xspecial_img_omega(uint64_t *elem)
Conjugation of \(\Omega\) with an element of \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation, and let \(\Omega\) be the standard frame in the Leech latice. The function returns \(g^{-1} \Omega g\) in Leech lattice encoding, ignoring the sign of the result.
- int32_t xsp2co1_elem_check_fix_short(uint64_t *elem1, uint32_t v)
Check if an element of \(G_{x0}\) fixes a short vector.
This function is deprecated!
Let \(v\) be the short vector in the Leech lattice modulo 2 given by parameter
vin Leech lattice encoding. Let \(g \in G_{x0}\) be stored in the arrayelemin G_x0 representation.If \(v\) is short then it corresponds to a vector \(v'\) in the 24-dimensional Leech lattice \(\Lambda\) up to sign. Note that the operation of \(G_{x0}\) on \(\Lambda\) is also defined up to sign only. So in the general case we cannot distinguish whether \(g\) fixes or negates \(v'\).
However, \(G_{x0}\) has a (faithful) representation on the tensor product \(\Lambda \otimes 4096_x\) for a certain representation \(4096_x\), see [Con85] for details. Here the operation of \(G_{x0}\) on \(4096_x\) is also defined up to sign only.
If the character of \(g\) on \(4096_x\) is nonzero then we can flip the signs in both representations, \(\Lambda\) and \(4096_x\), without changing the tensor product. Thus requiring the character of \(g\) on \(4096_x\) to be positive determines the sign of the operation of \(g\) on \(\Lambda\) uniquely. In this case we return 0 if \(g\) fixes the vector \(v'\), and 1 if \(g\) negates \(v'\). Otherwise we return 6.
If the character of \(g\) on \(4096_x\) is zero then there is no way to determine the sign of the operation of \(g\) on \(\Lambda\). In this case we return 2 if \(g\) fixes the vector \(v'\) (up to sign) and 6 otherwise.
In cases where \(g\) and \(-g\) are in different classes in \(G_{x0}\) we may sometimes obtain the class of \(g\) by using this function.
We return a negative value in case of any error. It is an error if \(v'\) is not short, i.e. \(v\) is not of type 2.
- int32_t xsp2co1_xspecial_vector(uint64_t *elem)
Convert \(x \in Q_{x0}\) from \(G_{x0}\) rep to Leech.
Let \(x \in Q_{x0} \subset G_{x0}\) be stored in the array
elemin G_x0 representation. The function returns \(x\) as an integer in Leech lattice encoding.The function returns a negative number in case of error. E.g. in case \(x \notin Q_{x0}\) it returns
ERR_QSTATE12_NOTIN_XSP.
- void xsp2co1_unit_elem(uint64_t *elem)
Store neutral element of \(G_{x0}\).
The function stores the neutral element of \(G_{x0}\) in the array
elemin G_x0 representation.
- uint32_t xsp2co1_is_unit_elem(uint64_t *elem)
Check if
elemis neutral element of \(G_{x0}\).The function returns 1 if
elemis the neutral element of \(G_{x0}\) and 0 otherwise.
- int32_t xsp2co1_elem_xspecial(uint64_t *elem, uint32_t x)
Convert \(x \in Q_{x0}\) from Leech to \(G_{x0}\) rep
Let \(x \in Q_{x0} \subset G_{x0}\) be stored in parameter
xin Leech lattice encoding. The function converts \(x\) to G_x0 representation and stores the result in the arrayelem.
- int32_t xsp2co1_mul_qs_v3_word(qstate12_type *pqs, uint64_t *pv3, uint32_t *a, uint32_t n, uint32_t s)
Auxiliary function for function
xsp2co1_mul_elem_wordFunction
_mul_set_qs_v3_word(pqs, pv3, a, n, s)multiplies the element \(g\) of the group \(G_{x0}\) with an element \(h\) of that group and replaces \(g\) by \(g \cdot h\).Element \(g\) of \(G_{x0}\) is represented as a pair
(qs, v3), whereqsis a quadratic state matrix of shape (12, 12) referred by parameterpqs, andv3is a vector in the Leech lattice mod 3 referred by parameterpv3. Herev3must be given in Leech lattice mod 3 encoding. The objectsqsandv3are multiplied by \(g\) in place.Element \(h\) is given as a word of generators of the monster group of length
nstored in the arraya.If
sis nonzero thenqsis set to the quadratic state unit matrix of shape (12, 12), andv3is set to the standard vector (0, 0, 1, -1, 0, …, 0) in the Leech lattice mod 3, before the multiplication starts.The function stops if an atom in array
ais not in \(G_{x0}\). It returns the numberkof atoms ofathat have been processed. In case of failure it returns a negative value.Remarks
As documented in function
xsp2co1_elem_to_qs_i, we actually store the inverse of a the group element \(g\) in an array representing an element \(G_{x0}\). For compatibility with that function we actually replace the element \(g^{-1}\) stored in the structureqsby \((g h)^{-1}\). In other words, we left-multiply the value stored inqsby \(h^{-1}\). Note that \(h^{-1} = h^{\top}\) holds for an orthogonal matrix \(h\).The function also works correctly for any quadratic state matrix
qs1of shape (12, 0) stored in the structure referred bypqs. A pair(qs1, v3)withqs1a quadratic state of shape (12,0), andv3as above, has a natural interpretation a vector in the representation of \(G_{x0}\) called \(24_x \otimes 4096_x\) in [CS99], with entries taken modulo 3. So we may also use this function for computations in that representation of \(G_{x0}\).
- int32_t xsp2co1_mul_elem_word(uint64_t *elem, uint32_t *a, uint32_t n)
Right multiply an element of \(G_{x0}\) with a word of generators.
Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation. We replace \(g\) by \(g \cdot w\), where \(w\) is a word in the generators of \(G_{x0}\) of length \(n\). \(w\) is stored in the arraya, and each entry ofaencodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h.The function fails and returns ERR_QSTATE12_GX0_TAG if not all atoms of the word \(w\) are in \(G_{x0}\).
- int32_t xsp2co1_set_elem_word(uint64_t *elem, uint32_t *a, uint32_t n)
Convert word of generators of \(G_{x0}\) to G_x0 representation.
Let \(w\) be a word in the generators of \(G_{x0}\) of length \(n\). \(w\) is stored in the array
a, and each entry ofaencodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h. We convert the word \(w\) to an element of \(G_{x0}\) in G_x0 representation and store the result in the arrayelem.The function fails and returns ERR_QSTATE12_GX0_TAG if not all atoms of the word \(w\) are in \(G_{x0}\).
- int32_t xsp2co1_mul_elem_atom(uint64_t *elem, uint32_t v)
Right multiply an element of \(G_{x0}\) with a generator.
Equivalent to
xsp2co1_mul_elem_word(elem, &v, 1)
- int32_t xsp2co1_set_elem_atom(uint64_t *elem, uint32_t v)
Convert a generator of \(G_{x0}\) to G_x0 representation.
Equivalent to
xsp2co1_set_elem_word(elem, &v, 1)
- int32_t xsp2co1_set_elem_word_scan(uint64_t *elem, uint32_t *a, uint32_t n, uint32_t mul)
Convert word of generators of \(G_{x0}\) to G_x0 representation.
Parameters and operation are as in function
xsp2co1_set_elem_word. But in contrast to functionxsp2co1_set_elem_word, this function succeeds also if just a prefix of the wordais in the subgroup \(G_{x0}\).Let
kbe the greatest number such that all prefixes ofaof length at mostkare in the group \(G_{x0}\). Let \(a_k\) be the element of \(G_{x0}\) corresponding to the prefix ofaof lengthk.If parameter
mulis zero then we convert the word \(a_k\) to an element of \(G_{x0}\) in G_x0 representation and store the result in the arrayelem. Otherwise we multiply the elementelemwith the word \(a_k\) and store the array inelem.
C functions in xsp2co1_word.c
File
xsp2co1_word.ccontains additional functions for computing in the subgroup \(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\)) of the monster. This file can be considered as a supplement to filexsp2co1.c.Functions
- uint64_t xsp2co1_to_vect_mod3(uint64_t x)
Convert vector from Leech lattice mod 3 to
mmgroup.mm_opencoding.The function converts a vector in \(\Lambda / 3\Lambda\) from Leech lattice mod 3 encoding to the encoding to the encoding of a vector in \((\mathbb{Z} / 3\mathbb{Z})^{24}\) used in the
mmgroup.mm_opextension.
- uint64_t xsp2co1_from_vect_mod3(uint64_t x)
Inverse of function
xsp2co1_to_vect_mod3The function converts a vector in \(\Lambda / 3\Lambda\) from the encoding of a vector in \((\mathbb{Z} / 3\mathbb{Z})^{24}\) used in the
mmgroup.mm_opextension to the Leech lattice mod 3 encoding.
- int32_t xsp2co1_elem_to_leech_op(uint64_t *elem, int8_t *pdest)
Get Leech lattice matrix from \(g \in G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem, in G_x0 representation. \(G_{x0}\) operates faithfully on the space \(4096_x \otimes_\mathbb{Z} \Lambda\). This function constructs a \(24 \times 24\) integer matrix \(L_g\) such that \(\frac{1}{8} L_g\) corresponds to the operation of \(g\) on \(\Lambda\). It stores entry \(L_g[i,j]\) indest[24*i+j]. Matrix \(L_g\) is unique up to sign.Function
xsp2co1_elem_to_qs(elem,...)computes a (representation of) an orthogonal \(4096 \times 4096\) matrix \(x_g\) such that right multiplication with the Kronecker product \(\frac{1}{8} x_g \otimes L_g\) is equal to the action of \(g\) on \(4096_x \otimes \Lambda\).
- int32_t xsp2co1_short_3_to_leech(uint64_t x, int8_t *pdest)
Compute integral short Leech lattice vector from vector mod 3.
Given a short Leech lattice vector
x(modulo 3) in Leech lattice mod 3 encoding, the function computes the real coordinates of vectorxin the array referred bypdest.pdestmust have length 24. As usual, the norm (i.e. the squared sum of the coordinates) of the computed short vector is normalized to 32.The function returns 0 if
xencodes a short Leech lattice vector mod 3 and a negative value otherwise.
- int32_t xsp2co1_short_2_to_leech(uint64_t x, int8_t *pdest)
Compute integral short Leech lattice vector from vector mod 2.
Given a short Leech lattice vector
x(modulo 2) in Leech lattice encoding, the function computes the real coordinates of vectorxin the array referred bypdest.pdestmust have length 24. As usual, the norm (i.e. the squared sum of the coordinates) of the computed short vector is normalized to 32. Note that the result is defined up to sign only. Here the function chooses an arbitrary sign.The function returns 0 if
xencodes a short Leech lattice vector mod 2 and a negative value otherwise.
- int32_t xsp2co1_elem_monomial_to_xsp(uint64_t *elem, uint32_t *a)
Map monomial element of \(G_{x0}\) to element of \(Q_{x0}\).
Let \(g \in G_{x0}\) stored in the array
elem. The matrix corresponding to \(g\) in the representation \(4096_x\) must be monomial. The function computes a word \(w\) of in the generators of \(G_{x0}\) such that \(g w \in Q_{x0}\). The word \(w\) has length at most 2 and is stored in the arraya. Each entry ofaencodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h. The function returns the length of that word.The atoms in the word have tags
p, yin that order. Each word is stored as the inverse of a generator.
- int32_t xsp2co1_elem_to_word(uint64_t *elem, uint32_t *a)
Convert element of \(G_{x0}\) to a word in its generators.
Let \(g \in G_{x0}\) be stored in the array
elem. The function converts \(g\) to a reduced word in the generators of \(g\) and stores that word in the arraya. Then each entry ofaencodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h. The function returns the length of that word.The reduced word stored in the array
amay have up to 10 entries. The tags of the entries in that word arexdyplplplpin that order. See documentation of classmmgroup.MMGroupfor the meaning of these tags. Each entry of a word may encode the neutral element as a generator; then that entry is dropped. We assert that the number of entries with taglis minimal.
- int32_t xsp2co1_reduce_word(uint32_t *a, uint32_t n, uint32_t *a1)
Reduce a word of generators of \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
aas a word \(w\) of length \(n\). The function computes the reduced word \(w_1\) equal to \(w\) in the arraya1and returns the length of the reduced word. Legal tags for the word \(w\) ared,x,y,p, andl. See documentation of classmmgroup.MMGroupfor the meaning of these tags.It uses function
xsp2co1_elem_to_wordfor computing \(w_1\). The word \(w_1\) stored in the arraya1may have up to 10 entries. Arraysaanda1may overlap.
- int32_t xsp2co1_elem_subtype(uint64_t *elem)
Return the subtype of an element of \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem. The function returns the subtype of \(g\). If \(g\) maps the standard frame \(\Omega\) of the Leech lattice modulo 2 to a frame of subtype \(t\) then \(g\) has subtype \(t\).The subtype is returned as an integer as in function
gen_leech2_subtypein modulegen_leech.c.Since the subtype is determined by the size of the denominators of the representation \(4096_x\), it can be computed very fast.
The function returns -1 in case of an error.
- uint32_t xsp2co1_check_word_g_x0(uint32_t *w, uint32_t n)
Check if a word of generators of the monster is in \(G_{x0}\).
We check if the word
wof lengthnof generators of the monster group is in the subgroup \(G_{x0}\). The function returns the following status information:0:
wis in \(G_{x0}\)1:
wis not in \(G_{x0}\)2: Nothing is known about
wWords of generators of the monster are implemented as described in file
mmgroup_generators.h.
- int32_t xsp2co1_isotropic_type4(uint32_t v, uint64_t *pB, int32_t n)
Compute maximal isotropic space corresponding to a type-4 vector.
This function is deprecated and will be removed!!
Any type-4 vector in the Leech lattice mod 2 corrsponds to a unique maximal isotropic space (of dimension 12) in the Leech lattice mod 2. E.g. the standard type-4 vector \(\Omega\) corresponds to the space spanned by \(\Omega\) and (the images in the Leech lattice mod 2 of) all even Golay cocode words.
Given a type-4 vector \(v\) in Leech lattice encoding, we usually want to find the intersection of the isotropic space \(v^{(\perp)}\) corresponding to \(v\) with a given linear subspace \(X\) of the Leech lattice mod 2. Let \(X\) be the space spanned by the vectors \(b_0,...,b_{n-1}\) in the array
Breferred bypBof sizen.The function modifies the basis in the array
B, so that it will be the a basis of the space \(v^{(\perp)} \cup X\) of dimensionmin reduced echelon form. The function returnsmin case of success and a negative value in case of failure. The function fails if \(v\) is not of type 4.In case \(n < 0\) we assume that
Bis a basis of the whole Leech lattice mod 2 and return a basis of \(v^{(\perp)}\) inB. ArrayBmust have size at least \(\max(n, 12)\).
- int64_t xsp2co1_isotropic_type4_span(uint32_t v, uint32_t *pB, int32_t n)
Compute maximal isotropic space corresponding to a type-4 vector.
Any type-4 vector \(v\) in the Leech lattice mod 2 corresponds to a unique maximal isotropic space \(v^{(\perp)}\) (of dimension 12) in the Leech lattice mod 2. E.g. the standard type-4 vector \(\Omega\) corresponds to the space spanned by \(\Omega\) and (the images in the Leech lattice mod 2 of) all even Golay cocode words.
Given a type-4 vector \(v\) in Leech lattice encoding, we want to find the space \(Y\) spanned by the isotropic space \(v^{(\perp)}\) and a given linear subspace \(X\) of the Leech lattice mod 2. Let \(X\) be the space spanned by the vectors \(b_0,...,b_{n-1}\) in the array
Breferred bypBof sizen. Herenmay be at most 24. In any case, the buffer referred bypBmust have size 24.The function modifies the basis in the array
B, so that it will be a basis of the space \(Y\) in reduced echelon form. The function returns the dimensionmof that space in case of success and a negative value in case of failure. The function fails if \(v\) is not of type 4.If the space \(Y\) has dimension
n = 23then the function also computes the unique nonzero vector \(w\) in the Leech lattice mod 2 orthogonal to \(Y\), and returns0x100 * w + ninstead ofn.
- int32_t xsp2co1_elem_row_mod3(uint64_t *elem, uint32_t column, uint64_t *v)
A low-level function to be used for testing.
A projection matrix \(\Pi\) is a symmetric matrix with one eigenvalue 1 and the other eigenvalues equal to zero operating on an Euclidean vector space. Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation. This function left multiplies \(g\) by a certain projection matrix \(\Pi\). The result \(y = \Pi \cdot g\) is an element of the vector space \(4096_x \otimes 24_x\). The function reduces the coordinates of \(y\) modulo 3 and stores the result in the arrayvin a format compatible the format used in themmgroup.mm_opextension.Right multiplcation of \(g\) by \(G_{x0}\) commutes with left multiplication of \(g\) by \(\Pi\), so that we can test the right multiplication by \(G_{x0}\) implemented in this module against the corresponding multiplication implemented in the
mmgroup.mm_opextension. This leads to the important interoperability test in the python functionmmgroup.tests.test_clifford.test_xs1_vector.test_vector.We specify the projection matrix \(\Pi\) as a tensor product \(\Pi_{4096} \otimes \Pi_{24}\). Here \(\Pi_{24}\) projects onto the fixed short Leech lattice vector \((0,0,1,-1,0, \ldots,0)\). \(\Pi_{4096}\) is the projection onto the coordinate with number
columnof the space \(4096_x\).Remark:
The result is an array with 4096 entries corresponding to the entries with tags
ZandYof a vector in the represention \(\rho_3\), as described in section The Representation of the Monster Group of the API reference.Warning:
This function works only if the data type
uint_mmv_tused in themmgroup.mm_opextension is equal to the data typeuint64_t.
- int32_t xsp2co1_elem_read_mod3(uint64_t *v, uint64_t *elem, uint32_t row, uint32_t column)
Read entry of a transformed vector of the monster rep modulo 3.
Let \(g \in G_{x0}\) be stored in the array
elem. Let \(v\) be the vector of the representation \(4096_x \otimes 24_x\) modulo 3 stored in the arrayvin a format compatible to the format used in themmgroup.mm_opextension. Then the function returns the entry of the vector \(v' = v \cdot g^{-1}\) in row0 <= row < 4096and column0 <= column < 24of \(v'\).This function is considerably faster than the computation of \(v' = v \cdot g^{-1}\) using the functions in the
mmgroup.mm_opextension.In case
column = 24the function returns the value(v'[row,2] - v'[row,3]) mod 3. In case of success the return value is a nonnegative integer less than 3. A negative return value indicates failure.This function is deprecated and will be removed!
C functions in xsp2co1_elem.c
File
xsp2co1_elem.ccontains functions for analyzing elements of the subgroup \(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\)) of the monster.Functions
- int32_t xsp2co1_elem_to_N0(uint64_t *elem, uint32_t *g)
Convert element of \(G_{x0}\) to element of \(N_{0}\).
Let \(g \in G_{x0}\) be stored in the array
elem1in G_x0 representation. The function converts \(g\) to an element \(N_0\), as described in the documentation of filemm_group_n.c. The result is stored in the array of length 5 referred by parameterg.The function returns 0 in case of success and
ERR_QSTATE12_GX0_BAD_ELEMif \(g\) is not and \(N_0\).
- int32_t xsp2co1_elem_from_N0(uint64_t *elem, uint32_t *g)
Convert element of \(N_{0}\) to element of \(G_{x0}\).
Let \(g \in N_{0}\) be stored in the array of length 5 referred by parameter
gas described in the documentation of filemm_group_n.c. We convert \(g\) to an element in G_x0 representation and store the result in the arrayelem.The function returns 0 in case of success and
ERR_QSTATE12_GX0_BAD_ELEMif \(g\) is not in \(G_{x0}\).
- int32_t xsp2co1_conjugate_elem(uint64_t *elem, uint32_t *a, uint32_t n)
Conjugate element of \(G_{x0}\) by an element of monster group.
Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation. Let \(w\) be a word in the generators of the monster group of lengthn. \(w\) is stored in the arraya, and each entry ofaencodes a generator of the monster group described in filemmgroup_generators.h.The function tries to replace \(g\) by \(h = w^{-1} g w\). The function succeeds if for any prefix \(w_i\) of the word \(w\) we have \(w_i^{-1} g w_i \in G_{x0}\).
- int32_t xsp2co1_power_elem(uint64_t *elem1, int64_t e, uint64_t *elem2)
Exponentiation of an element of the group \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem1in G_x0 representation. The function computes the power \(g^e\) and stores the result in the arrayelem2in G_x0 representation. Here \(-2^{63} < e < 2^{63}\) must hold.A negative return value indicates an error.
Any kind of overlapping beween the arrays
elem1andelem2is allowed.
- int32_t xsp2co1_power_word(uint32_t *a1, uint32_t n, int64_t e, uint32_t *a2)
Exponentiation of an word of the group \(G_{x0}\).
Let \(w\) be a word in the generators of \(G_{x0}\) of length
n. \(w\) is stored in the arraya1, and each entry ofa1encodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h.The function stores \(w^e\) in the array
a2in the same format as the word \(w\) and returns the length of the computed word, which is at most 10.A negative return value indicates an error.
Any kind of overlapping beween the arrays
a1anda2is allowed.
- int32_t xsp2co1_odd_order_bitmatrix(uint64_t *bm)
Compute odd part of the order of an element of \(\mbox{Co}_1\).
Let an element \(g\) of \(\mbox{Co}_1\) be given as a 24 times 24 bit matrix in the array
bmacting on the Leech lattice modulo 2 by right multiplication. Here vectors in the Leech lattice modulo 2 are given in Leech lattice encoding.Then the function returns the odd part of the order of \(g\). It returns a negative value in case of failure.
- int32_t xsp2co1_half_order_elem(uint64_t *elem1, uint64_t *elem2)
Compute (halved) order of an element of the group \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem1in G_x0 representation. The function returns the order of the element \(g\).If the order \(o\) of \(g\) is even then the function stores \(g^{o/2}\) in the array
elem2in G_x0 representation. Otherwise it stores the neutral element inelem2.A negative return value indicates an error.
Any kind of overlapping beween the arrays
elem1andelem2is allowed.
- int32_t xsp2co1_order_elem(uint64_t *elem)
Compute order of an element of the group \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elem1in G_x0 representation. The function returns the order of the element \(g\).A negative return value indicates an error.
- int32_t xsp2co1_half_order_word(uint32_t *a1, uint32_t n, uint32_t *a2)
Compute (halved) order of a word of the group \(G_{x0}\).
Let \(w\) be a word in the generators of \(G_{x0}\) of length
n. \(w\) is stored in the arraya1, and each entry ofa1encodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h.If the order \(o\) of the word \(w\) is even then the function stores \(w^{o/2}\) in the array
a2in the same format as the word \(w\). Otherwise it stores the empty word ina2. The lengthkof the word ina2is at most 10.The function returns the value
0x100 *o + k.A negative return value indicates an error.
- int32_t xsp2co1_order_word(uint32_t *a, uint32_t n)
Compute order of a word of the group \(G_{x0}\).
Let \(w\) be a word in the generators of \(G_{x0}\) of length
n. \(w\) is stored in the arraya, and each entry ofaencodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h.The function returns the order of \(w\) .
A negative return value indicates an error.
- uint32_t xsp2co1_leech2_count_type2(uint64_t *a, uint32_t n)
Count type-2 vectors in an affine subspace of the Leech lattice mod 2.
This function returns the number of type-2 vectors in an affine subspace \(V\) of the Leech lattice mod 2. Subspace \(V\) is defined by an array \(a\) of length \(n\) of bit vectors. \(V\) is given by:
\(V = \{a_0 + \sum_{i=1}^{n-1} \lambda_i a_i \mid \lambda_i=0,1\}\).
Caution:
The function may change the description of the affine space \(V\) in the array \(a\) to a different description of the same space \(V\).
Remark:
This function is a much faster version of the function
gen_leech2_count_type2in filegen_leech.c. The implementation of the latter function is much simpler; so we keep it for test purposes.
- int32_t xsp2co1_trace_98280(uint64_t *elem, int32_t (*f_fast)(uint64_t*))
Compute character of \(\rho_{98280}\) of element of \(G_{x0}\).
This function is for internal use only.
Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation. The function returns the character of the representation \(\rho_{98280}\).This function may takes a long time is it does not use precomputed tables. However, precomputing such tables may requires this function (being alled without any precomputed tables).
In parameter
f_fastthe user may specify a function with signatureint32_t (*f_fast)(uint64_t *elem)that returns the character \(\rho_{98280}\) in some cases. That function should use precomputed tables for computing that character and return an error code if it cannot compute a character. In this case we use the standard method form computing the requested character. Iff_fastisNULLthen we always use the standard method.Any value less than -0x1000000 returned by function
f_fastor by this function is to be interpreted as an error.
- int32_t xsp2co1_traces_small(uint64_t *elem, int32_t *ptrace)
Workhorse for function
xsp2co1_traces_allThis function is for internal use only.
Parameters and operation are are as in function
xsp2co1_traces_all. But this function does not compute the character of the representation \(\rho_{98280}\) inptrace[3].
- int32_t xsp2co1_traces_all(uint64_t *elem, int32_t *ptrace)
Compute relevant characters of element of \(G_{x0}\).
This function is for internal purposes only.
Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation. The function computes the characters of the representations \(\rho_{24}, \rho_{576}, \rho_{4096}, \rho_{98280}\) and stores the result inptrace[0],..., ptrace[3]in that order.This function returns 0 in case of success and a nonzero value otherwise.
There is a considerably faster function
xsp2co1_traces_allin modulexsp2co1_traces.cperforming exactly the same operation depending in the same input parameters. More details are given in the documentation of that function.In contrast to function
xsp2co1_traces_fast, this function does not use any precomputed tables. Actually, this function is used for precomputing those tables.
- int32_t xsp2co1_rand_word_N_0(uint32_t *w, uint32_t in_N_x0, uint32_t even, uint64_t *seed)
Generate a random element of the group \(N_0\).
The function computes a uniform distributed random element \(g\) of the subgroup \(N_0\) of structure \(2^{2+11+22}.(M_{24} \times \mbox{Sym}_3)\) of the monster. The group \(N_0\) is generated by the generators with tags
x, y, d, p, t.Thw function stores a word representing the element \(g\) in the buffer
wand returns the length of that word.The length of the word in the buffer
wis at most 5.If parameter
in_N_x0is nonzero then we compute a random element of the subgroup \(N_{x0}\) of index 3 in \(N_0\) generated by the generators with tagsx, y, d, p.If parameter
evenis nonzero then we compute a random element of the subgroup \(N_{\mbox{even}}\) of index 2 in \(N_{0}\) generated by the generators with tagsx, y, d, p, t, where all generators with tagdcorrespond to even Golay cocode words.If both,
in_N_x0andeven, are nonzero then we compute a random element of \(N_{xyz0} = N_{\mbox{even}} \cap N_{x0}\).The function uses the internal random generator in file
gen_random.c. Parameterseedmust be a seed for a random generator as described in filegen_random.c.
- int32_t xsp2co1_rand_word_G_x0(uint32_t *w, uint64_t *seed)
Generate a random element of the group \(G_{x0}\).
The function computes a uniform distributed random element \(g\) of the group \(G_{x0}\). It stores a word representing the element \(g\) in the buffer
wand returns the length of that word.The length of the word in the buffer
wis at most 10.The function uses the internal random generator in file
gen_random.c. Parameterseedmust be a seed for a random generator as described in filegen_random.c.A negative return value indicates an error.
C functions in leech2matrix.c
File
leech2matrix.ccontains functions for computing with matrices Leech lattice modulo 2.Functions
- int32_t leech2matrix_add_eqn(uint64_t *m, uint32_t nrows, uint32_t ncols, uint64_t a)
Add an equation to a system of linear bit equations.
The idea behind this function is that an external process generates rows of a bit matrix with
ncolscolumns, with0 < ncols <= 32. This function checks such a rowaand accepts it, if it linearly independent of all previously accepted rows. Thus at mostncolsrows can be accepted. Thenrowsalready accepted rows are stored in the arraym. The function returns1if rowais accepted and0otherwise. A negative return value indicates an error. The size of the arraymshould be at leastncols.Let
Abe thenrowstimesncolsmatrix of all accepted rowsa[i],0 <= i < ncols; and letIbe thenrowstimencolsmatrix obtained by transforming matrixAto reduced echelon form. (ThusIis the unit matrix in casenrows = ncols). We left multiplyAwith a matrixTsuch thatT * A = I.Technically, we perform row operations on the matrix
A[:nrows]containing the firstnrowslines already accepted, such thatT * A[:rnows]is in reduced echelon form. We also perform the same row operations on thenrowstimesnrowsunit matrix to obtainT. We storeT[:rnows]in columns0,...,ncols-1of matrixM, andT*A[:rnows]in columnsncols,...,ncols + nrows - 1of matrixM.One may use functions
leech2matrix_prep_eqnandleech2matrix_solve_eqnfor solving a system of linear equations obtained in that way.
- int32_t leech2matrix_prep_eqn(uint64_t *m, uint32_t nrows, uint32_t ncols, uint32_t *b)
Adjust result of function
leech2matrix_add_eqnThe function adjusts the matrix in the array
mobtained after a (repeated) application of functionleech2matrix_add_eqn, so that a (possibly underdetermined) equation system can be solved with functionleech2matrix_solve_eqn.Parameters
m,nrows, andncolsare as in functionleech2matrix_add_eqn.Let
Abe thenrowstimesncolsmatrix of all accepted rowsa[i]. Letvbe a row vector ofnrowsbit length; and letxbe an unknown row vector ofncolsbit length. We want to solve the equation
A * x^T = v^T,where
x^Tandv^Tare the transposed (column) vectors ofxandv.The function computes an
nrowstimesncolsbit matrixBand stores that matrix in the arrayb. Thenx = v * Bis a solution of the equation given above. That solution can be computed with functionleech2matrix_solve_eqn. Output arraybmust have size at leastnrows.Matrix
Bis essentially the matrixTcomputed by functionleech2matrix_add_eqn. If the leading coefficient of rowiof the echelonized matrixT * Acomputed by functionleech2matrix_add_eqnis in columnjthen columnjof matrixBis equal to columniof matrixT. Columns of matrixBthat cannot be obtained in this way are zero.
- uint32_t leech2matrix_solve_eqn(uint32_t *b, uint32_t nrows, uint64_t v)
Solve a system of linear bit equations.
The function returns the product
v * b, wherevis a bit vector of lengthnrows; andbis annrowstimesncolsbit matrix.This function can be used for solving linear bit equations. For background we refer to functions
leech2matrix_add_eqnandleech2matrix_prep_eqn.
- void leech2matrix_echelon_eqn(uint64_t *m, uint32_t nrows, uint32_t ncols, uint64_t *m1)
Store echelonized matrix of linear bit equations.
Let
m,nrows,ncolsbe as in the description of functionleech2matrix_echelon_eqn; and letAandTbe as in that description. ThenT * Ais the reduced echelon form of the matrixAof all previously accepted equations. Functionleech2matrix_echelon_eqnstores that matrixT * Ain the bufferm1of lengthnrows.
- int64_t leech2matrix_subspace_eqn(uint64_t *m, uint32_t nrows, uint32_t ncols, uint64_t v)
Check if a bit vector is in a certain space.
Let
mbe a bit matrix encoding a set of linear independent bit vectors as returned by functionleech2matrix_add_eqn. LetAbe thenrowstimesncolsmatrix with row vectors equal to these independent bit vectors, as in functionleech2matrix_add_eqn.The function checks if bit vector
vis in the space spanned by these vectors. If this is the case then the function returns a bit vectorxwithx * A = v. Otherwise it returns a negative value.
- uint32_t leech2_matrix_basis(uint32_t *v2, uint32_t n, uint64_t *basis, uint32_t d)
Subspace generated by vectors of Leech lattice modulo 2.
Compute a basis of the subspace of the Leech lattice modulo 2 generated by the vectors
v2[0],...,v2[n-1].The function returns the dimension
kof that subspace and computes a basis of that subspace inbasis[i], 0 <= i < k.Here
dmust be an upper bound for the dimensionk. Ifkis unknown, one should putd = 24.Bits 23,…,0 of the output matrix are echelonized in a special way. Here the columns are processed in the order:
11, 22, 21, …, 13, 12, 10, 9, …, 1, 0, 23.
One of the advantages of this echelonization is that the vector \(\Omega\) (encoded as 0x800000) will occur in the basis if it is in the subspace, and that there are many even vectors (i.e. vectors orthogonal to \(\Omega\)) in the basis.
- int32_t leech2_matrix_orthogonal(uint64_t *a, uint64_t *b, uint32_t k)
Compute standard orthogonal complement in Leech lattice mod 2.
Let \(A = a_0\ldots, a_{k-1}\) be a matrix of \(k\) vectors in the Leech lattice mod 2 stored in the array
a. The function returns a basis \(B = b_0\ldots, b_{23}\) of the Leech lattice mod 2 in the arrayb, and it returns a number \(m\) such that the vectors \(b_m\ldots, b_{23}\) are a basis of the orthogonal complement of the space generated by the row vectors of \(A\).If the vectors \((a_0\ldots, a_{k-1})\) are linear independent then the function returns \(m = k\), and vector \(b_i, i < k\) is orthogonal to all vectors \(a_j\) with \(j \neq i\).
The basis \(B = b_0\ldots, b_{23}\) is stored in the array
b.We require \(k \leq 24\). The function returns \(m \geq 0\) in case of success a negative value in case of failure.
- uint32_t leech2_matrix_radical(uint32_t *v2, uint32_t n, uint64_t *basis, uint32_t d)
Radical of subspace generated by vectors of Leech lattice mod 2.
Compute the radical of the subspace of the Leech lattice modulo 2 generated by the vectors
v2[0],...,v2[n-1]. Here the radical is the intersection of the space generated byv2[0],...,v2[n-1]with the orthogonal complement of that space.Input parameters
v2, n,anddare as in functionleech2_matrix_basis. A basis of the radical of the space is computed inbasis. The basis is echelonized as in functionleech2_matrix_basis. The function returns the dimensionkof radical spanned by that basis.
- uint32_t leech2_matrix_expand(uint64_t *basis, uint32_t dim, uint32_t *v2)
List vectors in a subspace of the Leech lattice modulo 2.
The function computes all
2**dimvectors of the subspaceVof the Leech lattice modulo 2 given by the basis
basis[0], ..., basis[dim - 1].These vectors are written into the array
v2. The function
C functions in leech3matrix.c
File
leech3matrix.ccontains functions for computing with matrices corresponding to the part with tag ‘A’ of a vector of the representation of the monster modulo 3. Note that this part has a natural interpretation as a symmetric matrix on the Leech lattice.For these computations we deal with
i0timesi1matricesmfori0 <= 24,i1 <= 48, Such a matrix is stored in an arrayaof integers of typeuint64_tof length 24 * 3. Here the entrym[i,j]is stored ina[3*i + j/16], bits4 * (j % 16),..., 4 * (j % 16) + 3. We callathe matrix mod 3 encoding of the matrixm.Unless otherwise stated, we assume that the lower two bits of such a bit field have arbitrary values, and that the higher two bits of that bit field are zero.
There are functions for loading such a matrix
mfrom a vector in a representation of the monster, for elechonization ofm, for computing the kernel ofmetc.Functions
- uint32_t leech3matrix_echelon(uint64_t *a)
Echelonize a matrix of integers mod 3.
Here
ais a matrix in matrix mod 3 encoding as documented in the header of this file. That matrix is transformed to row echelon form. We echelonize columns 0,…,23 of matrixain that order. The matrix is not converted to reduced echelon form.The function returns the number of rows in the echelonized matrix that are nonzero in columns 0,…,23.
- uint64_t leech3matrix_reduced_echelon(uint64_t *a, uint32_t d)
Convert matrix of integers mod 3 to reduced echelonized form.
Here
ais a matrix in matrix mod 3 encoding as documented in the header of this file. That matrix is converted to reduced row echelon form. We echelonize columns 0,…,47 of matrixain that order. The leading nonzero value in a row is always equal to 1.The function returns the set of columns used for pivoting as a bit field; i.e. bit
iin the returned integer is set if columnihas been used for pivoting.Parameter
dshould usually be0. In cased > 0we make no atttempt to zero an entry(i, j)ifj >= dand the leading coefficient of rowiis in a column with idnex< d.
- int32_t leech3matrix_kernel_image(uint64_t *a)
Intersection of kernel and image of matrix of integers mod 3.
Here
ais a matrix in matrix mod 3 encoding as documented in the header of this file. We consideraas a pair of two matricesAh, Al, withAlin columns 0,…,23, andAhin columns 24,…,47 ofa.We apply a sequence of row operations to the pair
Ah, Al, so that the resulting outputAh, Alhas the properties stated below. We will writeA_imgfor the output matrixAl.The first
len_imgrows of matrixA_imgare linear independent, and the other rows of matrixA_imgare zero; soA_imghas ranklen_img.Define
A_kerto be the submatrix of output matrixAhcontaining the rowslen_imgand above of that matrix. Then the firstlen_kerrows of matrixA_kerare linear independent, and the other rows ofA_kerare zero; soA_kerhas ranklen_ker.The function also computes the intersection of the spaces spanned by the rows of matrices
A_imgandA_ker. The intersection has dimensionlen_isect; and the firstlen_isectrows of the output matricesA_imgandA_kerwill be equal.In case of success the function returns
len_img + 0x100 * len_ker + 0x10000 * len_isect.It returns -1 in case of failure. Such a failure sould be considered as a software bug.
The typical use case for this function is to store an arbitrary matrix in
Al, and the unit matrix inAh. Then the function computes the image of input matrixAlin the firstlen_imgrows ofA_img, and the kernel ofAlin the firstlen_kerrows of matrixA_ker. As stated above, it also computes the intersection of the kernel and the image.
- void leech3matrix_compress(uint64_t *a, uint64_t *v)
compress a matrix in matrix mod 3 encoding
Let
abe an 24 times 48 matrix in matrix mod 3 encoding. We consideraas a pair of two matricesAh, Al, withAlin columns 0,…,23 andAhin columns 24,…,47 ofa.We store matrix
Alin the entriesv[0], ..., v[23], and matrixAhin the entriesv[24], ..., v[47]. Here columnjof a row ofAhorAlis reduced modulo 3 (so it has value 0, 1, or 2) and that value is stored in bits2*j+1and2*jof the corresponding entry ofv.So each of the matrices
AlandAhwill be encoded as the part with tag ‘A’ of a vector in the representation \(\rho_3\) of the monster modulo 3.The overlapping
v == ais legal; any other kind of overlappig betweenvandais illegal.
- void leech3matrix_sub_diag(uint64_t *a, uint64_t diag, uint32_t offset)
Subtract diagonal matrix from matrix in matrix mod 3 encoding.
Let
abe an 24 times 48 matrix in matrix mod 3 encoding.We subtract a diagonal matrix from
a. More precisely, we subtract the integerdiagfrom all entriesa[i, i+offset], fori = 0,...,23.
- uint64_t leech3matrix_rank(uint64_t *a, uint32_t d)
Rank and kernel of a
24 times 24matrix modulo 3.Let
rbe the rank of the24 times 24matrixb = a - d * 1. Here the entries of that matrix are taken modulo 3,dis an integer, and1is the unit matrix. Inputais a 24 times 24 matrix in matrix mod 3 encoding as documented in the header of this file.Let
rbe the rank of matrixbwith entries taken modulo 3. If matrixbhas rank 23 then its kernel is one dimensional. In that case the kernel contains two nonzero vectors+-w, and we definewto be one of these vectors. Otherwise we letwbe the zero vector.The function returns the value
(r << 48) + w, withwthe vector defined above given in Leech lattice mod 3 encoding as described in The C interface of the mmgroup project.Input
ais destroyed.
- uint64_t leech3matrix_vmul(uint64_t v, uint64_t *a)
Multiply vector with a
24 times 24matrix modulo 3.Input
ais a 24 times 24 matrix encoded as the part with tag ‘A’ of a vector in the representation \(\rho_3\) of the monster modulo 3. Inputvis a vector of 24 integers modulo 3 encoded in Leech lattice mod 3 encoding. The function computes the product \(v \cdot a\) of the vector \(v\) and the matrix \(a\) and returns the result in Leech lattice mod 3 encoding.Vector \(v\) has 24 entries. If the upper \(k\) entries of \(v\) are zero then we access the first \(24-k\) rows of matrix \(a\) only. So the buffer referred by
amust have length (24 - k) in this case.
- int32_t leech3matrix_prep_type4(uint64_t *a, uint32_t n, uint64_t *w, uint64_t *seed)
Prepare subspace of Leech lattice mod 3 for finding type-4 vectors.
Let \(a\) be the subspace of the Leech lattice mod 3 spanned by the vectors in the array
aof lengthn. Here each entry of the arrayais encoded in the same way as a row of the part with tag ‘A’ of a vector in the representation \(\rho_3\) of the Monster modulo 3. Usually, such a subspace of the Leech lattice mod 3 is computed by applying functionleech3matrix_echelonto a (suitably modified) part with tag ‘A’ of a vector in the representation \(\rho_3\).The function computes an array of
2*nrandom vectors taken from the space \(a\) and stores these2*nvectors in the arraywin Leech lattice mod 3 encoding. Half of the vectors in arrayware obtained by left multiplying matrix \(a\) with a random upper triangular matrix; and the other half of these vectors is obtained by left multiplication with a random lower triangular matrix. Parameterseedpoints to a random generator for generating random matrices; see modulegen_random.cfor details.Thus the vectors in array
wspan the space \(a\); and we may obtain random vectors in \(a\) by performing random additions and subtractions of the entries ofw. E.g. functionleech3matrix_prep_type4generates random type-4 in the space space \(a\) using that method.The function returns the size
2*nof the arraywin case of success and a negative value in case of failure. Any overlapping between the arraysaandwis allowed. On input,1 <= n <= 12must hold.
- int32_t leech3matrix_rand_type4(uint64_t *w, uint32_t n, uint32_t trials, uint64_t *seed)
Random type-4 vector in subspace of Leech lattice mod 3.
The function tries to find a random type-4 vector in a subspace \(a\) of the Leech lattice mod 3 spanned by the vectors in the array
aof lengthn. Here the entries of the arraywshould be given in Leech lattice mod 3 encoding, as e.g. returned by functionleech3matrix_prep_type4. That function returns more vectors generating the space \(a\) than necessary in order to facilitate the generation of random vectors in \(a\).The function performs up to
trialsrandom additions or subtractions in the space \(a\), until it finds a type-4 vector. If such a type-4 vector has been found then that vector is returned as a vectorvin the Leech lattice mod 2 in Leech lattice encoding. Parameterseedpoints to a random generator for generating the required random data; see modulegen_random.cfor details.If a type-4 vector
vhas been found then the function returns(t << 4) + v. Here0 <= v < 0x1000000is the vector found in the Leech lattice mod 2 in Leech lattice encoding; andtis the number of trials required to findv. In caset > 127we putt = 127.If no type-4 vector has been found after
trialstrials then the function returns 0.The function returns a negative value in case of failure; e.g. if the random generator has failed.
- void leech3_vect_mod3_to_signs(uint64_t *v, uint64_t mult, uint32_t n, uint64_t *signs)
Map vector in rep of the Monster mod 3 to array of signs.
Let
vbe a part of a vector of the 198884-dimensional representation of the monster group modulo 3, which is organized as antimes24matrix of integers mod 3. Herevis the relevant part of a vector encoded as in themmgroup.mm_opextension; see The C interface of the mmgroup project, section Description of the mmgroup.mm extension for details.Let
multbe a vector of 24 integers mod 3 encoded in the Leech lattice mod 3 encoding.The function computes the scalar product of each row of
vwithmultand stores thensigns of these products in the arraysign. Here the signs are stored in natural order and encoded as in functionqstate12_to_signsin moduleqstate12io.c. As usual, the integers 0, 1, and 2 (mod 3) are mapped to 0, ‘+’, and ‘-’, respectively.Output array
signsshould have at least(n + 31) >> 5entries.
C functions in involutions.c
File
involutions.ccontains functions for transforming involutions of the subgroup \(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\)) of the monster.We try to transform such involutions to a standard form via conjugation by elements of the monster group.
Functions
- int32_t xsp2co1_involution_invariants(uint64_t *elem, uint64_t *invar)
Compute invariant spaces for an involution in \(G_{x0}\).
Let \(g\) be the element of the group \(G_{x0}\) stored in the array given by parameter
elem. Let \(\Lambda_2\) be the Leech lattice mod 2, with vectors in \(\Lambda_2\) coded in Leech lattice encoding as usual. Conjugation by \(g\) is a linear operation on \(\Lambda_2\), since the vectors in \(\Lambda_2\) correspond to the elements of the normal subgroup \(Q_{x0}\) of structure \(2^{1+24}\) (modulo the centre of \(G_{x0}\)). Let \(A = A(g)\) be the \(24 \times 24\) bit matrix that performs this operation on \(\Lambda_2\) by right multiplication. Put \(A_1 = A - 1\), and let \(I_1\) be the image of matrix \(A_1\).In this function we require that the image of \(g\) in the factor group \(\mbox{Co}_1\) of \(G_{x0}\) has order 1 or 2; otherwise the function fails. That condition is equivalent to \(A^2 = 1\), and also to \(A_1^2 = 0\). If this is the case then we have:
\((\ker A_1)^\perp = I_1 \subset \ker A_1 = (I_1)^\perp\).
Any element \(v \in \ker A_1\) is invariant under \(g\), and so the corresponding element in \(Q_{x0}\) is invariant up to sign. The elements of \(Q_{x0}\) invariant under \(g\) (modulo the center of \(Q_{x0}\)) form a subspace \((\ker A_1)^+\) of \(\ker A_1\) of codimension \(0\) or \(1\). Let \((I_1)^+\) be the orthogonal complement of \((\ker A_1)^+\). Then \(I_1\) has the same codimension in \((I_1)^+\). The purpose of this function is to compute a basis of the smaller of the two spaces \((I_1)^+\) or \(\ker A_1\).
We compute an output matrix in the array
invarand return the numberkof rows of that matrix in case of success. We use the following column bits of the output matrix.23,…,0: Basis vector \(v_i\) of \(I_1\) or \((I_1)^+\)
55,…,32: Preimage (under \(A_1\)) of basis vector \(v_i\), undefined if \(v_i \notin I_1\)
27: Here a nonzero bit in row 0 indicates an error.
In bits 24,…,26 of the output matrix we return the following linear forms on the space spanned by basis vectors:
Case 1: \(I_1 = (I_1)^+\) or \(I_1 = \ker A_1 \)
Then we return a basis of \(I_1\), and we have \(k = \dim I_1 = \dim (I_1)^+ \in \{0, 8, 12\}\)
Bit 26: 0
Bit 25: type of basis vector (modulo 2)
Bit 24: sign of basis vector in \(I_1\)
Case 2: \(I_1 \neq (I_1)^+\) and \(I_1 \neq \ker A_1 \)
Then we return a basis of \((I_1)^+\), and we have \(k - 1 = \dim (I_1)^+ - 1 = \dim I_1 \in \{0, 8\}\).
Bit 26: 0 if and only if the basis vector is in \(I_1\)
Bit 25: 0
Bit 24: sign of the basis vector if the vector is in \(I_1\), and type of the basis vector (mod 2) otherwise
Parameter
invarmust be an array of length 12. Zero lines are appended to that array so that its length will be 12.The function returns the dimension
kof the computed basis, and a negative value in case of error. The return value ERR_QSTATE12_GX0_BAD_ELEM means that that the image of \(g\) in \(\mbox{Co}_1\) has order greater than \(2\).Bits 26,…,0 of the output matrix are echelonized in a special way. Here the columns are processed in the order:
26, 25, 24, 11, 22, 21, …, 13, 12, 10, 9, …, 1, 0, 23.
One of the advantages of this echelonization is that the vector \(\Omega\) (encoded as 0x800000) will occur in the basis if it is in the subspace, and that there are many even vectors (i.e. vectors orthogonal to \(\Omega\)) in the basis. Also, bits 26, 25, 24 may be nonzero at most in the first two columns of the output matrix.
- int32_t xsp2co1_involution_orthogonal(uint64_t *invar, uint32_t col)
Compute some orthogonal complement for involution invariants.
Let \(g\) be an element of the group \(G_{x0}\) such that the image of \(g\) in \(\mbox{Co}_1\) has order 1 or 2. For that element \(g\), let \(A, A_1\), and \(I_1\) be as in function
xsp2co1_involution_invariants.In this function the input parameter
invarmust be equal to the outputinvarof functionxsp2co1_involution_invariantsapplied to the element \(g\).There is a nondegenerate bilinear form \( \langle \langle .,. \rangle \rangle\) on \(I_1\) given by
\(\langle \langle x,y \rangle \rangle = \langle \pi(x),y \rangle\),
where \(\pi(x)\) is any preimage of \(x\) under \(A_1\), and \(\langle .,. \rangle\) is the scalar product on the Leech lattice modulo 2. The form \(\langle \langle .,. \rangle \rangle \) is also called the Wall parametrization, see [Wal63]. If the image of \(g\) in \(\mbox{Co}_1\) has order at most two then the Wall parametrization is a symmetric bilinear form.
The function computes the orthogonal complement \(v\) of a linear form \(l\) on the Leech lattice modulo 2 under the Wall parametrization. Then \(v\) is a vector in the Leech lattice modulo two. If parameter
colis 0 or 1 then we let \(l\) be the linear form in columncol + 25of matrixinvar.The function returns \(v\) in case of success and a negative value in case of failure.
[Wal63] G. E. Wall. On the conjugacy classes in the unitary, symplectic and orthogonal groups. J. Australian Math. Soc. 3, pp 1–63, 1963.
- int32_t xsp2co1_involution_find_type4(uint64_t *invar, uint32_t guide)
Find type-4 vector in a space computed by
xsp2co1_involution_invariants.Let \(g\) be the element of the group \(G_{x0}\), and for that element \(g\) let \(A, A_1, I_1\), and \((I_1)^+\) be as in function
xsp2co1_involution_invariants.Here input parameter
invarmust be the outputinvarof functionxsp2co1_involution_invariantsapplied to the element \(g\). This function is successful in case \(\dim I_1 = 8\) only.We return a type-4 vector the space \(I_1\). If no such vector exists then we return 0.
Parameter
guideis as in functionxsp2co1_elem_find_type4and should usually be zero.
- int32_t xsp2co1_elem_find_type4(uint64_t *elem, uint32_t guide)
Try to simplify an element in \(G_{x0}\) via conjugation.
Let \(g\) be the element of the group \(G_{x0}\) stored in the array given by parameter
elem. In this function we require that the image of \(g\) in the factor group \(\mbox{Co}_1\) of \(G_{x0}\) has order 1 or 2; otherwise the function fails.Let \(\Lambda_2\) be the Leech lattice mod 2, with vectors in \(\Lambda_2\) coded in Leech lattice encoding as usual. Let \(\Omega\) be the standard frame in \(\Lambda_2\).
Then the function tries to find a vector \(v \in \Lambda_2\) with the following property:
For any \(h \in G_{x0}\) with \(v \cdot h = \Omega\) we have \(h^{-1} g h \in N_{x0}\).
The function returns \(v\) in case of success and a negative value in case of an error. It returns
ERR_QSTATE12_GX0_BAD_ELEMif no suitable vector \(v\) has been found.The function succeeds if the following two conditions hold:
\(g\) is in class 1A, 2A, 2B or 4A of the monster group
\(g^2\) is in subgroup \(Q_{x0}\) of \(G_{x0}\).
In these two cases there is also a power \(\tau^e\) of the triality element \(\tau\) with
\(\tau^{-e} h^{-1} g h \tau^e \in Q_{x0}\).
Caution:
The last statement has been checked for classes 1A, 2A and 2B only!
Parameter
guideshould usually be zero. Ifguideis a type-4 vector in the Leech lattice mod 2 satisfying the assumptions given above then the function returnsv = guide. Ifguideis a type-2 vector in the Leech lattice mod 2 then we try to find a type-4 vectorvsuch that vectorv + guideis of type 2.Usually we try to find a ‘nice’ type-4 vector
v. In caseguide = 0xffffffffwe return the first suitable vectorvfound.In all other cases parameter
guideis ignored. That parameter is also ignored if we cannot (or do not try hard enough) to find a matching vectorv, or if \(g \in Q_{x0}\).
- int32_t xsp2co1_elem_conj_G_x0_to_Q_x0(uint64_t *elem, uint32_t *a, uint32_t baby)
Try to map an element of \(G_{x0}\) to \(Q_{x0}\).
Let \(g\) be the element of the group \(G_{x0}\) stored in the array given by parameter
elem. The function tries to find an element \(h\) in the monster group with \(h^{-1} g h = q \in Q_{x0}\).The function succeeds if the following two conditions hold:
\(g\) is in class 1A, 2A, 2B or 4A of the monster group
\(g^2\) is in subgroup \(Q_{x0}\) of \(G_{x0}\).
The function stores \(h\) in the output array
aas a word of generators of the monster group. Arrayamust be of length 7 . The function returns \(q\) in bits24,...,0of the return value, and number of atoms in the arrayain bits27, 26, 25of the return value The data in the arrayaare padded with zeros.The function returns a negative value in case of failure. It returns
ERR_QSTATE12_GX0_BAD_ELEMif no suitable element \(h\) can be found.Parameter
babyis as in functionxsp2co1_elem_find_type4and should usually be zero.
- int32_t xsp2co1_elem_conjugate_involution(uint64_t *elem, uint32_t *a)
Map an involution in \(G_{x0}\) to a standard form.
Let \(g\) be an involution of the group \(G_{x0}\) stored in the array given by parameter
elem.The function computes an element \(a\) in the monster such that \(h = a^{-1} g a\) is one of the following elements of the subgroup \(Q_{x0}\) of \(G_{x0}\):
If \(g = 1\) then \(h = a = 1\).
If \(g\) is a 2A involution then \(h\) is the involution in \(Q_{x0}\) corresponding to the Golay cocode word with entries \(2,3\) being set.
If \(g\) is a 2B involution then \(h\) is the central involution \(z\) in \(Q_{x0}\).
The element \(a\) is stored in the array
aas a word of generators of the monster group. In case of success the function returns0x100 * I + len(a), wherelen(a)is the length of the arraya. We putI = 0if \(g = 1\). We putI = 1, 2if \(g\) is a 2A or 2B involution, respectively.The function returns
ERR_QSTATE12_GX0_BAD_ELEMif \(g\) is not an involution.The array
amust have length at least \(14\).
C functions in xsp2co1_traces.c
File
xsp2co1_traces.ccontains functions for computing characters of some representations of the subgroup \(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\)) of the monster.Such computations can be very expensive, especially for some classes of involutions, or for elements that map to involutions in the factor group \(\mbox{Co}_1\) of \(G_{x0}\).
This file contains a function
xsp2co1_elem_involution_classfor the classification of elements that map to involutions in \(\mbox{Co}_1\).Function
xsp2co1_traces_fastuses a precomputed table for computing the characters of elements of \(G_{x0}\). That table is addressed by the class information computed by functionxsp2co1_elem_involution_class. The functions in modulemmgroup\tests\test_involutions.make_involution_samples.pyprecompute that table. We simply copy and paste the table from the output of that python function to to this file.The precomputation of the table requires the function
xsp2co1_traces_allin filexsp2co1_elem.c. That function computes the same characters as functionxsp2co1_traces_fastwithout using precomputed tables.Function
xsp2co1_elem_involution_classdoes not use a precomputed table, but the verification of this function requires inspection of the output of the modulemake_involution_samples.pymentioned above.Functions
- int32_t xsp2co1_elem_involution_class(uint64_t *elem)
Compute class information for certain elements of \(G_{x0}\)
Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation. If \(g\) maps to an involution in the factor group \(\mbox{Co}_1\) of \(G_{x0}\) then the function returns a nonzero value indicating some class information about \(g\). Otherwise the function returns 0.The class information in the return value is to interpreted as follows:
bits 7 .. 0: class of element g in the Monster group, e.g 0x21 means class 2A, 0x41 means class 4A, 0x42 means class 4B, etc. bits 11 .. 8: Class of element g in the factor group Co_1 0 means class 1A in Co_1 1 means class 2A in Co_1 2 means class 2B in Co_1 3 means class 2C in Co_1 bit 12: 0 if g and -g are in the same class in the Monster 1 otherwise bit 13: 1 if q g is equal to or powers up to -1 0 otherwiseAll other bits in the return value are set to zero.
Here \(-1\) is the central involution \(x_{-1}\) in \(G_{x0}\), and \(-g = x_{-1} \cdot g\) .
Write \(h(g)\) as an abbreviation for the result of this function applied to an element \(g\) of \(G_{x0}\). Then the following assertions have been checked computationally in files
make_involution_samples.py, ortest_xp2_traces.py, or can easily be checked mathematically.Possible values \(h(g)\) (depending on the class of \(g Q_{x0}\)) in \(\mbox{Co}_1\) are:
class 1A: 0x1011, 0x3022, 0x0022, 0x0021, 0x2041 class 2A: 0x1121, 0x1122, 0x0143, 0x2143, 0x0142, 0x0141, 0x0122 class 2B: 0x0244, 0x2244 class 2C: 0x0322, 0x0341, 0x0344, 0x2382, 0x0343, 0x0342The value \(h(g)\) determines the characters of the representations \(98280_x, 299_x, 24_x, 4096_x\) of \(g\) uniquely, where by construction of \(G_{x0}\) the last two characters are determined up to sign only.
The class of an involution \(g\) is determined uniquely by \(h(g)\).
- int32_t xsp2co1_traces_fast(uint64_t *elem, int32_t *ptrace)
Compute relevant characters of element of \(G_{x0}\).
Let \(g \in G_{x0}\) be stored in the array
elemin G_x0 representation. The function computes the characters of the representations \(\rho_{24}, \rho_{576}, \rho_{4096}, \rho_{98280}\) and stores the result inptrace[0],..., ptrace[3]in that order. Here \(\rho_{576}\) is the tensor square of \(\rho_{24}\).This function returns 0 in case of success and a nonzero value otherwise.
Note that the tensor product \(\rho_{24} \otimes \rho_{4096}\) is well defined, but the factors of that product are defined up to sign only. We normalize the characters corresponding to \(\rho_{24}\) and \(\rho_{4096}\) so that the first nonzero value of these two characters (in the order given above) is positive.
So this function performs the same action as function
xsp2co1_traces_allin filexsp2co1_elem.c, but it is considerably faster, since it uses precomputed tables for som hard cases.
- int32_t xsp2co1_elem_conjugate_involution_Gx0(uint64_t *elem, uint32_t guide, uint32_t *a)
Map an involution in \(G_{x0}\) to a standard form.
Let \(g\) be an involution in the group \(G_{x0}\) stored in the array given by parameter
elemin G_x0 representation.The function computes an element \(a\) in \(G_{x0}\) such that \(h = a^{-1} g a\) is a (fixed) representative of the class of \(g\) in the group \(G_{x0}\).
The element \(a\) is stored in the array
aas a word of generators of the monster group. In case of success the function returns0x100 * iclass + len(a), wherelen(a)is the length of the data in the arraya, andiclassis explained below. The function returns a negative value in case of failure, e.g. if \(g\) has order greater than 2. The arrayamust have length at least \(10\).In the sequel we list the representatives of all classes of involutions in \(G_{x0}\) computed by this function. For any such representative we also list the number
iclassindicating the class of the involution as computed by functionxsp2co1_elem_involution_class.
iclass = 0x1101: the neutral element \(x_1\)
iclass = 0x3022: the central involution \(x_{-1}\)
iclass = 0x0021: the element \(x_{\{2,3\}}\)
iclass = 0x0022: the element \(x_{\Omega}\)
iclass = 0x1121: the element \(y_o\)
iclass = 0x1122: the element \(x_{-1} y_o\)
iclass = 0x0122: the element \(y_o x_{\{8,9\}}\)
iclass = 0x0322: the element \(y_D x_{\{0, 12\}}\)Here in \(x_{\{i,j\}}\) the index \(\{i,j\}\) indicates a Golay cocode word of length 2 given by the entries \(i\) and \(j\). Octad \(o\) is the standard octad \(\{0,1,2,3,4,5,6,7\}\). Dodecad \(D\) is the standard dodecad \(\{0, 4, 8, 13, 14, 15, 17, 18, 19, 21, 22, 23\}\).
Parameter
guideshould usually be zero. Ifguideis a type-4 vector \(v_4\) in the Leech lattice mod 2 such that the two conditions \(h = a^{-1} g a\) and \(v_4 \cdot a = \Omega\) can both be achieved then we compute an element \(a\) satisfying these two conditions. Otherwise parameterguideis ignored. Here \(\Omega\) is the standard frame in the Leech lattice.
- int32_t xsp2co1_map_involution_class_Gx0(uint32_t iclass, uint32_t *a)
Map an involution class in \(G_{x0}\) to its representative.
Here parameter
classmust be a class number of an involution in the group \(G_{x0}\) as returned by functionxsp2co1_elem_conjugate_involution_Gx0.Then the function computes the representative \(h\) of the class of involutions in \(G_{x0}\) as it is computed by function
xsp2co1_elem_conjugate_involution_Gx0.The element \(h\) is stored in the array
aas a word of generators of the monster group. In case of success the function returns the lengthlen(a)of the data in the arraya. The function returns a negative value in case of failure, e.g. ificlassdoes not correspond to an involution. The arrayamust have length at least \(2\).
C functions in xsp2co1_map.c
File
xsp2co1_map.ccontains functions for computing an element \(g\) of the group \(G_{x0} = 2^{1+24}.\mbox{Co}_1\) from the action of \(g\) on the normal subgroup \(Q_{x0} = 2^{1+24}\) of \(G_{x0}\).Here the group \(G_{x0}\) is the maximal subgroup of the Monster used in our construction of the Monster. We store an element of \(G_{x0}\) as word of generators of that group as described in file
mmgroup_generators.h. Internally, we also use the G_x0 representation for elements of \(G_{x0}\) as described in filexsp2co1.c.Elements of the group \(Q_{x0}\) are stored in Leech lattice encoding as described in section Description of the mmgroup.generators extension.
Note that an element of \(G_{x0}\) is determined by its action on \(Q_{x0}\) up to sign only.
The main function
xsp2co1_elem_from_mappingin this module tries to find the ‘nicer’ of the elements \(\pm g\) from its action on \(Q_{x0}\).Functions
- int32_t xsp2co1_Co1_get_mapping(uint32_t *m1, uint32_t *m2, uint32_t *m_out)
Compute a certain mapping from \(Q_{x0}\) to itself.
Let \(g \in G_{x0}\) be such that \(g\) maps \(m_{1,j}\) to \(m_{2,j}\) via conjugation, for \(m_{i,j} \in Q_{x0}\), \(i = 1,2; 0 \leq j \leq 24\). If the \(m_{1,j}\) (considered as vectors in \(\Lambda/2 \Lambda\)) are linear independent then there is at most one such \(g\), up to sign.
Here inputs \(m_{1,j}, m_{2,j}\) are given in the arrays
m1, m2in Leech lattice encoding.The function computes \(g\) as a mapping \(m_{0,j} \mapsto m_{3,j}\), where \(m_{0,j}\) is the standard basis of \(\Lambda/2 \Lambda\) (with \(m_{0,j}\) =
1 << jin Leech lattice encoding). The function stores the vectors \(m_{3,j}\) in the arraym_outof length 24 in Leech lattice encoding.Let \(o\) be the odd part of the order of \(g\), so that \(g\) has order \(2^k \cdot o\).
The function returns a negative value if it detects an error, and it returns \(o\) if it does not detect any error. If the function returns \(o \geq 0\) and the output is a correct image of the standard basis then there exists a \(g \in G_{x0}\) that maps \(m_{1,j}\) to \(m_{2,j}\). The order of any such element \(g\) divided by \(o\) is a power of two.
Any overlapping between the arrays referred by
m1, m2, m_outis allowed.
- int32_t xsp2co1_Co1_matrix_to_word(uint32_t *m, uint32_t *g)
Compute preimage in \(G_{x0}\) of automorphism on \(Q_{x0}\).
Let matrix \(m\) (given by parameter
m) be a 24 times 25 bit matrix that describes an automorphism \(g'\) acting on \(Q_{x0}\). Here rowm[i]is the image of the (positive) element in \(Q_{x0}\) corresponding to thei-th basis vector of \(\Lambda/2\Lambda\), andm[i]is encoded in Leech lattice encoding.If possible, the function computes a \(g \in G_{x0}\) that acts on \(Q_{x0}\) by conjugation in the same way as \(g'\) acts on \(Q_{x0}\). If such a \(g\) exists, it is determined up to sign only.
In case of success the function stores \(g\) as a word of generators of \(G_{x0}\) in the buffer referred by parameter
gand returns the length of that word. In case of failure the function returns a negative value.Array
gmust have length at least 10.
- int32_t xsp2co1_elem_from_mapping(uint32_t *m1, uint32_t *m2, uint32_t *g)
Compute \(g \in G_{x0}\) from its operation on \(Q_{x0}\).
Let \(g \in G_{x0}\) be such that \(g\) maps \(m_{1,j}\) to \(m_{2,j}\) via conjugation, for \(m_{i,j} \in Q_{x0}\), \(i = 1,2; 0 \leq j \leq 24\). If the \(m_{1,j}\) (considered as vectors in \(\Lambda/2 \Lambda\)) are linear independent then there is at most one such \(g\), up to sign.
Here inputs \(m_{1,j}, m_{2,j}\) are given in the arrays
m1, m2in Leech lattice encoding.If possible then the function computes a \(g \in G_{x0}\) that maps \(m_{1,j}\) to \(m_{2,j}\) via conjugation. In case of success it stores \(g\) as a word of generators of \(G_{x0}\) in the buffer referred by parameter
gand returns the length of that word in the lower 8 bits of the return value. In case of failure the function returns a negative value.Array
gmust have length at least 10.Note that \(g\) is determined up to sign only. The function makes a considerable effort to disambiguate the two elements \(\pm g\).
If one of the two element \(\pm g\) has odd order then the other one has necessarily even order; in that case we return the element with odd order. Otherwise both elements have the same (even) order \(2^k \cdot o, o\) odd. Then at most one of the elements \(\pm g^o\) may have a negative character \(\chi(g^o)\) in the representation \(\rho_{24} \otimes \rho_{4096}\) of \(G_{x0}\); and in this case we return an element with \(\chi(g^o) \geq 0\). This leads to a disambiguation of \(\pm g\) in case \(\chi(g^o) \neq 0\).
We store the order of the computed element \(g\) in bits 15…,8 of the return value. We set bit 16 of the return value precisely if we could disambiguate \(g\) from \(-g\), i.e. in case \(\chi(g^o) \neq 0\). (Note that \(g^o = 1\) if \(g\) has odd order, implying \(\chi(g^o) > 0\).)
The function returns a negative value in case of failure.
C functions in xsp2co1_rep_mod3.c
File
xsp2co1__rep_mod3.ccontains function for dealing with the representation \(4096_x \otimes 24_x\) of the group \(G_{x0}\) (of structure \(2^{1+24}.\mbox{Co}_1\)), with entries of the representation taken modulo 3.Here we may store tensors \(q \otimes v_3\) in the space \(4096_x \otimes 24_x\) (mod 3) in a compact form, where \(q \in 4096_x\) can be expressed as a quadratic state vector, and \(v_3\) is an arbitrary vector in the Leech lattice modulo 3.
Functions
- int32_t xsp2co1_rep_mod3_from_qs(qstate12_type *pqs, uint64_t v3, uint64_t *p_rep)
Construct vector of representation from pair
(qs, v3)The function constructs a vector in the representation \(4096_x \otimes 24_x\) from a pair
(qs, v3), whereqsthe a quadratic state referred bypqs, andv3is a vector in the Leech Lattice mod 3 in Leech lattice mod 3 encoding. The function stores the vector in the arrayrepof length 14 referred byp_rep. The stateqsmust have shape (0, 12) or (12, 0).
- void xsp2co1_rep_mod3_unit_vector(uint32_t i, uint64_t v3, uint64_t *p_rep)
Construct vector of representation from pair \((x_g, v_g)\).
The function constructs a vector in the representation \(4096_x \otimes 24_x\) from a pair
(i, v3), whereimeans thei-th unit vector in the representation \(4096_x\) andv3is a vector in the Leech lattice mod 3 in Leech lattice mod 3 encoding. The function stores the vector in the arrayrepof length 14 referred byp_rep.In the standard repesentation \(\rho_3\) of the Monster the unit vector at position (‘Z’, i, j) should be encoded with parameters
i = i,v3 = 1 << j; and the unit vector at position (‘Y’, i, j) should be encoded with parametersi = 2048 + i,v3 = 1 << j; for0 <= i < 2048, and0 <= j < 24.
- int32_t xsp2co1_rep_mod3_mul_elem(uint64_t *p_rep, uint64_t *elem)
Multiply vector of representation with group element.
Let
vbe the vector in the representation \(4096_x \otimes 24_x\) (mod 3) referred byp_rep, as constructed by functionxsp2co1_rep_mod3_from_qs. This function multiplies the vectorvwith the element \(g\) of the group \(G_{x0}\) and replaces the vectorvby that product. Here the group element \(g\) is stored in the array referred byelemin G_x0 representation.This function suceeds only if the factor of the tensor product
vin \(24_x\) is a short vector (i.e. a vector of type 2) in the Leech lattice mod 3.
- int32_t xsp2co1_rep_mod3_mul_word(uint64_t *p_rep, uint32_t *a, uint32_t n)
Multiply vector of representation with word of group elements.
Let
vbe the vector in the representation \(4096_x \otimes 24_x\) (mod 3) referred byp_rep, as constructed by functionxsp2co1_rep_mod3_from_qs. This function multiplies the vectorvwith the element \(g\) of the group \(G_{x0}\) and replaces the vectorvby that product. Here the group element \(g\) given as a word in the generators of the group \(G_{x0}\) of lengthn. That word is stored in the arraya, and each entry ofaencodes a generator of \(G_{x0}\) as described in filemmgroup_generators.h.
- int32_t xsp2co1_rep_mod3_conv_mm_op(uint64_t *p_rep, uint64_t *p_wz)
Store vector of representation in mm_op format.
Let
vbe the vector in the representation \(4096_x \otimes 24_x\) (mod 3) referred byp_rep, as constructed by functionxsp2co1_rep_mod3_from_qs.Let
wbe a vector in the standard repesentation \(\rho_3\) of the Monster in themm_oppackage, and letp_wzbe a pointer to the position of the entry (‘Z’, 0, 0) of vectorp_wz. Then the function stores the vectorvat the parts of vectorwwith tagsZandY. It returns 0 in case of success a negative value in case of failure.This works only if the data type
uint_mmv_tused for storing vectors in \(\rho_3\) is equal touint64_t.
- int32_t xsp2co1_rep_mod3_scalprod_mm_op(uint64_t *p_rep, uint64_t *p_wz)
Scalar product of vector of representation with mm_op vector.
Let
vbe the vector in the representation \(4096_x \otimes 24_x\) (mod 3) referred byp_rep, as constructed by functionxsp2co1_rep_mod3_from_qs.Let
wbe a vector in the standard repesentation \(\rho_3\) of the Monster in themm_oppackage, and letp_wzbe a pointer to the position of the entry (‘Z’, 0, 0) of vectorp_wz. Then the function returns the scalar product of the vectorsvandw. It returns a negative value in case of failure.This works only if the data type
uint_mmv_tused for storing vectors in \(\rho_3\) is equal touint64_t.
- int32_t xsp2co1_rep_mod3_find_nonzero(uint64_t *p_rep)
Find a nonzero entry of a vector.
Let
vbe the vector in the representation \(4096_x \otimes 24_x\) (mod 3) referred byp_rep, as constructed by functionxsp2co1_rep_mod3_from_qs.The function returns index
(i, j)and valuexof a nonzero entry of the vector if present. Here index(i, j)denotes the unit vector at position (‘Z’, i, j) if0 < i < 2048, and the unit vector at position (‘Y’, i - 2048, j) if2048 < i < 4096. A nonzero valuexis always equal to 1 or 2.In case of success the function returns the triple
(i, j, x)in the form:
(0x6 << 25) + (i << 14) + (j << 8) + x,which is compatible with the sparse representation of a vector in \(\rho_3\) in the
mmgroup.mm_oppackage.In case of failure (e.g. if
vis zero) the function returns a negative value.This function is useful for determining the sign of a vector
vthat is already known up to sign.
Description of the mmgroup.mm_op extension
Module mmgroup.mm_op is implemented as an extension
in the mmgroup package implemented in Cython.
The main source file for that extension is mm_op.pyx in
directory src.mmgroup.dev.mm_op. Each documented .c
in this module function has been wrapped by a Cython
function with the same name and the same signature.
Module mmgroup.mm_op implements the 196884-dimensional rational
representation \(\rho_p\) of the monster group modulo several
fixed odd moduli \(p = 2^k-1\).
Representation of a vector in \(\rho_p\)
We describe the representations of a vector in \(\rho_p\)
The most important representation of a vector in \(\rho_p\) is the internal representation. All operations of the monster group are performed on vectors in in \(\rho_p\) in internal representation.
In the internal representation a vector is stored as an array of
247488 entries, where each entry is a bit field representing
an integer modulo p. Some components of a vector are stored
twice in that array and some entries of the array are unused. This
special structure facilitates the implementation of the operations
of the monster group.
The entries of a vector are organized as tuples (tag, i0, i1).
Here indices i0, i1 refer to a two-dimensional array as
indicated in column Size of the following table. As usual in
C, entries with adjacent last index i1 are stored in adjacent
locations. For a mathematical description of an entry
(tag, i0, i1), see section
The Representation of the Monster Group in the API reference.
Array sizes for tags in the internal representation Tag
Size
Space used
Remarks
Offset
A
24 x 24
24 x 32(1), (2)
0
B
24 x 24
24 x 32(1), (2), (3)
768
C
24 x 24
24 x 32(1), (2), (3)
1536
T
759 x 64
759 x 64(4),
2304
X
2048 x 24
2048 x 32(1),
50880
Z
2048 x 24
2048 x 32(1),
116416
Y
2048 x 24
2048 x 32(1),
181952
Remarks
As indicated in column
Space used, an array of sizentimes24is stored in a space reserved for an array of sizentimes32. So the entry with index(tag, i0, i1)is stored at locationOffset(tag) + 32 * i0 + i1. Unused entries must be equal to zero.The entry given by
(tag, i0, i1)must be equal to the entry given by(tag, i1, i0).The diagonal entry given by
(tag, i0, i0)must be equal to zero.The entry with index
(T, i0, i1)is stored at locationOffset(T) + 64 * i0 + i1.
The entries of a vector in internal representation are stored
a one-dimensional array of integers of type uint_mmv_t. Here
type uint_mmv_t may be one of the C integer types
uint64_t or uint32_t, depending on the value INT_BITS.
At present INT_BITS is set to the value 64. Several adjacent
entries of a vector are stored as bit fields in a single integer
of type uint_mmv_t. Entries with a lower index are stored at
bits with lower valence.
The number of bits in a bit field is always a power of two. So e.g.
for p = 3 we use 2 bits; for p = 7 we use 4 bits
with the highest bit unused. In case p = 2**k - 1, legal values
for an entry are 0,...,2**k - 1, with 2**k - 1 equal to
0. Thus negation of a value can be done by complementing all
k bits of that value. Apart from negation, the matrices
corresponding to operations of the monster may add, subtract and
half the entries of a vector (modulo p). These operations can
easily be done on several entries simultaneously by manipulating a
just single integer of type uint_mmv_t.
As indicated above, we reserve 32 entries for arrays of
integers modulo p with 24 entries. So we require about
25.7% more memory than necessary. In some cases we need this
extra memory anyway. E.g. for p = 3 a 64-bit integer may
store 32 entries, so that there will always be a slack of
8 entries when storing 24 entries.
Function mm_aux_mmv_size(p) returns the number of integers
of type uint_mmv_t required for storing a vector in external
representation.
When writing or calculating entries with tags A, B, C then
the high-level function for manipulating vectors in internal
representation make sure that e.g. entries with indices
(A, i0, i1) and (A, i1, i0) are always set to the same
value. These functions also make sure that unused bits in a bit
field and unused bit fields are set to zero. Note that a bit field
with value zero may contain the value p instead.
The external representation of a vector in \(\rho_p\)
There is also a so-called external representation of a vector in R_p. This is used to facilitate the access to vectors by external modules. Here the vector is represented as an array of 196884 integers of type uint8_t. Basis vectors are ordered similar to the ordering for the internal representation, but here the entries are in one-to-one correspondence with the basis vectors. In the external representation there are no unused or duplicated entries.
More precisely, the order of the entries is:
Order of entries in external representation Entries
Condition
No of entries
Offset
(A, i0, i1)
i0 = i1
24
0
(A, i0, i1)
i0 > i1
276
24
(B, i0, i1)
i0 > i1
276
300
(C, i0, i1)
i0 > i1
276
576
(T, i0, i1)
759*64
852
(X, i0, i1)
2048*24
49428
(Z, i0, i1)
2048*24
98580
(Y, i0, i1)
2048*24
147732
Indices (tag, i,j) for tag = A, B, C, i > j are ordered
as follows:
(1,0),
(2,0), (2,1),
(3,0), (3,1), (3,2),
...
(i,0), (i,1), ..., (i,i-1),
...
(24,0), (24,1), ..., (24,23).
Function mm_aux_bytes_to_mmv() converts a vector from external
to internal representation, Function mm_aux_mmv_to_bytes() does
the inverse conversion.
The sparse representation of a vector in \(\rho_p\)
The Python interface to vectors in \(\rho_p\) is optimized for readability and not for speed. Here a typical task is to read and modify single entries of a vector. In the internal representation the coordinates of a vector are indexed by tuples containing a string. Transferring tuples or strings from Python to C is awful. Here we need a representation of a vector in \(\rho_p\) where a single entry of a vector can be stored in an integer variable.
A vector in \(\rho_p\) can be stored in the sparse
representation.
Here a vector is stored as an array of 32-bit integers, where each
entry stands for a multiple of a basis vector. A component of
a vector is stored in the bit fields of an integer as a tuple
(tag, i0, i1, value). Here the tuple (tag, i0, i1) is as
in the external representation, and value is the value of the
coordinate of the vector corresponding to (tag, i0, i1).
Entries with coordinate zero may be dropped. A 32-bit integer
encodes a tuple (tag, i0, i1, value) in bit fields as shown
in the following table.
Bit fields in the sparse representation Bits
Meaning
27..25
Tag:A = 1,B = 2,C = 3,T = 4,X = 5,Z = 6,Y = 724..14
Index
i013.. 8
Index
i17.. 0
The
valueof the coordinate of the basis vector; if the moduluspis2**k - 1then only the lowestkbits are evaluated.
In a C function the length of a sparse representation of a vector
must be given as a parameter to the function.
The order of the entries is irrelevant in the sparse
representation. A sparse representation generated by a C function
contains at most one entry for each tuple (tag, i0, i1).
On input, entries with several equal tuples (tag, i0, i1) are
accepted. Unless stated otherwise, the corresponding values of
such equal tuples are added.
In an entry with tag A, B, or C generated by this module
we always have i0 >= i1. The value of an entry generated by
this module is always less than the modulus p.
When reading an entry, a value with 0 <= value <= p is
accepted. Entries with tag A, B, or C and i < j are
also accepted. Illegal tags or indices are usually ignored on input.
Header file mm_basics.h
The header file mm_basics.h contains basic definitions for dealing with vectors of the 198884-dimensional representation of the monster group, as described in The C interface of the mmgroup project, section Description of the mmgroup.mm extension.
It also contains prototypes for the C files in the mm extension. This extension comprises the files mm_aux.c, mm_crt.c, mm_group_word.c, mm_random.c, mm_tables.c, mm_tables_xi.c.
Defines
-
mm_aux_bad_p(p)
Return 0 if
pis a good modulus and a nonzero value otherwise.
Typedefs
-
typedef uint64_t uint_mmv_t
Used for the representation of the monster group.
Internally, a vector in the 196884-dimensional representation of the monster is stored as an array of integers of type
uint_mmv_t. Here several entries are stored in such an integer. Seeenum MM_AUX_OFS_typefor more details.
Enums
-
enum MM_AUX_OFS
This enumeration contains the offsets for the tags
A,B,C,T,X,Z,Yin a vector in the 196884-dimensional representation of the monster, stored in the internal representation.Such an offset counts the number of entries starting at the beginning of th vector. Note that several entries of a vector are stored in a 64-bit integer. Also there may be duplicate or unused entries in a vector, in order to speed up the operation of the monster group on a vector.
Values:
-
enumerator MM_AUX_OFS_A
Offset for tag A
-
enumerator MM_AUX_OFS_B
Offset for tag B
-
enumerator MM_AUX_OFS_C
Offset for tag C
-
enumerator MM_AUX_OFS_T
Offset for tag T
-
enumerator MM_AUX_OFS_X
Offset for tag X
-
enumerator MM_AUX_OFS_Z
Offset for tag Z
-
enumerator MM_AUX_OFS_Y
Offset for tag Y
-
enumerator MM_AUX_LEN_V
Total length of the internal representation
-
enumerator MM_AUX_OFS_A
-
enum MM_AUX_XOFS
This enumeration contains the offsets for the tags
A,B,C,T,X,Z,Yin a vector in the 196884-dimensional representation of the monster, stored in the external representation.In external representation, a vector is stored as a contiguous array of bytes.
Values:
-
enumerator MM_AUX_XOFS_D
Offset for diagonal entries of tag A
-
enumerator MM_AUX_XOFS_A
Offset for tag A
-
enumerator MM_AUX_XOFS_B
Offset for tag B
-
enumerator MM_AUX_XOFS_C
Offset for tag C
-
enumerator MM_AUX_XOFS_T
Offset for tag T
-
enumerator MM_AUX_XOFS_X
Offset for tag X
-
enumerator MM_AUX_XOFS_Z
Offset for tag Z
-
enumerator MM_AUX_XOFS_Y
Offset for tag Y
-
enumerator MM_AUX_XLEN_V
Total length of the external representation
-
enumerator MM_AUX_XOFS_D
-
enum MM_SPACE_TAG
This enumeration defines the values of the tags
A,B,C,T,X,Z,Yin a vector in the 196884-dimensional representation of the monster, stored in the sparse representation.In the sparse representation an entry of a vector is stored as a tuple of bit fields
(tag, par1, par2, value)inside an integer of typeuint32_tas follows:Bits 27,...,25: tag (as indicated below) Bits 24,...,14: par1 (an integer of up to 11 bits) Bits 13,..., 8: par2 (an integer of up to 6 bits) Bits 7,..., 0: value (Reserved for the value of an entry)
Values:
-
enumerator MM_SPACE_TAG_A
Encodes tag A
-
enumerator MM_SPACE_TAG_B
Encodes tag B
-
enumerator MM_SPACE_TAG_C
Encodes tag C
-
enumerator MM_SPACE_TAG_T
Encodes tag T
-
enumerator MM_SPACE_TAG_X
Encodes tag X
-
enumerator MM_SPACE_TAG_Z
Encodes tag Z
-
enumerator MM_SPACE_TAG_Y
Encodes tag Y
-
enumerator MM_SPACE_TAG_A
-
struct mm_sub_op_pi64_type
- #include “mm_basics.h”
Auxiliary structure for the structure
mm_sub_op_pi_typeAn array of type
mm_sub_op_pi64_type[759]encodes the operation of \(x_\epsilon x_\pi\) on the representation of the monster group for entries with tagT. Assume that entry(T, i, j)is mapped to entry+-(T, i1, j1). Theni1depends onionly, andj1depends oniandj. For fixedithe mappingj -> j1is linear if we consider the binary numbersjandj1as bit vectors.Entry
i1of the array of typemm_sub_op_pi64_type[759]describes the preimage of(T, i1, j1)for all0 <= j1 < 64as documented in the description of the memberspreimageandperm.Note that the values 1, 3, 7, 15, 31, 63 occur as differences
j1 ^ (j1 - 1)when countingj1from 0 up to 63. So the preimage of(T, i1, j1)can be computed from the preimage of(T, i1, j1 - 1)using linearity and the approprate entry in member perm.We remark that in case of an odd value epsilon the mapping for tag
Trequires a postprocessing step that cannot be derived from the infomration in this structure. Then entry(T, i, j)has to be negated if the bit weight of the subset of octadeicorresponding to indexjhas bit weight 2 modulo 4.In the sequel we describe the meaning of entry
i1an an array of elements of typemm_sub_op_pi64_type.
-
struct mm_sub_op_pi_type
- #include “mm_basics.h”
Structure used for preparing an operation \(x_\epsilon x_\pi\).
Function
mm_sub_prep_picomputes some tables required for the operation of \(x_\epsilon x_\pi\) on the representation of the monster group, and stores these tables in a structure of typemm_sub_op_pi_type.The structure of type
mm_sub_op_pi_typehas the following members:Public Members
-
uint32_t eps
A 12-bit integer describing an element \(\epsilon\) of the Golay cocode.
-
uint32_t pi
An integer describing the element \(\pi\) of the Mathieu group \(M_{24}\) as in module
mat24_functions.c.
-
uint8_t perm[24]
The permutation
0...23 -> 0...23given by the element \(\pi\) of \(M_{24}\).
-
uint8_t inv_perm[24]
The inverse of the permutation
perm.
-
uint32_t benes_net[9]
A representation of Benes network for computing permutationperm, as described in function
mat24_perm_to_netin filemat24_functions.c.
-
uint16_t tbl_perm24_big[2048 + 72]
For tags
A, B, C, X, Y, Z, an entry(tag, i, j)of the representation of the monster is mapped to entry(tag1, i1, j1), withi1depending oni(and the tag), andj1depending onjonly.If
tbl_perm24_big[i1] & 0x7ff = ifor0 <= i1 < 2048then(tag, i, j)ia mapped to(Tag, i1, perm[j]), up to sign, for tagsX,YandZ. In case of an odd \(\epsilon\), tagsYandZhave to be exchanged. The valuetbl_perm24_big[2048 + 24*k + i1] & 0x7ffdescribes the preimage of(tag, i1, j1)in a similar way, wheretag = A, B, C, fork = 0, 1, 2.Bits 12,…,15 of
tbl_perm24_big[i1]encode the signs of the preimages of the corresponding entry of the rep. Bits 12, 13, and 14 refer to the signs for the preimages for the tagsX,ZandY, respectively. Bit 15 refers to the signs for the preimages for tagsA,BandC. If the corresponding bit is set, the preimage has to be negated.Note that function
mat24_op_all_autplin modulemat24_functions.c computesthe first 2048 entries of the table.
-
mm_sub_op_pi64_type *tbl_perm64
A description of the operation of \(x_\epsilon x_\pi\) on the entries with tag
T, see structuremm_sub_op_pi64_type. Entrydof the Arrary refers to the octado(d)with numberd. It contains the followint information_Bits 5,…,0: Associator
\delta' = A(o(d), f))encoded as a suboctadBits 11,…,6: Associator
a = A(o(d), ef))encoded as a suboctad.Caution:
Pointer
tbl_perm64must be initialized with an array of typemm_sub_op_pi64_type a_tbl_perm64[759].
-
uint32_t eps
-
struct mm_sub_op_xy_type
- #include “mm_basics.h”
Structure used for preparing an operation \(y_f x_e x_\epsilon\).
The operation of \(g = y_f x_e x_\epsilon\), (or, more precisely, of its inverse \(g^{-1}\)) on the representation of the monster group is described in section Implementing generators of the Monster group in the The mmgroup guide for developers.
Function
mm_sub_prep_xyin filemm_tables.ccollects the data required for this operation in a structure of typemm_sub_op_xy_type.Public Members
-
uint32_t f
A 13-bit integer describing an element \(f\) of the Parker loop.
-
uint32_t e
A 13-bit integer describing an element \(e\) of the Parker loop.
-
uint32_t eps
A 12-bit integer describing an element \(\epsilon\) of the Golay cocode.
-
uint32_t f_i
Bit \(i\) of member
f_iis the scalar product of \(f\) and the singleton cocode word \((i)\).These bits are used for the operation of \(g^{-1}\) on entries with tag
A.
-
uint32_t ef_i
Bit \(i\) of member
ef_iis the scalar product of \(ef\) and the singleton cocode word \((i)\).These bits are used for the operation of \(g^{-1}\) on entries with tags
B, andC.
-
uint32_t lin_i[3]
Put \(g_0 = e\), \(g_1 = g_2 = f\). For
k = 0, 1,2, the bit \(i\) of memberlin_i[k]is the scalar product of \(g_k\) and the singleton cocode word \((i)\).These bits are used for the operation of \(g^{-1}\) on entries with tags
X,Z, andY.
-
uint32_t lin_d[3]
Let
U_k = X, Z, Yfork = 0, 1, 2. If the cocode element \(\epsilon\) is even then we putU'_k = U_k, otherwise we putU'_k = X, Y, Zfork = 0, 1, 2. The operation \(g^{-1}\) maps the vector with tag(U_k, d, i)to(-1)**stimes the vector with tag(U'_k, d ^ lin[d], i). Here**denotes exponentiation and we haves=s(k, d, i)=(lin_i[k] >> i) + (sign_XYZ[d] >> k).If
k = 0and \(\epsilon\) is odd then we have to corrects(k, d, i)by a term<d, i>.
-
uint8_t *sign_XYZ
Pointer
sign_XYZrefers to an array of length 2048. This is used for calculations of signs as described above. Here we use the formula in section Implementing generators of the Monster group of the mmgroup guide for developers, dropping all terms depending oni.
-
uint16_t *s_T
Pointer
s_Trefers to an array of length 759. Entrydof this array refers to the octado(d)with numberd. The bits of entrydare interpreted as follows:Bits 5,…,0: The asscociator
delta' = A(o(d), f)encoded as a suboctad of octado(d)).Bits 13,…,8: The asscociator
alpha = A(o(d), ef)encoded as a suboctad of octado(d)). From his information we can compute the scalar product<ef, \delta>for each suboctaddeltaofo(d)as an intersection of tow suboctads. Here we assume thatdeltais represented as such a suboctad.Bit 14: The sign bit
s(d) = P(d) + P(de) + <d, eps>, whereP(.)is the squaring map in the Parker loop.Bit 15: Parity bit
|eps|of the cocode wordeps.Then \(g^{-1}\) maps the vector with tag
(T, d, delta)to(-1)**s'times the vector with tag(T, d, \delta ^ delta'). Here**denotes exponentiation and we haves'=s'(T, d, delta)=s(d)+<\alpha, \delta>+|delta| * |eps| / 2.Here the product
<\alpha, \delta>must be computed as the bit length of an intersection of two suboctads.
-
uint32_t f
Header file mm_op_p.h
C interface for file mm_index.c
File mm_index.c provides the basic functions for converting an index of a vector of the 196884-dimensional representation of the monster between internal, external, and sparse notation.
Functions
-
uint32_t mm_aux_index_extern_to_sparse(uint32_t i)
Convert an index from external to sparse representation.
The function converts an index
ifor the external representation of a vector to an index for the sparse representation of a vector and returns the converted index. The function returns 0 in casei >= 196884.Indices for the sparse representation are defined as in
enum MM_SPACE_TAGin filemm_basics.h.
-
void mm_aux_array_extern_to_sparse(uint32_t *a, uint32_t len)
Convert index array from external to sparse representation.
The function converts an array
aof indices for the external representation to an array of indices for the sparse representation of a vector. All indices in the arrayaof lengthlenare converted in place, using functionmm_aux_index_extern_to_sparse.
-
int32_t mm_aux_index_sparse_to_extern(uint32_t i)
Convert an index from sparse to external representation.
The function converts an index
ifor the sparse representation of a vector to an index for the external representation of a vector and returns the converted index. The function returns -1 if the inputidenotes an illegal index. The coordinate value encoded in the inputiis ignored.Indices for the sparse representation are defined as in
enum MM_SPACE_TAGin filemm_basics.h.
-
int32_t mm_aux_index_sparse_to_leech(uint32_t i, int32_t *v)
Convert sparse index to a short vector in the Leech lattice.
The function converts an index
ifor the sparse representation of a vector to a vectorvin the Leech lattice. This conversion is successful ifidenotes a legal index for one of the tags tagsB, C, T, X. Then the function computes a short Leech lattice vector (scaled to norm 32) in the arrayv. Outputvis determined up to sign only; that sign is implementation dependent.The function returns 0 in case of a successful conversion and -1 in case of failure.
-
uint32_t mm_aux_index_sparse_to_leech2(uint32_t i)
Convert sparse index to a short vector in the Leech lattice mod 2.
The function converts an index
ifor the sparse representation of a vector to a vectorvin the Leech lattice mod 2. This conversion is successful ifidenotes a legal index for one of the tags tagsB, C, T, X. The function returns a short Leech lattice vector modulo 2, encoded in Leech lattice encoding, as described in section Description of the mmgroup.generators extension.The function returns 0 in case of failure.
-
uint32_t mm_aux_index_leech2_to_sparse(uint32_t v2)
Convert short vector in the Leech lattice mod 2 to sparse rep.
The function converts a value
v2representing a vector in the Leech lattice mod 2 to a sparse index and returns that sparse index. It returns 0 ifv2is not a short Leech lattice vector.
-
uint32_t mm_aux_index_leech2_to_intern_fast(uint32_t v2)
Convert short vector in the Leech lattice mod 2 to internal rep.
The function converts a value
v2representing a vector in the Leech lattice mod 2 to an index in internal representation and returns that index. It returns garbage ifv2is not a short Leech lattice vector.If
vis a vector of typeuint_mmv_t, andv2is not a short Leech lattice vector, then the valuemm_aux_get_mmv(v, mm_aux_index_leech2_to_intern_fast(v2))is invalid, but reading that value does not cause buffer overflow.
-
uint32_t mm_aux_index_intern_to_sparse(uint32_t i)
Convert an index from internal to sparse representation.
The function converts an index
ifor the internal representation of a vector to an index for the sparse representation of a vector and returns the converted index. The function returns 0 in case of a bad index.Indices for the sparse representation are defined as in
enum MM_SPACE_TAGin filemm_basics.h.
-
int32_t mm_aux_index_sparse_to_intern(uint32_t i)
Convert an index from sparse to internal representation.
The function converts an index
ifor the sparse representation of a vector to an index for the internal representation of a vector and returns the converted index. The function returns -1 if the inputidenotes an illegal index. The coordinate value encoded in the inputiis ignored.Indices for the sparse representation are defined as in
enum MM_SPACE_TAGin filemm_basics.h.
-
int32_t mm_aux_index_extern_to_intern(uint32_t i)
Convert an index from external to internal representation.
The function converts an index
ifor the external representation of a vector to an index for the internal representation of a vector and returns the converted index. The function returns -1 in casei >= 196884.
-
uint32_t mm_aux_index_intern_to_leech2(uint32_t i)
Convert an index from internal to Leech 2 representation.
The function converts an index
ifor the internal representation of a vector to a vectorvin the Leech lattice mod 2. This conversion is successful ifidenotes a legal index for one of the tagsB, C, T, X. The function returns a short Leech lattice vector modulo 2, encoded in Leech lattice encoding, as described in section Description of the mmgroup.generators extension.The function returns 0 in case of failure.
-
int32_t mm_aux_index_check_intern(uint32_t i)
Check an index in internal representation.
The function checks an index
iin the internal representation of a vector. Some entries of the vectors are stored at two different locations, e.g entriesA[i,j], B[i,j], C[i,j]fori != j.The function returns the other location of the same entry (as an index in internal representation) if there is any. It returns 0 if that entry is stored at exactly one location, and -1 if index
iis illegal.
C interface for file mm_aux.c
File mm_aux.c provides the basic functions for dealing with the representations of the monster group modulo various small integers p = 2**n-1, 2 <= n <= 8. Here the integer p is called the modulus.
Especially, we deal with vectors in such a representation as described in The C interface of the mmgroup project, section Description of the mmgroup.mm extension.
For such a vector there is an internal representation, an external representation, and also a sparse representation, as described in the documentation mentioned above.
The functions in this file provide access to the internal representation of such a vector. The also support the conversion between the different representations of a vector.
Usually, the order of the parameters of functions in this file is:
1. Modulus p, if present
2. The input value or the input data array
3. Any parameters that do not affect the positions in the output array
4. The output data array
5. Parameters (e.g. lengths, indices) that affect the positions of the
data being modified in the output array
Among others, functions in this file use functions from file mm_index.c for converting indices of vectors to different representations.
A vector modulo p is organized in rows of 32 entries. In many rows only 24 of the 32 bits are used; but in some all 32 bit are used. Details are given in the API reference of the project.
Functions
-
uint8_t mm_aux_get_mmv(uint32_t p, uint_mmv_t *mv, uint32_t i)
Read entry at index from vector in internal representation.
The function returns the entry with index
iof the vectormvwith modulusp. The return value is reduced modulop. Indeximust be given in internal representation. The function returns garbage in case of an illegal index.
-
void mm_aux_put_mmv(uint32_t p, uint8_t value, uint_mmv_t *mv, uint32_t i)
Write entry to a vector at an index in internal representation.
The function sets the entry of the vector
mvwith moduluspat the indexito the given value.0 <= value <= pmust hold.Here the index
imust be given in internal representation. Writing at an illegal index performs no action.
-
void mm_aux_add_mmv(uint32_t p, uint8_t value, uint_mmv_t *mv, uint32_t i)
Add to entry of a vector at an index in internal representation.
The function adds the given value to the entry of the vector
mvwith moduluspat the indexi. Here0 <= value <= pmust hold.The index
imust be given in internal representation. Writing at an illegal index performs no action.
-
void mm_aux_read_mmv32(uint32_t p, uint_mmv_t *mv, uint32_t i, uint8_t *b, uint32_t len)
Read entries from vector in internal representation.
Read entries of vector
mv(stored in internal representation with modulusp) and store these entries in the arrayb. Herelenis the number of rows to be read starting at rowi. Each row consists of 32 entries.Here
pmust be a legal modulus.
-
void mm_aux_write_mmv32(uint32_t p, uint8_t *b, uint_mmv_t *mv, uint32_t i, uint32_t len)
Write data to a vector in internal representation.
Write data from the array
bto the vectormv(stored in internal representation with modulusp). Herelenis the number of rows to be read starting at rowi. Each row consists of 32 entries.Here
pmust be a legal modulus.
-
void mm_aux_read_mmv24(uint32_t p, uint_mmv_t *mv, uint32_t i, uint8_t *b, uint32_t len)
Read rows of length 24 from vector in internal representation.
Read entries of vector
mvwith moduluspand store these entries in the arrayb, , starting at rowi. Heremvis a vector of rows of 24 entries, with 8 entries slack after each row.lenis the number of such rows to be read. So altogether 24 *lenentries are read frommvand written to arrayb; the 8 bytes slack after each 24-byte row are dropped. Vectorbis reduced modulop.Here
pmust be a legal modulus.
-
void mm_aux_write_mmv24(uint32_t p, uint8_t *b, uint_mmv_t *mv, uint32_t i, uint32_t len)
Write rows of length 24 to vector in internal representation.
Write data from the array
bto the vectormvwith modulusp. We take24 * lenbytes from the arrayband write them to the vectormv, starting at rowi. Heremvis considered as a vector of rows of 24 entries, with 8 entries slack after each row; solenis the number of such 24-byte rows to be written. The entries in the slack after each row written tomvare set to zero.Here
pmust be a legal modulus.
-
uint32_t mm_aux_mmv_size(uint32_t p)
Return the size of a vector in internal representation.
The function returns the number of integers of type
uint_mmv_trequired to store a vector of the representation \(\rho_p\) (in internal representation) with modulusp.The function returns 0 if
pis illegal modulus.
-
uint32_t mm_aux_int_fields(uint32_t p)
Return number of entries stored in integer of type
uint_mmv_tThe function returns the number of entries of a vector of the representation \(\rho_p\) (in internal representation) that can be stored in an integer of type
uint_mmv_t.The function returns 0 if
pis illegal modulus.
-
uint32_t mm_aux_v24_ints(uint32_t p)
Return number of integers of type
uint_mmv_tto store 24 entries.The function returns the number of integers of type
uint_mmv_trequired to store a part of 24 entries of a vector of the representation \(\rho_p\) (in internal representation) with modulusp. Such parts of 24 entries arise naturally in the construction of \(\rho_p\).The function returns 0 if
pis illegal modulus.
-
void mm_aux_zero_mmv(uint32_t p, uint_mmv_t *mv)
Zero a vector in internal representation.
The function sets all entries of the vector
mvwith moduluspin internal representation to zero.
-
void mm_aux_random_mmv(uint32_t p, uint_mmv_t *mv, uint64_t *seed)
Randomize a vector in internal representation.
The function randomizes all entries of the vector
mvwith moduluspin internal representation uniformly using the internal random generator in filegen_random.c. Parameterseedmust be a seed for a random generator as described in filegen_random.c.
-
int32_t mm_aux_reduce_mmv(uint32_t p, uint_mmv_t *mv)
Reduce a vector in internal representation.
The function reduces all entries of the vector
mvwith moduluspin internal representation to a standard form, so that equal vectors are represented by equal arrays of integers.Note that a zero entry in such a vector can be represented either by the bit string
0...0or by1...1. This functions sets all zero entries of the vector to0...0.The function returns 0 if it detects no error. It may return the following error codes:
-1: Bad modulus
p-2: A one bit outside a valid bit field for an entry has been found
-
int32_t mm_aux_reduce_mmv_fields(uint32_t p, uint_mmv_t *mv, uint32_t nfields)
Auxiliary function of function
mm_aux_reduce_mmvThe function performs the same operation as function
mm_aux_reduce_mmv. But instead of all entries of the vectormv, it reduces the firstlenentries only.
-
int32_t mm_aux_check_mmv(uint32_t p, uint_mmv_t *mv)
Check a vector in internal representation for errors.
The function checks all entries of the vector
mvwith moduluspin internal representation for errors. It returns 0 if it detects no error. It may return the following error codes:-1: Bad modulus
p-2: A one bit outside a valid bit field for an entry has been found
-3: A subfield of 24 entries has an illegal nonzero entry at index >= 24
-4: The vector has an illegal nonzero diagonal entry
-5: The symmetric part of the vector is not actually symmetric
As a side effect,
mvis reduced with functionmm_aux_reduce_mmv.
-
int32_t mm_aux_index_mmv(uint32_t p, uint_mmv_t *mv, uint16_t *a, uint32_t l)
Index a vector in internal representation.
The function computes an array
aof all indicesisuch that entrymv[i]of the vectormvwith moduluspin internal representation contains a nonzero component of the vector.Array
ais computed in the buffer of lengthlreferred by parametera. Arrayawill contain a sorted list of the relevant indices terminated by an entry0xffff.The function returns the length of the computed index array
aor a negative value in case of error. The required lengthlof index arrayais at mostmm_aux_mmv_size(p) + 1.
-
void mm_aux_small24_expand(uint8_t *b_src, uint8_t *b_dest)
Convert part of vector from external to internal representation.
Conversion between the internal and the external representation of a vector is straightforward, except for entries with tags
A, B, C. The entries with these tags are stored in the first 852 entries of the external representation. In the internal representation the entries with these tags are spread over three symmetric 24 times 24 times matrices.This function maps the 852 entries of the array
b_src(corresponding to tagsA, B, C) to the arrayb_destof size 3 * 24 * 24 (corresponding to three symmetric 24 times 24 times matrices). Functionmm_aux_write_mmv24can be used to write the data from the arrayb_destto the initial segment of the internal representation of a vector.
-
void mm_aux_small24_compress(uint8_t *b_src, uint8_t *b_dest)
Convert part of vector from internal to external representation.
Conversion between the internal and the external representation of a vector is straightforward, except for entries with tags
A, B, C. The entries with these tags are stored in the first 852 entries of the external representation. In the internal representation the entries with these tags are spread over three symmetric 24 times 24 times matrices.This function maps the 3 * 24 * 24 entries of the array
b_src(corresponding to three symmetric 24 times 24 times matrices) to the 852 entries of the arrayb_dest(corresponding to tagsA, B, Cin external representation).This reverses the effect of function
mm_aux_small24_expand. Functionmm_aux_read_mmv24can be used to read the data from the initial segment of the internal representation of a vector to the arrayb_src, before calling this function.
-
void mm_aux_mmv_to_bytes(uint32_t p, uint_mmv_t *mv, uint8_t *b)
Convert vector from internal to external representation.
Read all entries of vector
mv(stored in internal representation with modulusp) and store these entries in the arraybin external representation.Output vector
bis reduced modulop. It must have length 196884.
-
void mm_aux_bytes_to_mmv(uint32_t p, uint8_t *b, uint_mmv_t *mv)
Convert vector from external to internal representation.
Read all entries of the array
b(of length 196884, containing a vector in external representation) and store these entries the vectormv. Heremvis a vector stored in internal representation with modulusp.Any entry
xin the arraybmust satisfy0 <= x <= p. The vectormvis an array ofnintegers of typeuint_mmv_twithn = mm_aux_mmv_size(p).
-
int32_t mm_aux_mmv_to_sparse(uint32_t p, uint_mmv_t *mv, uint32_t *sp)
Convert vector from internal to sparse representation.
Read all entries of vector
mv(stored in internal representation with modulusp) and store these entries in the arrayspin sparse representation. Each entry in the arraysprepresents a nonzero entry of the vector. The function returns the length of the output arrayspor an negative value in case of error. Negative return values are as in functioncheck_mmv_buffer.Output vector
spis reduced modulop. The buffer for arrayspmust have length 196884. Input vectormvis checked with functioncheck_mmv_buffer.
-
void mm_aux_mmv_extract_sparse(uint32_t p, uint_mmv_t *mv, uint32_t *sp, uint32_t length)
Extract entries from a vector in internal representation.
The function extracts certain entries from the vector
mvdepending on the vectorsp. Heremvis a vector stored in internal representation with modulusp. Vectorspis a vector of lengthlengthin sparse representation.The entries of vector
spare updated with the corresponding entries ofmv. Ifsphas an entry with a certain label then the coordinate of that entry is set to the corresponding coordinate of vectormv. If several entries ofsphave the same label then the same coordinate is taken frommvseveral times.Entries of vector
spwith tag 0 are not changed.Bit 7,…,0 of any entry of
spshould be either 0 or p. If that value is 0 then the coordinate is read to bits 7,…,0 of that entry. If that entry ispthen the negative coordinate is read instead. Other values of these bits are strongly discouraged; but technically we XOR the corresponding coordinate of vectormvto these bits; and we then change a resultpto zero. There is a special case where this detail is relevant.
-
uint32_t mm_aux_mmv_get_sparse(uint32_t p, uint_mmv_t *mv, uint32_t sp)
Extract one entry of a vector in internal representation.
The statement
uint32_t sp1 = mm_aux_mmv_get_sparse(p, mv, sp);is equivalent touint32_t sp1 = sp; mm_aux_mmv_extract_sparse(p, mv, &sp1, 1);
-
void mm_aux_mmv_add_sparse(uint32_t p, uint32_t *sp, uint32_t length, uint_mmv_t *mv)
Add vector in sparse rep to vector in internal representation.
The function adds a vector
spin sparse representation to a vectormvin internal representation with modulusp. Vectorsphas lengthlength, and each valuexin an entry of vectorspmust satisfy0 <= x <= p. Different entries inspwith the same index are added up.
-
void mm_aux_mmv_set_sparse(uint32_t p, uint_mmv_t *mv, uint32_t *sp, uint32_t length)
Set certain entries of a vector in internal representation.
The function sets certain entries of the vector
mvdepending on the vectorsp. Vectormvis given in internal representation with modulusp. Vectorspis given in sparse representation and has lengthlength.If
sphas an entry with a certain label then the corresponding entry ofmvis set to to the value coded in that entry ofsp. Each of these valuesxmust satisfy0 <= x <= p. Duplicate entries inspwith the same label and different values are illegal; in that case the value ofmvis undefined.
-
int32_t mm_aux_mmv_extract_sparse_signs(uint32_t p, uint_mmv_t *mv, uint32_t *sp, uint32_t n)
Extract signs of a vector in internal representation.
The function extracts the signs of certain entries of the vector
mvdepending on the vectorsp. Vectormvis given in internal representation with modulusp. Vectorspis given in sparse representation and has lengthn.Entry
sp[i]specifies a multiplec[i] * u[i]of a unit vectoru[i]. Letm[i]be the coordinate of vectormvwith respect to the unit vectoru[i]. We puts[i] = 0ifm[i] = c[i]ands[i] = 1ifm[i] = -c[i]. In all other cases we assign a random value 0 or 1 tos[i]. Then the function returns the sum of the valuess[i] << i, whereiranges from0ton - 1.
-
int32_t mm_aux_leech2_op_word_sparse(uint32_t *q, uint32_t m, uint32_t *g, uint32_t n, uint32_t *qg)
Perform operation \(G_{x0}\) of on elements of \(Q_{x0}\).
This is a variant of function
gen_leech2_op_word_manyin filegen_leech.c.Let
qbe an array ofmelements \(q_j\) of the group \(Q_{x0}\) in Leech lattice encoding. Let \(g\) be an element of the group \(G_{x0}\) encoded in the arraygof lengthnas in functiongen_leech2_op_word.The function computes the elements \(q'_j = g^{-1} q_j g\) for \(0 \leq j < m\) and stores \(q'_j\) in
qg[j]. The data in arrayqgare stored in sparse representation. Here the idea is that the data in arrayqgcan be passed directly to functions likemm_aux_mmv_extract_sparse_signs. Arrayqis not changed.The value of an entry in array
qg(which is always 1 or -1) is encoded as 0x01 for 1, and 0xfe for -1, in the lower 8 bits of the entry. This in compatible to encoding a number modulo \(2^k-1, k \leq 8\) in one’s complement, and also to functionmm_aux_mmv_extract_sparse_signs.The function returns a negative value in case of failure, e.g. if any entry in array
qis not of type 2, or if any generator of in the arraygis not in \(G_{x0}\).
-
int32_t mm_aux_mmv_extract_x_signs(uint32_t p, uint_mmv_t *mv, uint64_t *elem, uint32_t *a, uint32_t n)
Extract some bits of a vector in internal representation.
This function is deprecated and will be removed in future versions!
The function extracts the least significant bits of certain entries of the vector
mvdepending on the vectora. Vectormvis given in internal representation of the Monster with modulusp.Vector
ais a an array ofnelements of the groupQ_x0of structure \(2^{1+24}\), with each element given in Leech lattice encoding. Here each element ofQ_x0must correspond to a Leech lattice vector of type 2; otherwise the function fails.The array
elemrepresents an element of the groupG_x0of structure \(2^{1+24}.\mbox{Co}_1\), given in G_x0 representation. Internally, the function transforms (i.e. conjugates) all elements ofQ_x0in the arrayawith the elementelem, i.e. it calculates the elementa'[i] = elem^-1 * a[i] * elemofQ_x0. Then it extracts the least significant bitb[i]of the entry of the vectormvwith the coordinate labelled bya'[i].Note that negating
a'[i]corresponds to negating the coordinate with labela'[i]in the vectormv. Hence when negatinga'[i]we also have to flip the bitb[i]. The function fails in casea'[i] = 0.The function returns the sum of the values
b[i] << i, whereiranges from0ton - 1. The function also fails in casei > 31. It returns a negative value in case of failure.Assume that a vector
mv' = mv * q * gis given with a known vectormv, a knownginG_x0, and an unknownqinQ_x0. Then the main use case of this function is to find the elementq(up to sign) without modifyingmv'.
-
int32_t mm_aux_mul_sparse(uint32_t p, uint32_t *sp, uint32_t length, int64_t f, uint32_t p1, uint32_t *sp1)
Scalar multiplication and modular reduction in sparse representation.
The function multiplies a vector
spin sparse representation with a factorfand reduces the result modulo a numberp1.The vector
sphas lengthlengthand is stored in sparse representation as a vector modulo an odd number2 < p < 256. The result is reduced modulo the numberp1and stored in sparse representation in the arraysp1.The number
p1must be odd and satisfy2 < p < 256. In casef != 0the numberp1must dividep * abs(f).The function returns the length of the array
sp1in case of success and-1in case of failure.The two arrays
spandsp1may be non overlapping or equal.
-
int32_t mm_aux_get_mmv_leech2(uint32_t p, uint_mmv_t *mv, uint32_t v2)
Read entry from vector in internal rep indexed by Leech lattice.
The function returns the entry with index
iof the vectormvwith modulusp. Hereimust be an index referring to a vector of type 2 in the Leech lattice modulo 2 in Leech lattice encoding. The sign bit 24 ofiis evaluated as expected. The return value is reduced modulop.The function returns a negative value if
iis not a vector of type 2 in the Leech lattice modulo 2 orpis not a legal modulus.
-
uint64_t mm_aux_hash(uint32_t p, uint_mmv_t *mv, uint32_t skip)
Compute hash value of vector in internal.
The function returns a hash value of the vector
mvwith modulusp.Parameter
skipshould usually be zero. If bitiof parameterskipis set, then entries with thei-th tag in the string'ABCTXZY'are ignored. So in caseskip == 4the tag'C'is ignored.
C interface for file mm_tables.c
File mm_tables.c contains functions for supporting the operations \(x_\epsilon x_\pi\) and \(y_f x_e x_\epsilon\) on the vectors of the 198884-dimesional represention \(\rho_p\) modulo a small number \(p\). These operations are implemented in separate packages for the differnet values of \(p\). But there are commom preprocessing steps required for all values \(p\). These common preprocessing steps are implemented here.
The monomial operations \(x_\epsilon, x_\pi, y_f, x_e\) are as defined in the API Reference, section The monster group. Here \(\epsilon\) is an element of the Golay cocode represented as a 12-bit integer. \(f\) and \(e\) are elements of the Parker loop represented as 13-bit integers. \(\pi\) is a automorphism of the Parker loop. In the API Reference, section Automorphisms of the Parker loop we number a certain set of these automorphisms in the same way as the elements of the Mathieu group \(M_{24}\). We denote such an automorphism \(\pi\) by its number.
Apart from that, this file contains a small table for supporting the Griess algebra multiplication of a vector in represention \(\rho_p\) by the standard axis \(v^+\).
Functions
-
void mm_sub_prep_pi(uint32_t eps, uint32_t pi, mm_sub_op_pi_type *p_op)
Compute information for operation \(x_\epsilon x_\pi\).
Given an element \(x_\epsilon x_\pi\) of the monster by parameters
epsandpi, the function computes the relevant data for performing that operation on the representation of the monster. These data are stored in the structure of typemm_sub_op_pi_typereferred by parameterp_op.Caution:
Component
p_op->tbl_perm64must be initialized with an array of typemm_sub_op_pi64_type a_tbl_perm64[759]befor aclling this function!!!.
-
int32_t mm_sub_test_prep_pi_64(uint32_t eps, uint32_t pi, uint32_t *p_tbl)
For internal use only!
This is an auxiliary function for testing function
mm_sub_prep_pi.Given
epsandpias in functionmm_sub_prep_pi, this function executes functionmm_sub_prep_p(eps, pi, p_op)and stores the outputp_op->tbl_perm64(as an array of length 759 * (1 + 6)) in the array referred byp_tbl.
-
void mm_sub_prep_xy(uint32_t f, uint32_t e, uint32_t eps, mm_sub_op_xy_type *p_op)
Compute information for operation \(y_f x_e x_\epsilon\).
Given an element \(y_f x_e x_\epsilon\) of the monster by parameters
f,e, andeps, the function computes the relevant data for performing that operation on the representation of the monster. These data are stored in the structure of typemm_sub_op_xy_typereferred by parameterp_op.Caution!
Component
p_op->sign_XYZmust either be NULL or refer to an array of typeuint8_tof length 2048. Componentp_op->s_Tmust either be NULL or refer to an array of typeuint8_tof length 759.
C interface for file mm_op_p_vector.c
File mm_op_p_vector.c implements the operation of the Monster group on a vector in the representation \(\rho_p\) of the Monster modulo \(p\).
The representation \(\rho_p\) is equal to the 196884-dimensional representation \(\rho\) of the monster, with coefficients taken modulo \(p\), as defined in section The representation of the monster group in the API reference.
Unless otherwise stated, the first parameter of a function in this module is the modulus \(p\), and that modulus must be one of the values 3, 7, 15, 31, 127, or 255.
An element of \(\rho_p\) is implemented as an array of integers of type uint_mmv_t as described in section Description of the mmgroup.mm extension in this document.
The number of entries of a vector of type uint_mmv_t[] for modulus \(p\) is equal to mm_aux_mmv_size(p).
Functions
-
int32_t mm_op_copy(uint32_t p, uint_mmv_t *mv1, uint_mmv_t *mv2)
Copy vector
mv1in \(\rho_p\) tomv2Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_compare_len(uint32_t p, uint_mmv_t *mv1, uint_mmv_t *mv2, uint32_t len)
Compare arrays
mv1andmv2of integers.The function compares parts of the two vectors
mv1andmv2of the representation \(\rho_p\).Here the function compares
lenintegers of typeuint_mmv_tstarting at the pointersmv1andmv2. These integers are interpreted as arrays of bit fields containing integers modulo p.The function returns 0 in case of equality and 1 otherwise.
Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_compare(uint32_t p, uint_mmv_t *mv1, uint_mmv_t *mv2)
Compare vectors
mv1andmv2of \(\rho_p\).The function compares two vectors
mv1andmv2of the representation \(\rho_p\).It returns 0 in case of equality and 1 otherwise.
Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_compare_abs(uint32_t p, uint_mmv_t *mv1, uint_mmv_t *mv2)
Compare vectors
mv1andmv2of \(\rho_p\).The function compares two vectors
mv1andmv2of the representation \(\rho_p\).It returns 0 if these vectors are equal up to sign and 1 otherwise.
Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_checkzero(uint32_t p, uint_mmv_t *mv)
Check if a vector
mvin \(\rho_p\) is zero.The function checks it the vector
mvin the representation \(\rho_p\) is zero.It returns 0 in case
mv == 0and 1 otherwise. It is optimized for the case thatmvis expected to be zero.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_vector_add(uint32_t p, uint_mmv_t *mv1, uint_mmv_t *mv2)
Add vectors
mv1andmv2of \(\rho_p\).The function adds the two vectors
mv1andmv2of the representation \(\rho_p\) and stores the result in the vectormv1.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_scalar_mul(uint32_t p, int32_t factor, uint_mmv_t *mv1)
Multiply vector
mv1of \(\rho_p\) with scalar.The function multiplies the vector
mv1of the representation \(\rho_p\) and with the (signed) integerfactorand stores the result in the vectormv1.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_compare_mod_q(uint32_t p, uint_mmv_t *mv1, uint_mmv_t *mv2, uint32_t q)
Compare two vectors of \(\rho_p\) modulo \(q\).
The function compares two vectors
mv1andmv2of the representation \(\rho_p\) modulo a number \(q\). Here \(q\) should divide \(p\).It returns 0 in case of equality, 1 in case of inequality, and 2 if \(q\) does not divide \(p\).
Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_store_axis(uint32_t p, uint32_t x, uint_mmv_t *mv)
Set a vector in \(\rho_p\) to an axis.
Let
xbe an element of the subgroup \(Q_{x0}\) if the Monster that maps to a short Leech lattice vector. Herexmust be given in Leech lattice encoding as in the Description of the mmgroup.generators extension in the documentation of the C interface.Then
xcorresponds to vector in \(\rho_p\) that is called a 2A axis. The function stores that 2A axis inmv.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_pi(uint32_t p, uint_mmv_t *v_in, uint32_t delta, uint32_t pi, uint_mmv_t *v_out)
Compute automophism of the Parker loop on a vector.
File
mm_op_pi.cimplements the operation of the generators \(x_\pi\) and \(x_\delta\) of the monster group on a vector in the representation \(\rho_p\) of the Monster modulop. Herepmust be 3, 7, 15, 31, 127, or 255.Here generators \(x_\pi\) and \(x_\delta\) are defined as automorphisms of the Parker loop as in section The monster group of the API reference. An automophism of the Parker loop is specified by a pair of integers
d, pias in the constructor of the Python classAutPL, see section Automophisms of the Parker loop in the API reference.The exact operation of an automorphism of the Parker loop on \(\rho\) is as defined in [Seysen19].
Note that the integers
d, pimentioned above describe the number of an element of the Golay cocode and the number of a permutation in the Mathieu group \(M_{24}\), respectively. Internally, we use the C functions in filemat24_functions.cand the functionmm_sub_prep_piin filemm_tables.cfor converting the integersd, pito mathematical objects that can be used for implementing the operation on \(\rho_p\). These conversions are very fast compared to the cost for the operation on \(\rho_p\). This helps us to keep the C interface for these operations simple.Let
v_inbe a vector of the representation \(\rho_p\) of the monster group. Then the function computes this automorphism on the input vectorv_inand stores the result in the output vectorv_out.Input vectorv_inis not changed.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_xy(uint32_t p, uint_mmv_t *v_in, uint32_t f, uint32_t e, uint32_t eps, uint_mmv_t *v_out)
Compute an operation of the monster group on a vector.
Let
v_inbe a vector of the representation \(\rho_p\) of the monster group.The function implements the operation of the element \(y_f \cdot x_e \cdot x_\epsilon\) of the monster group on a vector
v_inin the representation \(\rho_p\) of the monster.The integers
fandeoccuring in the generators \(y_f\) and \(x_e\) encode elements of the Parker loop. The integerepsencodes the element \(\epsilon\) of the Golay cocode occuring in the generator \(x_\epsilon\), as indicated in the header of this file. The function computes this operation of the element of the monster (given by parametersf, e, eps) on the input vectorv_inand stores the result in the output vectorv_out.Input vector
v_inis not changed.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_omega(uint32_t p, uint_mmv_t *v, uint32_t d)
Compute an operation of the monster group on a vector.
Let
vbe a vector of the representation \(\rho_p\) of the monster group.The function implements the operation of the element \(x_d\) of the monster group on a vector
vin the representation \(\rho_p\) of the monster. Heredmust be one of the integers0, 0x800, 0x1000, or0x1800, encoding the generators \(x_1, x_\Omega, x_{-1}\), or \(x_{-\Omega}\), respectively.The function computes the operation \(x_d\) on the vector
vand overwrites the vectorvwith the result. The function can be considered as a simplified (and much faster) version of functionmm_op_xy.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_t_A(uint32_t p, uint_mmv_t *v_in, uint32_t e, uint_mmv_t *v_out)
Compute part A of operation of \(\tau^e\) on vector.
Function
mm_op_t_Acomputes a the operation of the monster group element \(\tau^e\) on a vectorv_inand stores the A part of the result in a vectorv_out. That operation depends on a parametere. The other entries of vectorv_outare not changed. See section The representation of the monster group in the API reference for tags of entries of a vector in the representation of the monster. Note that the entries of vectorv_outwith tagAalso depend on entries of vectorv_inwith tags different fromA.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_word(uint32_t p, uint_mmv_t *v, uint32_t *g, int32_t len_g, int32_t e, uint_mmv_t *work)
Compute operation of the monster group on a vector.
Let \(v\) be a vector of the representation \(\rho_p\) of the monster group stored in the array referred by
v.Let \(g\) be the element of the monster group stored in the array of length
len_greferred by the pointerg.Then the function computes the vector \(v \cdot g^e\) and overwrites the vector in the array
vwith that vector. Here \(e\) is the exponent given by the integere.The function requires a work buffer (referrd by
work), which is an array ofmm_aux_mmv_size(p)entries of typeuint_mmv_t. So the work buffer has the same size as the vectorv.The function returns 0 in case of success and a nonzero value in case of failure.
Internally, the function simplifies all substrings of the string representing the word \(g^e\), except for atoms corresponding to nonzero powers of the generator \(\xi\). So the user need not ‘optimize’ the input \(g\). Of course, this simplification does not change the input array
g.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_word_tag_A(uint32_t p, uint_mmv_t *v, uint32_t *g, int32_t len_g, int32_t e)
Restriction of function
mm_op_wordto tagAFunction
mm_op_wordcomputes the operation of an element \(h = g^e\) of the monster group a vectorvand overwritesvwith the result of that operation. \(h\) depends on parametersg, len_g,andeof this function.Function
mm_op_word_tag_Acomputes the same automorphism on the entries of the vectorvwith tagAonly, and ignores the other entries ofv. See section The representation of the monster group in the API reference for tags of entries of a vector in the representation of the monster.The function overwrites the vector
vwith the result. Here only entries ofvwith tagAare changed.Parameters and return value are the same as in function
mm_op_word, except that a work buffer is not required here. Also, the function fails and returns a nonzero value, if the word that makes up the group element \(h\) contains any nonzero powers of the generator \(\tau\) of the monster group. Note that such a power of \(\tau\) does not fix the the part of the vectorvwith tagA. Powers of the generator \(\tau\) correspond to atoms with tagt.This function is much faster than function
mm_op_word. Arrayvmust have24 * mm_aux_v24_ints(p)entries of typeuint_mmv_t.Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_word_ABC(uint32_t p, uint_mmv_t *v, uint32_t *g, int32_t len_g, uint_mmv_t *v_out)
Compute ABC part of the operation of the monster group on a vector.
Let \(v\) be a vector of the representation \(\rho_p\) of the monster group stored in the array referred by
v.Let \(g\) be the element of the monster group stored in the array of length
len_greferred by the pointerg. Here \(g\), and also all prefixes of the word representing \(g\), must be in the set \(G_{x0} \cdot N_0\).The function computes the parts with tags
A,B, andCof the vector \(v \cdot g\) and stores the result in the arrayv_out. The other parts of the vector \(v \cdot g\) are not computed. Here the arrayv_outmust have72 * mm_aux_v24_ints(p)entries of typeuint_mmv_t.This function is much faster than function
mm_op_word. It is mainly used for dealing with a 2A axis \(v\).Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_scalprod(uint32_t p, uint_mmv_t *v1, uint_mmv_t *v2)
Compute the scalar product of two vectors.
Let \(v_1, v_2\) be vectors of the representation \(\rho_p\) of the monster group stored in the array referred by
v1, v2.The function returns the scalar product \((v_1, v_2)\) (reduced modulo \(p\)) in case of success and a negative value in case of failure.
Here modulus
pmust be one of the values 3, 7, 15, 31, 127, or 255.
-
int32_t mm_op_scalprod_ind(uint32_t p, uint_mmv_t *v1, uint_mmv_t *v2, uint16_t *ind)
Compute the scalar product of two vectors.
Let \(v_1, v_2\) be vectors of the representation \(\rho_p\) of the monster group stored in the array referred by
v1, v2.The function returns the scalar product \((v_1, v_2)\) (reduced modulo \(p\)) in case of success and a negative value in case of failure.
Here modulus
pmust be one of the values 3, or 15.This is an optimized version for the case that vector
mv1is sparse. Hereindshould be an array of lengthlen. This array should have been filled with data by calling:mm_aux_index_mmv(p, mv1, ind, len).Function
mm_op_scalprod_indwill crash if arrayindhas not been computed successfully with functionmm_aux_index_mmv. A bufferindof lengthlen = mm_aux_mmv_size(p) + 1is always sufficient.
-
int32_t mm_op_mul_std_axis(uint32_t p, uint_mmv_t *v)
Griess algebra product with standard axis \(v^+\).
Let \(v\) be a vector of the representation \(\rho_p\) of the Monster group stored in the array referred by
v.The function replaces the vector \(v\) by the vector \(v * v^+\). Here \('*'\) is the Griess algebra product. The vector \(v^+\) in \(\rho_p\) is the axis corresponding to the standard 2A involution \(x_\beta\) of the Monster, where \(\beta\) is the Golay cocode element
[2,3].Axis \(v^+\) is scaled so that the eigenvalues of the operator \(\mathop{ad} v^+\) are 0, 1, 8, and 32. For details we refer to Section The Griess algebra product of a vector and an axis in The mmgroup guide for developers.
Variables
-
const uint8_t MM_OP_P_TABLE[] = {0x03, 0x07, 0x0f, 0x1f, 0x7f, 0xff, 0x00}
Table of legal moduli
p, terminted by zero.
C interface for file mm_op_p_axis.c
File mm_op_p_axis.c implements the operation of the Monster group on a vector in the representation \(\rho_p\) of the Monster modulo \(p\). In this module such a vector is usually a 2A axis.
The representation \(\rho_p\) is equal to the 196884-dimensional representation \(\rho\) of the monster, with coefficients taken modulo \(p\), as defined in section The representation of the monster group in the API reference.
The first parameter of a function in this module is the modulus \(p\), and that modulus must be one of the values specified in the function.
An element of \(\rho_p\) is implemented as an array of integers of type uint_mmv_t as described in section Description of the mmgroup.mm extension in this document.
The number of entries of a vector of type uint_mmv_t[] for modulus \(p\) is equal to mm_aux_mmv_size(p).
Functions
-
int32_t mm_op_load_leech3matrix(uint32_t p, uint_mmv_t *v, uint64_t *a)
Load the ‘A’ part of a vector of the representation of the monster.
The function loads the part of with tag ‘A’ of a vector
vof the representation of the monster modulopto the matrixa. Here matrixawill be given in matrix mod 3 encoding as documented in the header of fileleech3matrix.c.Here modulus
pmust be one of the values 3, or 15.
-
int64_t mm_op_eval_A_rank_mod3(uint32_t p, uint_mmv_t *v, uint32_t d)
Rank of ‘A’ part of a vector of the representation of the monster.
Let
abe the symmetric 24 times matrix corresponding to the part with tag ‘A’ of a input vectorvin the representation of the monster modulop. Letb = a - d * 1, for an integer inputd, where1is the unit matrix.Let
rbe the rank of matrixbwith entries taken modulo 3. If matrixbhas rank 23 then its kernel is one dimensional. In that case the kernel contains two nonzero vectors+-w, and we definewto be one of these vectors. Otherwise we letwbe the zero vector.The function returns the value
(r << 48) + w, withwthe vector defined above given in Leech lattice mod 3 encoding as described in The C interface of the mmgroup project.The number of entries of parameter
vfor modulus \(p\) is equal to24 * mm_aux_int_fields(p).Here modulus
pmust be 3, or 15.
-
int32_t mm_op_eval_A_aux(uint32_t p, uint_mmv_t *v, uint32_t m_and, uint32_t m_xor, uint32_t row)
Auxiliary function for
mm_op_eval_ALet matrix
Abe the part with tag ‘A’ of a vectorvof the representation of the monster modulop}.Let
m_and[i]andm_xor[i]be the bitiofm_andandm_xor, respectively. Define a vectory = (y[0],...,y[23])by:y[i] = m_and[i] * (-1)**m_xor[i].If
row >= 24the function returnsres = y * A * transpose(y)(modulop). We have0 < res < 0x8000, butresis not reduced modulop.In case
row < 24define the vectorzbyz[i] = y[i]ifi = rowandz[i] = 0otherwise. Putzz = z * A * transpose(y)(modulop). We have0 < res < 0x8000, butresis not reduced modulop.Here modulus
pmust be 3, or 15.
-
int32_t mm_op_eval_A(uint32_t p, uint_mmv_t *v, uint32_t v2)
Evaluate A part in rep of monster at a short Leech vector.
Let
vbe a vector in the 196884-dimensional representation of the monster group modulop, encoded as described in section Description of the mmgroup.mm<p> extensions in the description of the C interface. The entries corresponding to tag ‘A’ ofvform a symmetric 24 times 24 matrix \(A\).Let \(v_2\) be a short Leech lattice vector given by parameter
v2, encoded as a vector in the Leech lattice modulo 2. Then \(v_2\) is determined up to sign and \(v_2 A v_2^\top\) is determined uniquely.The function returns \(r = v_2 A v_2^\top\) modulo
p, with \(0 \leq r < p\) in case of success. It returns -1 if \(v_2\) is not short (i.e. not of type 2).The short Leech lattice vector \(v_2\) (of norm 4) is scaled to norm 32 as usual, when \(v_2\) is given in integer coordinates.
Here modulus
pmust be 3, or 15.
-
int32_t mm_op_norm_A(uint32_t p, uint_mmv_t *v)
Compute norm of the ‘A’ part of a vector in the rep of the monster.
Assume that
vis a vector in the representation of the monster modulop. Then the part ofvwith tag ‘A’ is considered as a symmetric 24 times 24 matrix. The function returns the norm (i.e. the sum of the squares of the entries) of that matrix.Here modulus
pmust be 3, or 15.
-
int32_t mm_op_watermark_A(uint32_t p, uint_mmv_t *v, uint32_t *w)
Watermark ‘A’ part of a vector of the representation of the monster.
Let matrix
Abe the part with tag ‘A’ of a vectorvof the representation of the monster modulop.Then we watermark 24 the rows of matrix
A. For each of the rowsA[i], 0 <= i < 24we compute a watermarkw(i)in the arrayw. Note that the watermarkw(i)contains an information about the marked rowiin its lower bits. We store the sorted array of these watermarks in the arraywof lengthIf all these watermarks (ignoring the information about the row) are different, we can easily recognize a permutation of the rows of matrix
Aby comparing the watermark of matrixAwith the watermark of the permuted matrixA.
The watermark
w[i]depends on the distribution of the absolute values of the entriesw[i, j](modulop) of rowi. Thus permutations of the columns and sign changes in the matrix do not affect these watermarks.The function returns 0 in case of success and a negative value in case of error.
When working in the representation modulo
p = 3we fail unless at least nine rows ofAhave a unique watermark. This is sufficient for reconstructing a permutation in the Mathieu group.In the other cases the watermark of row \(i\) is equal to \(i + 32\cdot S(A,i)\). Here \(S(A,i)\) depends on the entries of matrix
A. The value \(S(A,i)\) it is invariant under sign changes of any off-diagonal elements ofA. It is also invariant under any permutation of the symmetric matrixAfixing row and column \(i\).We assert that watermarking
A + k*Isucceeds if and only if watermarkingAsucceeds, for any multiplek*Iof the unit matrix.Here modulus
pmust be 3, or 15.
-
int32_t mm_op_watermark_A_perm_num(uint32_t p, uint32_t *w, uint_mmv_t *v)
Compute permutation from watermarks of matrices.
Let matrix
Abe the part with tag ‘A’ of a vectorvof the representation of the monster modulop. Letwbe the watermark of another matrixA'which is obtained fromAby permutations of the rows and columns, and by sign changes. Here the watermarkwmust have been computed by functionmm_op_watermark_A.Then the function watermarks matrix
Aand computes a permutation that mapsA'toA. If that permutation is in the Mathieu group \(M_{24}\) then the function returns the number of that permutation, as given by functionmat24_perm_to_m24numin filemat24_functions.c.The function returns a nonegative permutation number in case of success and a negative value in case of error.
If all watermarks in the array
w(ignoring the information about the row in the lower 5 bits) are different then there is at most one permutation that mapsA'toA. If that permutation is in \(M_{24}\) then the function returns the number of that permutation. In all other cases the function fails.In case
p = 3we succeed already if the first 9 watermarks in the arrayware different. Then there is at most one permutation in \(M_{24}\) that mapsA'toA.Here modulus
pmust be 3, or 15.
-
int32_t mm_op_eval_X_find_abs(uint32_t p, uint_mmv_t *v, uint32_t *p_out, uint32_t n, uint32_t y0, uint32_t y1)
Find certain entries of a vector of the monster rep modulo %
pLet
vbe a vector of the monster group representation modulo %p. The function tries to find all entries of the monomial part ofvwith absolute valuesy0andy1,1 <= y0, y1 <= p / 2. In casey1 = 0entries with valuey1are ignored.Here the monomial part of
vconsists of the entries with tags ‘B’, ‘C’, ‘T’, ‘X’. The coordinates of these entries correspond to the short vectors of the Leech lattice.Output is written into the array
p_outof lengthn. If the monomial part ofvcontains an entry with absolute valuey0then the coordinate of that entry is written into arrayp_outin Leech lattice encoding. If that part ofvcontains an entry with absolute valuey1then the coordinate of that entry is witten into that array in the same encoding.In addition, for entries in
vwith absolute valuey1the bit 24 of the corresponding entry inp_outis set. Inp_out, the entries with absolute valuey1are stored after those with absolute valuey0. Entries with the same absolute value are stored in the same order as inv.The function returns the number of valid entries in the array
p_out. If the lengthnofp_outis too small then some entries will be dropped without notice.Here modulus
pmust be 15.
-
int32_t mm_op_eval_X_count_abs(uint32_t p, uint_mmv_t *v, uint32_t *p_out)
Count certain entries of a vector of the monster rep modulo
pLet
vbe a vector of the monster group representation modulop. The function counts the absolute values of all entries of the monomial part ofv.Here the monomial part of
vconsists of the entries with tags ‘B’, ‘C’, ‘T’, ‘X’. The coordinates of these entries correspond to the short vectors of the Leech lattice.Output is written into the array
p_outof lengthp/2 + 1. Entryp_out[i]contains the number if entries of the monomial part ofvwith absolute valueifor0 <= i <= p/2 + 1.Here modulus
pmust be 15.The function returns 0.
Internal operation
The source code for the functions in modules mm_aux.c
and mm_tables.c is located in subdirectory
src/mmgroup/dev/mm_basics. The code generation process
genrates .c files from the source files with extension
.ske in that subdirectory. Protoypes for the functions in
these .c files can be found in file mm_basics.h.
The source code for the functions in modules mm_op_p_vector.c
and mm_op_p_axis.c is located in subdirectory
src/mmgroup/dev/mm_op. The code generation process
genrates .c files from the source files with extension
.ske in that subdirectory. Protoypes for the functions in
these files can be found in file mm_o_p.h.
The code gerneration process for C files derived from the source
files in the src/mmgroup/dev/mm_basics directory is
straightforward. In the remainder of this subsection we describe
the code gerneration process for files derived form sources
in the src/mmgroup/dev/mm_op directory.
For reasons of efficiency a dedicated set of .c files is
generated from the .ske```files in the ``src/mmgroup/dev/mm_op
directory for each modulus p supported. Here corresponding
.c files for different moduli are generated from the same
source file with extension .ske. The .c functions in
modules mm_op_p_vector.c and mm_op_p_axis.c``contain
automatically-generated ``case statements that call the working
functions for the appropriate modulus p. Any of these .c
functions takes the modulus p as its first argument, and
dispatches the work to the subfunction dedicated to the
appropriate modulus p.
E.g. the function mm_op_pi in module mm_op_p_vector.c` calls
working functions ``mm3_op_pi, mm7_op_pi, etc. in
case p = 3, p = 7, etc., for doing the actual work in the
representation of the Monster modulo p. Such working functions
are implemented in different .c files, with one .c file for
each modulus. So the functions mm3_op_pi and mm7_op_pi are
implemented in the .c files mm3_op_pi.c and mm7_op_pi.c`,
respectively. Here such a .c file may implement several working
functions for the same modules p.
All functions exported from file mm_op_p_vector.c support the
same set of moduli p. Functions exported from file
mm_op_p_axis.c deal with 2A axes; the usually support moduli
3 and 15 (or just one of these two values) only; see documentation
of the corresponding functions.
So the process of switching to the appropriate function for a given modulus is completely invisible for Python and Cython.
Basic table-providing classes for module mmgroup.mm_op
We describe the class MM_Basics and its subclass MM_Const
Class MM_Basics in module mmgroup.dev.mm_basics.mm_basics defines
several constants that describe the organization of vectors of integers
modulo \(p\) used in the representation modulo \(\rho_p\). Here
several integers modulo \(p\) are stored in a single unsigned
integer of type uint_mmv_t. Type uint_mmv_t is equal to the
standard C integer type uint64_t on a 64-bit system.
For a 32-bit system that type may be changed to uint32_t by adjusting
the variable INT_BITS in this module, but this has no longer been
tested for several years.
Constants used for generating representations of the monster Name
Value
FIELD_BITSNumber of bits used to store an integer modulo
P. This is the smallest power of two greater than or equal toP_BITS.
INT_BITSNumber of bits available in an unsigned integer of type
uint_mmv_t. This is equal to 64.
INT_FIELDSNumber of integers modulo
Pthat is stored in a variable of typeuint_mmv_t.INT_FIELDSis a power of two and equal toINT_BITS/FIELD_BITS.
LOG_FIELD_BITSBinary logarithm of the value
FIELD_BITS.
LOG_INT_BITSBinary logarithm of the value
INT_BITS.
LOG_INT_FIELDSBinary logarithm of the value
INT_FIELDS.
LOG_V24_INTSBinary logarithm of the value
V24_INTS.
LOG_V64_INTSBinary logarithm of the value
V64_INTS.
MVV_ENTRIESNumber of integers modulo
Pcontained in a vector of the representation of the monster, including unused entries.
MVV_INTSNumber of integers of type
uint_mmv_trequired to store a vector of the representation of the monster. This value depends onP.
PThe modulus of the current representation being generated.
Pis equal to2**P_BITS - 1.
P_BITSBit length of modulus
P.
V24_INTSNumber of integers of type
uint_mmv_tused up to store a vector of24integers moduloP.V24_INTSis always a power of two.
V64_INTSNumber of integers of type
uint_mmv_tused to store a vector of64integers moduloP.V64_INTSis always a power of two.
V64_INTS_USEDNumber of integers of type
uint_mmv_tactually used to store a vector of24integers moduloP. This may be less thanV24_INTS.
Class MM_Const in module mmgroup.dev.mm_basics.mm_basics is
a table-providing class for the C functions used by python extension
mmgroup.mm. Most C functions in that module take the modulus p as
a parameter. They need fast access to the constants given in the table
above for all legal values of p. Using the code generator with the
tables and directives provided by class MM_Const, we can easily
obtain these values for any legal p as in the following example:
// Return a nonzero value if p is a bad modulus,
// i.e. not p = 2**k - 1 for some 2 <= k <= 8
#define mm_aux_bad_p(p) (((p) & ((p)+1)) | (((p)-3) & ((0UL-256UL))))
// Create a precomputed table containing the constants for modulus p
// %%USE_TABLE
static const uint32_t MMV_CONST_TABLE[] = {
// %%TABLE MMV_CONST_TAB, uint32
};
int do_something_for_modulus_p(uint 32_t p, ...)
{
uint32_t modulus_data, p_bits, field_bits;
// Reject any illegal modulus p
if (mm_aux_bad_p(p)) return -1;
// Load the constants for modulus p to variable modulus_data
// %%MMV_LOAD_CONST p, modulus_data;
// Load value P_BITS for modulus P to p_bits (using modulus_data)
p_bits = %{MMV_CONST:P_BITS,modulus_data};
// Load value FIELD_BITS for modulus P to field_bits
field_bits = %{MMV_CONST:FIELD_BITS,modulus_data};
// Now do the actual work of the function using these values
...
}
- class mmgroup.dev.mm_basics.mm_basics.MM_Const(**kwds)
This is the basic table-providing class for module
mmgroup.mmThe main purpose of this class is to provide the constants defined in class
MM_Basics, for a variable modulus ``pas shown in the example above.This class provides the directive
MMV_CONST_TABfor generating all tables, and the directiveMMV_LOAD_CONSTfor storing the table of constants, for a specific modulusp, in an integer variable. The string formatting functionMMV_CONSTcan be used for extracting a specific constant from that variable, as indicated in the example above.Internally, we use a deBruijn sequence to translate the value
pto an index for the table generated via the directiveMMV_CONST_TAB.Constants not depending on the modulus
p, such asINT_BITS,LOG_INT_BITS, andMMV_ENTRIESare available as attributes of classMM_Const. They can also be coded with the code generator directly via string formatting, e.g.:uint_8_t a[%{MMV_ENTRIES}];For a fixed modulus
pthe constants depending onpcan also be coded with the code generator via string formatting, e.g.:a >>= %{P_BITS:3};That constant also availble in the form
MM_Const().P_BITS(3).Class
MM_Constprovides a string-formatting functionshlwhich generates a shift expression Here:%{shl:expression, i}generates an expression equivalent to
((expression) << i). Hereimust be an integer. In casei < 0we generate((expression) >> -i)instead. E.g.%{shl:'x',-3}evaluates tox >> 3.Class
MM_Constprovides another string-formatting functionsmaskwhich generates an integer constant to be used as a bit mask for integers of typeuint_mmv_t. Here:%{smask:value, fields, width}with integers
value,fields, andwidthcreates such a bit mask.For 0 <= iand0 <= j < width, the bit of that mask at positioni * width + jis set if both, bitiof the integerfieldsand bitjof the integervalueare set. A bit in the mask at positionINT_BITSor higher is never set.Any of the arguments
valueandfieldsmay either be an integer or anything iterable that yields a list of integers. Then this list is interpreted as a list of bit positions. A bit of that argument is set if its position occurs in that list and cleared otherwise.E.g.
%{smask:3, [1,2], 4}evaluates to0x330.- snippet(source, *args, **kwds)
Generate a C code snippet
This method calls function
c_snippetin modulemmgroup.generate_cto generate a C code snippet. Parameters are as in functionc_snippet. The method returns the generated C code snippet as a string.In addition, all tables and directives available in the given instance of the table-providing class are also passed as arguments to function
c_snippet.
We describe the class MM_Op.
Class MM_Op in module mmgroup.dev.mm_op.mm_op is a
table-providing class for the C functions used by python extensions
mmgroup.mm<p>. Each of these extensions implements
the operation of monster group modulo a fixed number p.
Class MM_Op provides the same functionality as class MM_Const
in module mmgroup.dev.mm_basics.mm_basics. Since modulus p
is fixed in an instance of class MM_Op, all constants provided
by the base class MM_Basics of MM_Op and MM_Const (see
table Constants used for generating representations of the monster)
have fixed values. So they are available as attributes of an
instance of class MM_Op and they may also be used by the code
generator directly via string formatting.
The string formatting functions %{shl:expression,i} and
%{smask:value, fields, width} work as in class MM_Op. In
addition, parameter fields defaults to -1 (i.e. the mask
is set in all bit fields) and width defaults to the constant
FIELD_BITS. i.e. the number of bits used to store an integer
modulo p. E.g. for p = 7 we have FIELD_BITS = 4, and
%{smask:1} evaluates to the 64-bit integer constant
0x1111111111111111.
Class MM_Op also provides the following directives:
MMV_ROTL src, count, dest
Rotate the bit fields of a variable of type
uint_mmv_tHere
srcis an integer of typeuint_mmv_twhich is interpreted as an array of bit fields, where each bit field stores a number modulop. Then each bit field is rotated left bycountbits. This means that the numbers in all bit fields are multiplied by2**count.countmust be an integer. It is reduced modulo the bit length ofp. Socountmay also be negative. The result of the rotation is written to the variabledestwhich should also be of typeuint_mmv_t.destdefaults tosrc.
MMV_UINT_SPREAD src, dest, value
Spread bits of an integer
srcto the bit fields ofdest. Heresrcmay be any integer variable anddestshould be a variable of typeuint_mmv_t. If bitiof the integersrcis set then thei-th bit field of variabledestis set tovalue; otherwise it is set to zero.valuemust be an integer with0 <= value <= p; default isp.
- class mmgroup.dev.mm_op.mm_op.MM_Op(**kwds)
Supports basic operations on integers of type
uint_mmv_t.Here an integer of type
uint_mmv_tis interpreted as an array of bit fields, where each bit field stores an integer modulopfor a fixed numberp. This class is similar to classMM_Constin modulemmgroup.dev.mm_basics.mm_basics, where the moduluspmay be variable.Usage of this class is documented in the module documentation.
- Parameters:
p (int) – This is the modulus
3 <= p < 256.p + 1must be a power of two.
Deprecated stuff
In older versions of the mmgroup project the functionality of
the mm_op extension was spread over several Cython extensions
with names mm, mm3, mm7, mm15, etc. There are now
python modules emulating the functionality of these deprecated
extensions, which appear to work in Windows and Linux, but
possibly not in macOS.
Note that the modules mmgroup.mm, mmgroup.mm3, mmgroup.mm7,
etc., which emulate the old functionality, are also deprecated. So the
user is strongly discouraged from using these deprecated modules.
He or she should use the mm_op extension instead!
In older versions some python functions had to select the C function for the requested modulus, which has caused rather nasty problemes in some cases.
In the mm_op extension each documented .c function has
been wrapped by a Cython function with the same name and
the same signature. In the depreceated modules naming conventions
are considerably more complicated.
Description of the mmgroup.mm_reduce extension
The functions in this module implement the fast reduction of an
element of the monster group described in [Sey22]. There
we define a triple of vector \((v_1, v^+, v^-)\) in the
representation \(\rho_{15}\) such that an element
\(g\) of the monster van be recognized from the triple
\((v_1 \cdot g, v^+ \cdot g, v^- \cdot g)\). A precomputed
vector \(v_1\) is stored in file mm_order_vector.c.
Module mm_order.c contains functions for computing the
order of an element of the monster. Module mm_reduce.c
contains the function mm_reduce_M that implements the
fast reduction algorithm in the monster group.
Generating an order vector
Python module mmgroup.dev.mm_reduce.find_order_vector
This module computes an order vector in a representation of the monster.
In [Sey22] we define a vector \(v_1\) in the representation \(\rho_{15}\) of the monster group \(\mathbb{M}\) that is used for recognizing elements of the subgroup \(G_{x0}\) of \(\mathbb{M}\). Vector \(v_1\) is also used for computing the order of an element of \(\mathbb{M}\), so we call \(v_1\) an order vector here.
\(v_1\) is constructed from two vectors \(v_{71} \in \rho_3\) and \(v_{94} \in \rho_5\) via Chinese remaindering. This module contains functions for computing vectors \(v_{71}\) and \(v_{94}\) with the properties required in [Sey22].
These computations are the most time-consuming part of the computation of \(v_1\); and we use multiprocessing for performing these computations.
All computations in the monster group are done with instances
of class MM0, but not MM. The reason for this is that
class MM requires the existence of an order vector.
Header file mm_reduce.h
Yet to be documented
Typedefs
-
typedef struct gt_subword_s gt_subword_type
typedef for structure
struct gt_subword_s
-
typedef struct gt_subword_buf_s gt_subword_buf_type
typedef for structure
struct gt_subword_buf_s
-
typedef struct mm_order_find_Gx0_s mm_order_find_Gx0_type
typedef for structure
struct mm_order_find_Gx0_s
-
typedef struct mm_order_data_Gx0_s mm_order_data_Gx0_type
typedef for structure
struct mm_order_data_Gx0_s
-
struct mm_compress_type
- #include <mm_reduce.h>
Structure for storing an element of the Monster compactly.
A properly reduced element of the Monster stored in a structure of type
gt_word_typemay also be encoded in this structure in a more compact form. This facilitates the conversion of that element to an integer, which is out of the scope of this module.This structure may store an element of the Monster as a word of generators of shape
\[ y_f \, x_d \, x_{\delta} \, \pi \, c_1 \, \tau_1 \, c_2 \, \tau_1 \, c_3 \, \tau_3 \, \ldots \, , \]where \(d, f \in \mathcal{P}, \delta \in \mathcal{C}^*\), and \(\pi \in \mbox{Aut}_{\mbox{St}} \mathcal{P}\). Here \(\pi\) must correspond to a generator with tag
p. See section Implementation of the generators of the monster group in the API reference for details. \(\tau_i\) is wqaul to generator \(\tau\) or to its inverse.A generator \(c_i\) is an element of the group \(G_{x0}\) referred by a 24-bit integer
c_irepresenting a type-4 vector in Leech lattice encoding. This encodes the inverse of the element of \(G_{x0}\) computed by applying the C functiongen_leech2_reduce_type4toc_i.The product \(y_f \, x_d \, x_{\delta} \, \pi\) is encdoded in component
nx, and the other generators are encdoded in the entries of componentw, as desribed in the procedures below.For background see section Computations in the Leech lattice modulo 2 in The mmgroup guide for developers.
-
struct gt_subword_s
- #include <mm_reduce.h>
Stucture to store a subword of generators of the Monster.
This structure is required in file
mm_shorten.c.It stores a subword of a word in the Monster in a node of a circular doubly-linked list. There is a dedicated EOF (end of file) mark in that list, in which member
eofis set to 1; and elsewhere membereofis set to zero. Note that standard operations like insertions and deletions are easier in a circular doubly-linked list than in a standard doubly-linked list.Member
datacontains a word \(g\) of generators of the subgroup \(G_{x0}\); and membert_expcontains an exponent \(0 \leq e < 3\). Then the structure represents the element \(g \tau^e\) of the Monster, where \(\tau\) is the triality element in the subgroup \(N_0\) of the Monster.The length of a word in member
datais limited to the sizeMAX_GT_WORD_DATA - 1; and we will reduce that word using functionxsp2co1_reduce_wordin modulexsp2co1.cif necessary. Note that memberdatamay contain atoms with tags'x', 'y', 'd', 'p', 'l'only, and the inversion bit in such an atom is always cleared.Member
img_Omegacontains the image \(g \cdot \Omega\), where \(\Omega\) is the standard frame of the Leech lattice mod 2. Hereimg_Omegais given in Leech lattice encoding. Memberreducedis 1 if the word in memberdatais reduced (by functionxsp2co1_reduce_word) and 0 otherwise.Public Members
-
uint32_t eof
0 means standard subword, 1 means EOF mark
-
uint32_t length
Number of entries in component
data
-
uint32_t img_Omega
Image of \(\Omega\) under element.
-
uint32_t t_exp
Exponent of final tag ‘t’.
-
uint32_t reduced
True if part ‘data’ is reduced.
-
struct gt_subword_s *p_prev
Pointer to previous subword.
-
struct gt_subword_s *p_next
Pointer to previous subword.
-
uint32_t data[MAX_GT_WORD_DATA]
Element of monster group.
-
uint32_t eof
-
struct gt_subword_buf_s
- #include <mm_reduce.h>
Structure to store an array of entries of type
gt_subword_typeWe allocate several entries of of type
gt_subword_typewith a single call to functionmalloc. This saves a considerable amount of interaction with the operating system.This structure contains an array of type
gt_subword_type[]plus the necessary bookkeeping information.Public Members
-
uint32_t capacity
max No of type
gt_subword_sentries
-
uint32_t n_used
used No of type
gt_subword_sentries
-
struct gt_subword_buf_s *p_next
Pointer to next buffer.
-
gt_subword_type subwords[1]
array of subwords in this buffer
-
uint32_t capacity
-
struct gt_word_type
- #include <mm_reduce.h>
Stucture to store a word of generators of the Monster.
This structure is required in file
mm_shorten.c.It stores a word in the Monster in a circular doubly-linked list of nodes of type
gt_subword_type. Each of these node represents subword of that word, and there is a dedicated EOF (end of file) mark in that list that marks both, the beginning and the end of the list. Memberp_endalways points to the EOF mark.The structure contains a pointer
p_nodepointing to one of the nodes of the list, which we will call the current node. Some functions in these module take a pointer to this structure, and the perform operations on the current node. The pointer may be manipulated with functiongt_word_seek.Public Members
-
gt_subword_type *p_end
Pointer to the end mark subword.
-
gt_subword_type *p_node
Pointer to current subword.
-
gt_subword_type *p_free
Pointer to list of free subwords.
-
int32_t reduce_mode
Mode for the reduction of a word.
-
uint32_t is_allocated
1 if this structure has been allcocated
-
gt_subword_buf_type *pb0
pointer to first buffer
-
gt_subword_buf_type *pbe
pointer to last buffer
-
gt_subword_buf_type buf
1st buffer containing Array of subwords
-
gt_subword_type *p_end
-
struct mm_order_find_Gx0_s
- #include <mm_reduce.h>
Structure for state machine for finding an element of \(G_{x0}\).
This structure is used in file
mm_vector_v1_mod3.c. For details we refer to the documentation of that file.Public Members
-
int32_t state
State of state machine.
-
uint32_t length
Number of entries in component
data
-
uint32_t data[24]
Interface to caller.
Private Members
-
uint32_t len_g
Length of group element g.
-
uint32_t g[12]
Group element g computed so far.
-
uint32_t signs
For internal use.
-
struct mm_order_data_Gx0_s *pdata
point to data for evaluation
-
int32_t state
-
struct mm_order_data_Gx0_s
- #include <mm_reduce.h>
Structure for finding an element of \(G_{x0}\) from a vector.
This structure is used in file
mm_vector_v1_mod3.c. Data in this structure are used to compute an element of the group \(N_{x0}\) of structure \(2^{1+24+11}.M_{24}\) that transforms the a given vectorvto the standard order vectorv1.Part
HAcontains the hash values of the rows of part ‘A’ of the order vectorv1.Part
WMcontains hash values of rows of part ‘A’ ofv1. The hash value of a row is the sum of the absolute values of the entries (mod 3) of the row vector plus 32 times the diagonal element. EntryWMcontains hash values of rows [0,1,2,3,4,5,8] ofv1. From these entries we compute a permutationpiin a factor group \(M_{24}\) that transformsvto a vector inv1* \(2^{1+24+11}\). In the sequel we assume thatvis in that group.An entry (Y[k,0],Y[k,1]) describes an entry in the 24 times 24 matrix making up part ‘A’ of the vector
v1. The 11 entries ofv1encoded here must all be 1 (mod 3). Also the positions of these entries are linear independent when considered as Golay cocode vectors. From the corrsponding entries ofv1we compute a bit vector by setting the bits where the correspnding entry is 2 (mod 3). Multiplying that bit vector by the matrix in part EQU_Y yields an elementdof the Golay code, such that transforming the vectorvwithy_dyields a vector inv1* \(Q_{x0}\), with \(Q_{x0}\) of structure \(2^{1+24}\). In the sequel we assume thatvis in that group.Part
Xcontains a list of 24 entries ofv1(in Leech lattice encoding) that are used to determine a transformationx_r = x_d * x_deltathat transformsvto a vector inv* \(x_{\pm 1}\). As above, a bit vector is computed from these 24 entries. The product of that bit vector with the matrix EQU_X yields an elementrin the Leech lattice mod2 (in Leech lattice encoding) so thatv * x_ris equal tov1up to multiplication by \(x_{\pm 1}\). The sign is obtained by inspecting the entry ofv * x_rencoded in partZ(im sparse notation).Public Members
-
uint8_t HA[24]
hash values for part ‘A’ of order vector
-
uint8_t WM[7]
hash table for part ‘A’ of vector
-
uint8_t Y[11][2]
(Y[k,0],Y[k,1]) refers to ‘A’[Y[k,0],Y[k,1]]
-
uint32_t EQU_Y[11]
matrix to solve equation for y_e
-
uint32_t X[24]
Vector entries in parts B, C, T, X in sparse notation.
-
uint32_t EQU_X[24]
matrix to solve equation for x_r (mod x_{-1}
-
uint32_t Z
Vector entriy in part Z on sparse notation.
-
uint8_t HA[24]
C interface for file mm_order_vector.c
File mm_order_vector contains the precomuted order_vector and data related to that order_vector,
It also contains functions for retrieving these data.
Functions
-
int32_t mm_order_load_tag_data(uint32_t *buf, uint32_t buf_size)
Load data from tables to a buffer.
The propose of this function is to provide the information for checking the correctness of the precomuted order vector \(v_1\) stored in this module.
This function stores precomputed data in a buffer
bufof typeuint32_t[buf_size], wherebuf_sizeis the size of the buffer. Parameternspecifies the value to be stored in the buffer. The function returns the length of the data in buffer. If the buffer is too short for that data then the function returns -1.For the interpretation of this data we refer to class
mmgroup.dev.mm_reduce.order_vector.OrderVectorMod15.
-
void mm_order_load_vector(uint_mmv_t *p_dest)
Load order vector from tables to a buffer.
The function stores the precomputed order vector \(v_1\) into the array referred by
p_dest. That array must must be sufficiently long to store a vector of the representation \(\rho_{15}\).See [Sey22] for a decription of the properties of the vector \(v_1\) in the representation \(\rho_{15}\) of the monster group.
The standard way to obtain the number of entries of type
unint_mmv_trequired for a vector of the representation \(\rho_{15}\) is to call functionmm_aux_mmv_size(15)in filemm_aux.c.
-
int32_t mm_order_compare_vector(uint_mmv_t *p_v)
Compare vector with precomputed order vector.
The function compares the vector \(v\) in the representation \(\rho_{15}\) of the monster group referred by
p_vwith the precomputed order vector \(v_1\).The function returns 0 in case of equality and 1 otherwise.
-
int32_t mm_order_compare_vector_part_A(uint_mmv_t *p_v)
Compare A part of vector with precomputed order vector.
The function compares the A part the vector \(v\) in the representation \(\rho_{15}\) of the monster group referred by
p_vwith the A part of the precomputed order vector \(v_1\).The function returns 0 in case of equality and 1 otherwise.
-
uint64_t mm_order_hash_vector(uint_mmv_t *p_dest)
Return the hash value of the ordervector.
The function returns the hash value of the precomuted order vector as given by function
mm_aux_hashin filemm_aux.c.
C interface for file mm_order.c
File mm_order.c contains functions for checking if an element is in the subgroup \(G_{x0}\) (or \(Q_{x0}\)) of the monster group. If this is the case, the element is expressed as a word in the generators of the corresponding subgroup.
File mm_order.c also contains functions for computing the order of an element of the monster.
All these function use the precomputed order_vector in file mm_order_vector.c
Enums
-
enum tag_offsets
The following enumeration contains the offsets of the (static) array
TAG_VECTORof unsigned 32-bit integers stored in this module. This array contains data that are required for dealing with the precomputed order vector \(v_1\) stored in this module. That order vector can be obtained by calling functionmm_order_load_vectorin modulemm_order_vector.c. The data in the arrayTAG_VECTORcan be obtained by calling functionmm_order_load_tag_datain the same module.The purpose of the order vector \(v_1\) is to identify an element \(g\) of the subgroup \(G_{x0}\) of the monster from \(v_1 \cdot g\), as described in [Sey22]. The basic steps of this identification process are:
Given \(v_1 \cdot g\), reduce \(g\) to an element \(g_1\) of \(N_{x0}\), see [Sey22] for background.
Given \(v_1 \cdot g_1\), reduce \(g_1 \in N_{x0}\) to \(g_2\), where \(g_2\) is in a certain 2 group of structure \(2^{1+24+11}\). Therefore we have to watermark of the A part of \(v_1 \cdot g_1\) with function
mm_op15_watermark_Ain modulemm15_op_eval_A.c. Then we have to check that watermark against the precomputed watermark of the A part of \(v_1\) using functionmm_op15_watermark_A_perm_numin the same module. That precomputed watermark (of length 24) is stored in the arrayTAG_VECTORat offsetOFS_WATERMARK_PERM.Given \(v_1 \cdot g_2\), with \(g_2\) as above, we want to present \(g_2\) as a product of generators \(g_2 = x_d x_\delta y_e\). For computing the factor \(y_e\) we have to extract (the signs of) 11 entries of \(v_1 \cdot g_2\), with function
mm_aux_mmv_extract_sparse_signsin modulemm_aux.c. The coordinates and the expected values of these 11 entries are stored at theTAG_VECTORat offsetOFS_TAGS_Y. Once having extracted these sign bits we have to solve the linear equation system given by the 11 entries at theTAG_VECTORat offsetOFS_SOLVE_Y. This solution gives the value \(e\) of the factor \(y_e\).For computing the part \(x_d x_\delta\) of \(g_2\) (up to sign) we have to extract (the signs of) 24 more entries of the vector \(v_1 \cdot g_2 y_e^{-1}\) and to solve another equation system as in the previous step. Here the relevant coordinates are stored at the
TAG_VECTORat offsetOFS_TAGS_X, and the equation system is stored at offsetOFS_SOLVE_X.To correct the sign in the part \(x_d x_\delta\), we have to extract another sign from \(v_1 \cdot g_2 \cdot y_e^{-1} (x_d x_\delta)^{-1}\) at the coordinate given by
OFS_TAGS_SIGN.
Values:
-
enumerator OFS_DUMMY
Functions
-
int32_t mm_order_check_in_Gx0_fast(uint_mmv_t *v)
Quick check if a vector is an image under an element of \(G_{x0}\).
Assume that the vector \(v\) in \(\rho_{15}\) referred by
vis the image of the precomputed order vector \(v_1\) under an (unknown) element \(g\) of the monster. The function checks if that element \(g\) is in the subgroup \(G_{x0}\) of the monster.The function may return 0, 1, or a negative value. If it returns 0 then \(g\) is not in \(G_{x0}\). If it returns 1 then \(g\) is in \(G_{x0}\) with an error probability that is negligible for all practial purposes. A negative return value indicates an error.
-
int32_t mm_order_check_in_Gx0(uint_mmv_t *v, uint32_t *g, uint32_t mode, uint_mmv_t *work)
Check if a vector is an image under an element of \(G_{x0}\).
Assume that the vector \(v\) in \(\rho_{15}\) referred by
vis the image of the precomputed order vector \(v_1\) under an (unknown) element \(g\) of the monster. We want to find that element \(g\) if it is in the subgroup \(G_{x0}\) of the monster.We first describe the action of the function in the standard case that parameter
modeis zero.The function computes the element \(g\) if it is in the subgroup \(G_{x0}\) of the monster; otherwise it fails.
In case of success the function writes the element \(g\) into the array
gas a word in the generators of \(G_{x0}\) of length at most 11; and the function returns the length of that word.If no such element \(g_1\) has been found then the function returns a number greater than 256. Then the exact return value gives some indication why no such element \(g\) has been found; this is for debugging only.
A negative return value indicates an internal error.
The function also requires an array
workof length 15468 as a work buffer. This is the capacity required for storing a vector in the representation \(\rho_{15}\).Parameter
modeis a bit field that modifies the action of the function as follows:If bit 0 is set, then the inverse of the result \(g\) is returned in buffer
g.If bit 1 is set then we insert an atom into the word in
gthat indicates the image of the vector \(\Omega \in \Lambda / 2 \Lambda\) under conjugation with \(g_0\). Such an atom is considered as a comment, acting as the neutral element of the monster group. This is required for functionmm_reduce_Min filemm_reduce.c. See documentation in that file for details.If bit 2 is set then we perform an action to be used for internal tests only. Then the function computes an element \(g_1\) such that \(g^{-1} g_1\in Q_{x0}\) holds in case \(g \in G_{x0}\). If \(g \notin G_{x0}\) then the function detects this fact with high probability. Usually, \(g_1\) is a shorter word in the generators of the monster than \(g\).
If bit 3 is set then input vector
vis preserved; but the work bufferworkmust have the (doubled) length 30936 for storing an additional temporary copy of vectorv.
-
int32_t mm_order_element_Gx0(uint32_t *g, uint32_t n, uint32_t *h, uint32_t o)
Compute exponent \(e\) such that \(g^e \in G_{x0}\).
Let \(g\) be the element of the monster group stored in the array
gas a word of generators of the monster group of lengthn.The function computes the smallest exponent \(e\) such that \(g^e\) is in \(G_{x0}\). Then the function writes \(h = g^e\) into the buffer
has a word of generators of \(G_{x0}\) of length at most 10. Let \(k\) be the length of the word representing \(h\). Then the function returns the value \(\mbox{0x100} \cdot e + k\); here we have \(1 \leq e \leq 119\) and \(0 \leq k \leq 10\).Computation of \(e\) is time consuming, and in some cases we are interested in small values of \(e\) only. Parameter
ois an upper bound for the exponent \(e\) . The function may abort and return 0 in if \(e\) is greater thano; then the data in bufferhare invalid.A negative return value indicates an internal error.
-
int32_t mm_order_element_M(uint32_t *g, uint32_t n, uint32_t o)
Compute order of an element \(g\) of the monster.
Let \(g\) be the element of the monster group stored in the array
gas a word of generators of the monster group of lengthn.The function returns the order of \(g\).
Computation of the order is time consuming, and in some cases we are interested in small orders only. Parameter
ois an upper bound for the order. The function may return 0 if the order is greater thano.A negative return value indicates an error.
C interface for file mm_reduce.c
Function mm_reduce_M is the most important C function in this project. It reduces an arbitrary element of the monster group (represented as a word in the generators of the monster) to a word of fixed maximum length. Function mm_reduce_M uses the method in [Sey22] for reducing an element of the monster.
Here a word in the monster group is represented as an array of 32-bit integers of type uint32_t as described in section The monster group in the API reference. Such an array represents a word of generators of the monster. Thus group multiplication is concatenation of words. An generator in a word (given by an entry in the array of integers) can be inverted by flipping its most significant bit.
According to [Sey22], and element \(g\) of the monster group can be computed from the images \(v^+ g\), \(v^- g\), and \(v_1 g\). Here \(v^+, v^- \in \rho_{15} \) are certain 2A axes, and \(v_1 \in \rho_{15}\) is certain vector used for recognizing an element of the subgroup \(G_{x0}\) of the monster, see ibid. for details. Representation \(\rho_{15}\) is the 198884-dimensional faithful representation of the monster group modulo 15. Vector \(v_1\) is also called an order vector; and we can use the functions in module mm_order.c for dealing with a fixed precomputed order vector.
An element of \(\rho_{15}\) is implemented as a array of MM_OP15_LEN_V integers of type uint_mmv_t as described in The C interface of the mmgroup project, section Description of the mmgroup.mm extension. The value MM_OP15_LEN_V is defined in file mm_op15.h.
For reducing an element \(g\) of the monster we have to analyze the images \(v^+ g\), \(v^- g\), and \(v_1 g\) in that order. This file also exports subfunctions for performing these tasks. We use subfunctions mm_reduce_vector_vp, mm_reduce_vector_vm, and mm_reduce_vector_v1 for analyzing \(v^+ g\), \(v^- g\), and \(v_1 g\), respectively. These functions accumulate their results in a buffer (of type uint32_t[] and size at least 128) that will eventually contain the reduced word equal to \(g\).
The following code example shows an implementation of the main function mm_reduce_M based on these subfunctions, ignoring the error handling.
// The following buffers contain the element ``g`` to be reduced
uint32_t a[256]; // buffer containing element ``g``
uint32_t n; // length of data in buffer ``a``
// The folling buffers will contain the reduced element ``g``
uint32_t r[256]; // buffer for reduced element ``g``
uint32_t len; // length of data in buffer ``r``
// Temporary work buffers
uint_mmv_t v[MM_OP15_LEN_V]; // buffer for 2A axes
uint_mmv_twork[MM_OP15_LEN_V]; // work buffer
mm_op15_store_axis(V_PLUS, v ); // Store 2A axis V_PLUS in v
mm_op15_word(v, a, n, 1, work); // multiply v_plus with g
mm_reduce_vector_vp(0, v, mode, r, work); // reduce V_PLUS * g
mm_op15_store_axis(V_MINUS, v ); // Store 2A axis V_MINUS in v
mm_op15_word(v, a, n, 1, work); // multiply v_minus with g
mm_reduce_vector_vm(0,v, r, work); // reduce V_MINUS * g
mm_order_load_vector(v); // load the order vector v_1
mm_op15_word(v, a, n, 1, work); // multiply v_1 with g
len = mm_reduce_vector_v1(v, r, work); // reduce v_1 vector
// Now buffer ``r`` contains the reduced word of length ``len``
// equal to the element ``g`` of the monster group.
Functions
-
uint32_t mm_reduce_2A_axis_type(uint_mmv_t *v)
Return type of a 2A axis in rep of monster.
Let
vbe a vector in the 196884-dimensional representation of the monster group modulo15, encoded as described in section Description of the mmgroup.mm<p> extensions in the description of the C interface.If
vis a 2A axis then the function computes the type of the 2A axis. Each 2A axis corresponds uniquely to a 2A involution \(x\) in the monster. Let \(z\) be the central involution in the subgroup \(G_{x0}\) of the monster. Then the type of the 2A axisvis the class of the product \(xz\) in the monster, which has one of the values 2A, 2B, 4A, 4B, 4C, 6A, 6C, 6F, 8B, 10A, 10B, 12CThe function returns a value
n * 2**28 + k * 2**24 + v. Herenis the number of the class, e.g.n == 6for class 6C,kencodes the letter in the name of the class (‘A’ = 1, ‘B’ = 2, …) e.g.k = 3for class 6C.Output
vis either 0 or a vector in the Leech lattice mod 2 found during the computation. Here a vector of type 2 is returned for classes 2A, 6A; and a vector of type 4 is returned for class 4A.Caution:
This is a quick disambiguation of the type of a 2A axis. The function may return any axis type if
vis not a 2A axis.
-
int32_t mm_reduce_analyze_2A_axis(uint_mmv_t *v, uint32_t *r)
Analyze a 2A axis in rep of monster.
Let
vbe a vector in the 196884-dimensional representation of the monster group modulo15, encoded as described in section Description of the mmgroup.mm<p> extensions in the description of the C interface.We assume that
vdescribes a 2A axis \(v\). The purpose of this function is to compute the list \(U(v)\) of vectors in the Leech lattice mod 2 defined in [Sey22], Section 8.4.If
vis a 2A axis then the function analyzes the type of the 2A axis. Each 2A axis corresponds uniquely to a 2A involution \(x\) in the monster. Let \(z\) be the central involution in the subgroup \(G_{x0}\) of the monster. Then the type of the 2A axisvis the class of the product \(xz\) in the monster, which has one of the values 2A, 2B, 4A, 4B, 4C, 6A, 6C, 6F, 8B, 10A, 10B, 12CThe function returns 0 in case of success and a negative value value if it detects an error.
Buffer
rshould be at least 896 bytes long. It will contain the result.The entries of buffer
rare set as follows:Entry 0: Axis type of axis
v. This is an integer16 * n + k. Herenis the number of the class, e.g.n == 6for class 6C; andkencodes the letter in the name of the class (‘A’ = 1, ‘B’ = 2, …).Entry 1: Axis type of a target axis, ecoded as entry 0.
Entry 2: Axis type of a target axis, ecoded as entry 0.
Entry 3: Number N of entries in the following List \(U(v)\).
Entries 4, …, N + 3: Here each entry encodes a vector in the Leech lattice mod 2 in Leech lattice encoding.
Entries 2 and 3 of buffer
rdescribe the Axis type to which axis \(v\) may be reduced by applying first an transformation in \(G_{x0}\) and then a power of the triality element \(G_{x0}\). Both entries are encoded in the same way as Entry 1. So these two entries desribe the graph in [Sey22], Figure 2. An unused entry is encoded as0xffffffff.If the axis type of \(v\) is 2A then we define \(U(v)\) to be the singleton containing the short vector in the Leech lattice corresponding to axis \(v\).
Caution:
This is a quick analyis of a 2A axis. The function may return garbage if
vis not a 2A axis.
-
uint32_t mm_reduce_find_type4(uint32_t *v, uint32_t n, uint32_t v2)
Select a type-4 vector from list of Leech lattice vectors
Let
vbe an array ofnvectors in the Leech lattice modulo 2 in Leech lattice encoding.If parameter
v2is 0 then the function returns the least vector of type 4 in the listvwith repect to a certain ordering. If listvcontains no vector of type 4 then the function returns 0.Here subtypes are ordered as follows:
[48, 40, (42, 44), 46, 43]. So e.g. a vector of subtype40is selected in favor of a vactor of subtype46. We do not distinguish between substypes42and44. From all vectors of the same subtype (equalizing subtypes42and44) we return the smallest vector in the list in the natural order.If
v2is nonzero then we accept only vectorsv1in the listvwithtype(v1) = 4andtype(v1 + v2) = 2.The list
vis destroyed. More precisely, all entries ofvare masked with0xffffffand subjected to an (undocumented) permutation.
-
uint32_t mm_reduce_find_type4_axis(uint_mmv_t *v, uint32_t v2)
Select a suitable type-4 vector
wfor beautifyng an axisThis function combines the actions of functions
mm_reduce_analyze_2A_axisandmm_reduce_find_type4. Given a vectorvecoding an axis \(v\), the function first computes the list \(U(v)\) defined in functionmm_reduce_analyze_2A_axis. Then it uses functionfind_type4to find a type-4 vectorwin that list. If parameterv2is nonzero then we look for vectorswwithtype(w) = 4andtype(w + v2) = 2only. Letaxis_typebe the type of axis \(v\) as computed by functionmm_reduce_analyze_2A_axis.Then the function returns
(axis_type << 24) + w.The function may or may not detect that \(v\) is not an axis. If the function detects this, it returns 0. If \(v\) is not an axis then the fuction may also return a valid
axis_type, and either a valid vectorw, orw = 0.In the special case that the detected axis type of
vis 2A (i.e.axis_type == 0x21) we letwbe the type-2 vector corresponding to axisv, ignoring parameterv2.We choose the vector
wdetermistically; but the choice ofwis impelementation dependent.
-
int32_t mm_reduce_transform_v4(uint_mmv_t *v, uint32_t v4, uint32_t *target_axes, uint32_t *r, uint_mmv_t *work)
Transform a 2A axis to a ‘better’ 2A axis.
The function tries to transform the 2A axis \(v\) given by parameter
vto a better axis. Therefore it first applies a transformation \(g \in G_{x0}\) given by parameterv4. Herev4must be a vector of type 4 in the Leech lattice mod 2 in Leech lattice encoding. Then \(g\) is the transformation mappingv4to the standard type 4-vectorOmegaas computed by functiongen_leech2_reduce_type4.In the next step this function tries to apply the transfomations \(\tau^e\) for \(e = 1,2\) (in that order) until the type of the axis \(v g \tau^e\) is in a set of types given by parameter
target_axes. Heretarget_axesmust be an array of length 2 containing the feasible axis types, encoded as described in functionmm_reduce_2A_axis_type. An unused entry in arraytarget_axesshould be set to0xffffffff.If a suitable transformed axis \(v g \tau^e\) has been found then the function stores the element \(g \tau^e\) in the array referred by
r; and it returns the length of the data in the arrayr. Then it also overwrites the axis in buffervwith the transformed axis.The function returns a negative value in case of any error, e.g. if no suitable transformed axis \(v\) has been found; then buffers
vandrwill contain garbage.If the original axis \(v\) is orthogonal to the standard 2A axis then the transformed axis is also orthogonal to that axis.
Buffer
rmust have size at least 7. The function requires a work bufferworkof the same type and size as parameterv.
-
int32_t mm_reduce_load_axis(uint_mmv_t *v, uint32_t s)
Load the 2A axis \(v^+\) or \(v^-\) into a vector in \(\rho_{15}\).
The function loads the 2A axis \(v^+\) (in case
s == 0) or \(v^-\) (in cases == 1) in the vector referred byv. Other values ofsare illegal. Vectorvwill store an element of the representation \(\rho_{15}\) of the monster group as described in the header of this file. Vectors \(v^+\) and \(v^-\) are defined in [Sey22], Section 6.
-
int32_t mm_reduce_map_axis(uint32_t *vt, uint_mmv_t *v, uint32_t *a, uint32_t n, uint_mmv_t *work)
Transform a 2A axis with an element of the Monster group.
Here we encode a 2A axis \(v\) as follows. It may be encoded as an element of the group \(Q_{x0}\) in the integer referred by
vt. In case*vt = 0we encode \(v\) as a vector of the representation \(\rho_{15}\) of the Monster in the arrayv. In case*vt != 0the value*vtmust be a short element (corresponding to a type-2 vector in \(\Lambda/2\Lambda\)) of the group \(Q_{x0}\), in Leech lattice encoding.vis ignored in case*vt != 0.Let \(g\) be the element of the monster given as a word of generators in the buffer
aof lengthn. Then the function computes \(v' = v \cdot g\) and stores \(v'\) in*vt(if possible), or inv. In last case it sets*vtto zero.The function returns 0 in case of success an a negative value in case of failure. It requires a work buffer
workof the same type and size as parameterv.
-
int32_t mm_reduce_vector_vp(uint32_t *vt, uint_mmv_t *v, uint32_t mode, uint32_t *r, uint_mmv_t *work)
Step 1 of the reduction of an element of the monster.
Here inputs
vtandvof this function encode a 2A axis \(v\) as described in functionmm_reduce_map_axis. Here \(v\) is considered as an image \(v = v^+ \cdot g\) of \(v^+\) under the operation of an (unknown) element \(g\) of the Monster group.The function computes an element \(h\) of the monster group with \(v \cdot h = v^+\). We use the method in [Sey22], Section 6 ff. for computing \(h\).
The function stores \(h\) as a word of generators in the array
ras described in the header of this file and returns the length of this word. That word is augmented by some atoms acting as commentsThe buffer referred by
rshould have length at least 128.Parameter
modeis yet to be documented! In the current version is should be set to1. This means that the function will strictly follow the reduction method in ibid.A negative return value indicates a fatal error.
Parameter
workmust refer to a work buffer of size at leastMM_OP15_LEN_V.More details are yet to be documented!!!!
-
int32_t mm_reduce_vector_shortcut(uint32_t stage, uint32_t mode, uint32_t axis, uint32_t *r)
Simulate steps of the reduction of an element of the monster.
Yet to be documented!!!!
-
int32_t mm_reduce_vector_vm(uint32_t *vt, uint_mmv_t *v, uint32_t *r, uint_mmv_t *work)
Step 2 of the reduction of an element of the monster.
This function should be applied immediately after function
mm_reduce_vector_vp.Here inputs
vtandvof this function encode a 2A axis \(v\) as described in functionmm_reduce_map_axis. Here \(v\) is considered as an image \(v = v^+ \cdot g\) of \(v^+\) under the operation of an (unknown) element \(g\) of the Monster group.The function computes an element \(h\) of the monster group with \(v \cdot h = v^-\). We use the method in [Sey22], Section 8, for computing \(h\). Note that \(h\) preserves the 2A axis \(v^+\).
The function appends \(h\) as a word of generators to the array
ras described in the header of this file and returns the length of the data in the arrayr. That information in bufferris augmented by some atoms acting as comments.The buffer referred by
rshould have length at least 128.A negative return value indicates a fatal error.
Parameter
workmust refer to a work buffer of size at leastMM_OP15_LEN_V.More details are yet to be documented!!!!
-
int32_t mm_reduce_vector_v1(uint_mmv_t *v, uint32_t *r, uint_mmv_t *work)
Step 3 of the reduction of an element of the monster.
This function should be applied immediately after functions
mm_reduce_vector_vpandmm_reduce_vector_vm.Here input
vof this function must refer to the image of the precomputed order vector \(v_1 \in \rho_{15}\) under the operation of the same element \(g\) of the monster group as described in the documentation of functionmm_reduce_vector_vp.The function computes an element \(h\) of the monster group with \(v \cdot h = v_1\). We use the method in [Sey22], Appendix A. for computing \(h\). Note that \(h\) preserves the 2A axes \(v^+\) and \(v^-\).
The function appends \(h\) as a word of generators to the array
ras described in the header of this file and returns the length of the data in the arrayr. That information in bufferris augmented by some atoms acting as comments.Finally, the function computes a word in the buffer that is equal to the element \(g\) of the monster group and stores that element in the buffer
r. The function returns the length of data in bufferr.The buffer referred by
rshould have length at least 128.A negative return value indicates a fatal error.
Parameter
workmust refer to a work buffer of size at leastMM_OP15_LEN_V.
-
static inline int32_t mm_reduce_vector_v1_mod3(uint_mmv_t *v, uint32_t *r, uint_mmv_t *work)
Variant of Step 3 of the reduction of an element of the monster.
This is a variant of function
mm_reduce_vector_v1that works with precomputed order vector \(v_1 \in \rho_{3}\) instead of an order vector in \(\rho_{15}\). Parameters and operation are the same as in functionmm_reduce_vector_v1. But here inputvof this function must refer to the image of the precomputed order vector \(v_1 \in \rho_{3}\) under the operation of the same element \(g\) of the monster group as described in the documentation of functionmm_reduce_vector_vp.The order vector \(v_1 \in \rho_{3}\) can be obtained by using the functions in module
mm_vector_v1_mod3.c.This function is faster than function
mm_reduce_vector_v1. But the order vector in \(v_1 \in \rho_{3}\) may have a non-trivial centralizer in the Monster; so we cannot use it for checking equality of elements of the Monster.The buffer referred by
rshould have length at least 128.A negative return value indicates a fatal error.
Parameter
workmust refer to a work buffer of size at leastMM_OP3_LEN_V.
-
static inline int32_t mm_reduce_vector_shorten(uint32_t *a, uint32_t n, uint32_t *r, uint_mmv_t *work)
Special case of Step 3 of reduction of an element of the monster.
This is a variant of function
mm_reduce_vector_v1that works in the special case when all prefixes of a word \(g\) in the Monster map the 2A-involutions \(v^+\) and \(v^-\) to 2A-involutions in the subgroup \(Q_{x0}\) of \(G_{x0}\). Here the mapping is done via conjuation. That condition holds e.g if all prefixes of the word \(g\) are in \(\in N_x \cdot G_{x0}\).The function returns 0 in case of success and a negative value in case of failure. In case of success, this function is (at least) 100 times faster than function
mm_reduce_vector_v1. So using this function leads to a substantial speedup when computing in the 2-local subgroups \(N_x\) or \(G_{x0}\) of the Monster. The user profits from this speedup without effort, since functionmm_reduce_Mcalls functionmm_reduce_vector_shortenwhen appropriate.Here the original element \(g\) of the Monster to be reduced must be stored in the buffer
aof lengthnas usual. Parametersrandworkare as in functionmm_reduce_vector_v1.If function
mm_reduce_vector_shortenreturns a negative value then we may retry the final reduction of \(g\) with one of the functionsmm_reduce_vector_v1ormm_reduce_vector_v1_mod3.
-
int32_t mm_reduce_vector_incomplete(uint32_t *r)
Step finish incomplete reduction of an element of the monster.
This function should be applied immediately after function
mm_reduce_vector_vpor after functionmm_reduce_vector_vn.The function outputs the word already stored in the buffer
rcomputed by the functionsmm_reduce_vector_vpand, possibly,mm_reduce_vector_vnand returns the length of the data in bufferr. Here we assume that subsequent calls to the functions in the sequencemm_reduce_vector_vp, mm_reduce_vector_vn, mm_reduce_vector_v1,that have not yet been called, would contribute nothing the the output assembled in buffer
r.The buffer referred by
rshould have length at least 128.A negative return value indicates a fatal error.
More details are yet to be documented!!!!
-
int32_t mm_reduce_M(uint32_t *a, uint32_t n, uint32_t mode, uint32_t *r)
Reduce an element in the monster group.
This is the most important function in the project. It reduces an arbitrary element \(g\) of the monster to an element \(h\). The value of the element \(h\) depends on the value of \(g\) as an element of the monster group, but not of the representation of \(g\).
Let \(g\) be the element of the monster given as a word of generators in the buffer
aof lengthn. Then the function computes the reduced element \(h\) of the monster with \(g = h\). We use the method in [Sey22] for computing \(h\).The function stores \(h\) as a word of generators in the array
ras described in the header of this file and returns the length of this word.A negative return value indicates a fatal error.
The buffer referred by
rshould have length at least 128.Parameter
modeshould usually be set to zero. It is interpreted as follows:If bit 0 of
modeis set then the reduction is strictly compatible with the reduction process described in [Sey22]. Otherwise we perform a more practical reduction. The latter reduction ensures e.g. that an element of the subgroup \(G_{x0}\) is always represented as a word in the generators of that subgroup. This feature greatly accelerates computations in the subgroup \(G_{x0}\).Bit 1 of
modeshould be set for tests only. If this bit is set then we omit some simplifications of the input prior to the actual reduction.
-
uint32_t mm_reduce_set_order_vector_mod15(uint32_t mode)
Set a special reduction mode for tests.
The end user need not call this function.
In [Sey22] we show how to compute an ‘order vector’ \(v_1\) in the representation \(\rho_{15}\) of the Monster satisfying the following property:
The only element of the Monster fixing \(v_1\) is the neutral element of the Monster.
For verifying this property of \(v_1\) is suffices to use the methods in [LPWW98]. Thus by tracing the an image of \(v_1\) under an element \(g\) back to its preimage \(v_1\) we obtain a verification of a reduction process which depends on classical results only.
By default, the main reduction function
mm_reduce_Min this module uses an ‘order vector’ in \(\rho_3\) which leads to a faster reduction process than obtained by using \(v_1\).When calling function
mm_reduce_set_order_vector_mod15with parametermode = 1then in all subsequent calls to functionmm_reduce_Mwe will use an ‘order vector’ \(v_1\) in \(\rho_{15}\) as desrcibed above; and we will verify that the ‘reduced’ form of an element \(g\) of the Monster maps \(v_1\) to the same vector as the original element \(g\) does.This gives a tester the capability to do long calcuations in the Monster group that will be verified by using classical results without referring to the theory developed in [Sey22].
The user may switch back to the default behaviour by calling function
mm_reduce_set_order_vector_mod15with parametermode = 0. The function returns the value of parametermodepassed in the previous call (or the default value 0 at first call).
C interface for file mm_shorten.c
This file contains function for reducing a word of generators of the Monster group. Here word reduction is done by computations in the subgroups \(G_{x0} = 2^{1+24}.\mbox{Co}_1\) and \(N_0 = 2^{2+11+22}.(\mbox{Mat}_{24} \times \mbox{Sym}_3)\). To some extent, we will also compute in the Frobenius group of order 21 generated by the generators \(\tau\) and \(\xi\) of the Monster.
Internally, we store a word a of generators of the Monster in a structure of type gt_word_type. Here the word a is split into subwords, where each subword is in the double coset \(G_{x0} N_0\). Such a subword is represented as a word of generators of \(G_{x0}\), followed by a power of the triality element \(\xi\). A subword is stored in a structure of type gt_subword_type.
Unless otherwise stated, a negative return value of a function is this module indicates an error.
Structures required for this module are defined in file mm_reduce.h.
The following code block demonstrates the reduction of a word with the functions in this module (ignoring error handling).
// Assume that the following buffer contains a word ``g``
// of length 10 of generators of the Monster group
#define INPUT_LENGTH 10
uint32_t in_buf[INPUT_LENGTH];
// Declare a sufficiently long output buffer
#define MAX_OUTPUT_LENGTH 20
uint32_t out_buf[MAX_OUTPUT_LENGTH];
// Define a reduction mode as specified in function gt_word_alloc
#define REDUCTION_MODE 1
// Allocate a structure for reduction
gt_word_type* p_gt = gt_word_alloc(REDUCTION_MODE, NULL, 0);
// Enter the word ``g`` into that structure
gt_word_append(p_gt, in_buf, INPUT_LENGTH);
// Reduce the word in that structure
gt_word_reduce(p_gt);
// Store the reduced word in the output buffer and the actual
// length of that word in variable output_length
int32_t output_length;
output_length = gt_word_store(p_gt, out_buf, MAX_OUTPUT_LENGTH);
// Free the allocated structure
gt_word_free(p_gt);
Functions
-
void gt_subword_clear(gt_subword_type *p_gtsub)
Low-level function.
Set a subword to the empty subword.
-
gt_word_type *gt_word_alloc(uint32_t mode, void *p_buffer, size_t nbytes)
Create a structure of type
gt_word_typeThis function creates a valid structure of type
gt_word_typeand returns a pointer to that structure. The returned structure contains the empty word of generators of the Monster. If a bufferp_bufferofnbytesbytes length is given as a parameter then the structure may be ininitalized inside this buffer. We recommendnbytes >= 4096.If
p_buffer = NULLornbytesis too small then a buffer is allocated via the C functionmalloc. You should always use the returned pointer as a pointer to a valid structure of typegt_word_typecontaining the neutral element of the Monster.The structure referred by returned pointer will contain the circular doubly linked list with a single entry of type
gt_subword_type. This entry is an end-of-file mark. So the whole word stored in that structure corresponds to the neutral element of the Monster group.In any case function
gt_word_freemust be called to free all buffers allocated by this function and, possibly, by other function in this module applied to the pointer returned by this function.Parameter
modespecifies the reduction mode:mode = 0means no reduction. Here the user has to apply the low-level functions in this module to perform reduction. This mode is used for testing.mode = 1means the maximum possible reduction which is supported.mode = 2means a lazy mode of reduction. The idea is to reduce only in cases where we can expect a substantial decrease of the word length. This mode is faster thanmode = 1.This function returns
NULLin case of failure, e.g. if the C functionmallocfails to allocate memory.
-
void gt_word_free(gt_word_type *p_gt)
Free a structure of type
gt_word_typeThis function frees the memory allocated to a structure of type
gt_word_typecreated by functiongt_word_alloc. Ultimately, it must be applied to all pointers created by functiongt_word_allocin order to avoid memory leaks. It is safe to apply functiongt_word_freeto theNULLpointer.
-
void gt_word_clear(gt_word_type *p_gt)
Set content of the structure
*p_gtto the empty word.This function sets the value of the structure of type
gt_word_typereferred byp_gtto the neutral element of the Monster. It also frees all allocated memory blocks referred byp_gt, except for the blockp_gtitself.
-
int32_t gt_word_insert(gt_word_type *p_gt)
Low-level function.
Insert an empty subword after the current subword pf
*p_gtand set the position of the current subword to the new subword.Return a negative value if out of memory.
-
int32_t gt_word_delete(gt_word_type *p_gt)
Low-level function.
Delete the current subword, and set the position of the current subword to its predecessor.
Return a negative value on an attempt to delete an EOF mark.
-
int32_t gt_word_seek(gt_word_type *p_gt, int32_t pos, uint32_t set)
Low-level function.
Move the pointer to the current subword to position ‘pos’ Her pos = 0 means the EOF mark if ‘set’ is True, and the position of the current subword otherwise. pos = i+1 means the subword after pos = i, pos = i-1 means node subword pos = i.
It is an error to move p_gt->p_node across the EOF node. When starting at the EOF node we may move forward or back until finding the EOF node once again, but not any further.
-
int32_t gt_word_append_sub_part(gt_word_type *p_gt, uint32_t *a, uint32_t n)
Low-level function.
Try to append a prefix of word ‘a’ of length ‘n’ to the current subword. Return number of atoms of ‘a’ sucessfully appended to that word. A negative return value inducates an error.
-
int32_t gt_word_reduce_sub(gt_word_type *p_gt, uint32_t sub_mode)
Low-level function.
Reduce current subword
sub_mode = 0: lazy reduction (just some word shortening)
sub_mode = 1: standard reduction
sub_mode = 2: as sub_mode 0, but move also prefix in N_x0 to previous subword
sub_mode = 3: as sub_mode 1, but move also prefix in N_x0 to previous subword
-
int32_t gt_word_rule_join(gt_word_type *p_gt)
Low-level reduction function.
Try to join current subwort
p_gt->p_nodewith its predecessor. Return 1 and letp_gt->p_nodepoint to first node being changed if the rule could be applied. Return 0 and do not changep_gt->p_nodethis is not the case. Return a negative number in case of a fatal error.
-
int32_t gt_word_rule_t_xi_t(gt_word_type *p_gt)
Low-level reduction function.
This function tries to apply a reduction rule:
\(\tau^{e_1} \xi^{e_2} \tau^{e_3} \rightarrow \xi^{e_4} \tau^{e_5} \xi^{e_6}\).
Such a rule exists for all \(0 < e_1, e_2, e_3 < 3\). This rule is applied to the subword
p_gt->p_nodeand to its predecessor. Applying such a rule decreases the number of generators \(\tau^{\pm 1}\) in a word.The function returns 1 and lets
p_gt->p_nodepoint to first node being changed if such rule could be applied. It returns 0 and does not changep_gt->p_nodethis is not the case. It returns a negative number in case of a fatal error.To show the existence of suitable reduction rules as mentioned above we put \(a = \tau \xi^{-1}\). Then we verify that \(a\) has order 7 and that \(\tau^{-1} a \tau = a^2\) holds. Therefore is suffices to verify that the group operations corresponding to these relations fix the ‘order vector’ in the representation \(\rho_{15}\) .
Since \(\tau\) has order 3, the group generated by \(\tau\) and \(a\) (and hence also the group generated by \(\tau\) and \(\xi\)) is visibly a Frobenius group of order 21. Finding suitable reduction rules in such a group is easy.
-
int32_t gt_word_append(gt_word_type *p_gt, uint32_t *a, uint32_t n)
Append word of generators to strcture
*p_gtAppend the word
aof lengthnto the word in the buffer refered byp_gt.A negative return value inducates an error.
At exit, pointer
p_gt->p_nodewill point to theEOFmark.
-
uint32_t gt_word_n_subwords(uint32_t *a, uint32_t n)
Return number of subwords required to store element of the Monster.
Return (an upper bound for) the number of subwords in a doubly linked list of type
gt_word_typerequired to store the word of generators of the Monster of lengthnreferred bya.
-
int32_t gt_word_length(gt_word_type *p_gt)
Return the length of the word stored in
*p_gt.
-
int32_t gt_word_reduce(gt_word_type *p_gt)
Reduce the word stored in
*p_gt.The function reduces the word \(g\) stored in the structure
*p_gt. The mode of reduction depends on the parametermodepassed to functiongt_word_allocwhen creating that structure. The function returns:0 if \(g\) is not known to be in any subgroup of the Monster
4 if \(g\) is known to be in \(G_{x0} \cdot N_0\)
5 if \(g\) is known to be in \(N_0\)
6 if \(g\) is known to be in \(G_{x0}\)
7 if \(g\) is known to be in \(N_{x0} = G_{x0} \cap N_0\)
A negative value in case of failure.
If the return value is > 0 (i.e. if we know \(g \in G_{x0} \cdot N_0\)) then we also have performed a full reduction of the result.
-
int32_t gt_word_store(gt_word_type *p_gt, uint32_t *pa, uint32_t maxlen)
Store the word in
*p_gtin an array.The function stores the word in
*p_gtin the arraya(of lengthmaxlen) referred bypa. It returns the actual lengthnof the word stored in the arraya.The function returns a negative value in case of failure, e.g. if
n > maxlen.
-
int32_t gt_word_to_mm_compress(gt_word_type *p_gt, mm_compress_type *p_c)
Compress word in
*p_gtto strcuture of typemm_compress_typeYet to be tested and documented!!!
-
int32_t gt_word_compress(gt_word_type *p_gt, uint64_t *p_n)
Compress word in
*p_gtto a 256-bit integer.Yet to be tested and documented!!!
-
int32_t gt_word_shorten(uint32_t *g, uint32_t n, uint32_t *g1, uint32_t n1max, uint32_t mode)
Reduce a word of generators of the Monster group.
Let \(g\) be the word of the monster group of length
nstored in the arrayg. The function reduces the word \(g\) and stores the reduced word in the bufferg1of lengthn1max. It returns the actual lengthn1of the reduced word.Internally, the function uses a buffer of type
gt_word_typefor reduction. Parametermodecontrols the reduction mode; it is specified as in functiongt_word_alloc.The function returns a negative value in case of failure, e.g. if
n1 > n1max.
-
int32_t gt_word_pickle(gt_word_type *p_gt, uint32_t *buf, uint32_t maxlen)
Pickle data from a structure of type
gt_word_typeThe function copies the relevant data from the structure referred by
p_gtinto the linear arraybufof lengthmaxlen. It returns the actual length of buffer buf, or a negative value ifmaxlenis too short. Entries of bufferbufare organized as follows:0: component
reduce_modeof the strcture1: number N of records in the buffer
2 + i: start index of the i-th record in the buffer, 0 <= i < N
The entries of a record (inside the buffer) are organized as follows.
0: 1 if this record is marked as the current reocord, 0 otherwise
1: image of \(\Omega\) under the element \(g \in G_{x0}\) stored in this record
2: Exponent \(e\) of the trailing element \(\tau^e\) stored in this record
3: 1 if element \(g\) in this record is reduced, 0 otherwise
4: Length n of element \(g\) in this record
5 .. n+4: data for element \(g\) in this record
The required buffer length is obtained by calling function
gt_word_len_picklewith parameterp_gt.
-
int32_t gt_word_len_pickle(gt_word_type *p_gt)
Length of buffer required for function
gt_word_pickle
C interface for file mm_compress.c
This file contains functions for compressing a word of generators of the Monster group to an integer.
We describe the decoding of an integer n to a word of generators of the Monster.
The phrase “Store i input bits in k” means: Store the lower i bits of the input n to k, and put n = n >> i.
The phrase “Append entry (‘t’, x)” means: Append an entry with tag ‘t’ and value x to the output word representing an element of the Monster. Tags are as in Section The Monster group in the API reference. Initially, the output word is empty.
Store 28 input bits in p.
if 0 <= p < MAT24_ORDER then:
(Here MAT24_ORDER is the order of the Mathieu group M_24.)
Store 11 input bits in y, 13 input bits in x,
and 12 input bits in d.
Append entries ('y', y), ('x', x), ('d', d), ('p', p).
Abort with an error if p == y == x == d == 0.
else if p == MAT24_ORDER then:
Do nothing
else if p == MAT24_ORDER + 1 then:
Store 1 input bit in t and append entry ('t', t+1)
else:
Abort with an error.
(Here some deprecated options are still coded).
endif.
Store 23 input bits in k. Return with success if k == 0.
Otherwise append entry ('c', f(k)), where f is the
function mm_compress_expand_type4 in this module.
Repeat forever:
Store 24 input bits in k.
Return with success if k == 0.
Otherwise append entries ('t', 1 + (k & 1)), ('c', f(k >> 1)).
Function mm_compress_pc_expand_int performs this deconding algorithm. It accepts an integer of at most 255 bits length. Here an integer is encodes as an array of precisely four integers of type uint64_t with the lowest digit in array entry 0.
From the deccoding algorithm we see that not all words of generators of the Monster can be encoded. So a word must be reduced before encoding it. The functions in file mm_shorten.c peform a suitable reduction of a word. Function gt_word_to_mm_compress in that file copies a word of generators into a variable of type mm_compress_type. Then one may call function mm_compress_pc in this file for computing an integer corresponding to the compressed element.
For manually collecting generators of the Monster to be compressed, we first have do declare a variable of type mm_compress_type. Then we have to call function mm_compress_pc_init for initializing that variable. Then tags representing elements of the Monster may be appended by calling function mm_compress_pc_add_nx, mm_compress_pc_add_type4, or mm_compress_pc_add_t. The function gt_word_to_mm_compress mentioned above uses these functions for storing an element of the Monster in a variable of type mm_compress_type.
Functions
-
int32_t mm_compress_type4(uint32_t i)
Compress a type-4 vector in the Leech lattice mod 2.
This function compresses the bit vector
iin the Leech lattice mod 2 of type 4 from its natural 24-bit representation to a 23-bit unsigned integer.The function returns -1 if bit vector
iis not of type 4. Bits ofiat position 24 or higher are ignored.
-
int32_t mm_compress_expand_type4(uint32_t i)
Reverse operation of function
mm_compress_type4.So we have
mm_compress_expand_type4(mm_compress_type4(i)) == ifor0 <= i < 0x1000000, ifisatisfies the conditions stated in functionmm_compress_type4, i.e.iencodes a type-4 vector in the Leech lattice mod 2.The function returns -1 in case of an error.
-
void mm_compress_pc_init(mm_compress_type *pc)
Initialize a structure of type
mm_compress_type.Afterwards, the empty word is stored in the structure referred by
pc; and one may use functions in this module for adding words of generators of the Monster to this structure.
-
int32_t mm_compress_pc_add_nx(mm_compress_type *pc, uint32_t *m, uint32_t len)
Add word to structure of type
mm_compress_type.The function adds a word
mof lengthlenof Monster elements to a structure of type structure of typemm_compress_typereferred bypc. Heremis encoded as an array of 32-bit integers as described in filemmgroup_generators.h. Inmthe only allowd tags are'd', 'p', x', 'y'.The function returns the number of entries read from
m. I may be applied only if structurepcstores the empty word. It returns a negative value in case of failure.
-
int32_t mm_compress_pc_add_type4(mm_compress_type *pc, uint32_t c)
Add entry with tag ‘c’ to structure of type
mm_compress_type.The function adds an entry (‘c’, c) with tag ‘c’, as described in Section The Monster group in the API reference, to a structure of type
mm_compress_typereferred bypc.
-
int32_t mm_compress_pc_add_t(mm_compress_type *pc, uint32_t t)
Add entry with tag ‘t’ to structure of type
mm_compress_type.The function adds an entry (‘t’, t) with tag ‘t’, as described in Section The Monster group in the API reference, to a structure of type
mm_compress_typereferred bypc.
-
int32_t mm_compress_pc(mm_compress_type *pc, uint64_t *p_n)
Compress word in a structure of type
mm_compress_type.Here structure
pccontains a word of generators of the Monster. The function compresses that word into an unsigned integernof at most 255 bit length and storesnin the array referred byp_n. That array must have length 4. The lowest 64-bit digit ofnis stored ina_n[0]; the highest digit is is stored ina_n[3].The function returns 0 in case of success and a negative value in case of failure.
-
int32_t mm_compress_pc_expand_int(uint64_t *p_n, uint32_t *m, uint32_t l_m)
Expand compressed word of generators of the Monster.
The function expands a 255-bit unsigned integer
nto a word of generators of the Monster. The integernmust have been computed by functionmm_compress_pc; and it must be stored in the array of length 4 referred byp_nas described in that function.The expanded word of generators of the Monster will be stored in the array
mof lengthl_m. That word is encoded as an array of 32-bit integers as described in filemmgroup_generators.h.The function returns the actual length of the data in array
min case of success, and a negative value in case of failure. If the buffer formis too short then the function fails. A lengthl_m = 80is sufficent in all cases.
C interface for file mm_vector_v1_mod3.c
File mm_vector_v1_mod3 contains a precomputed vector v_1 (with entries taken modulo 3) of the representation of the Monster. Then the vector v = v_1 * g can be used for identifying an unknown element g of the subgroup \(G_{x0}\) of the Monster.
So the functions in this module are similar to those in module mm_order.c, but faster.
Vector v_1 can be obtained from Table MM_VECTOR_V1_MOD3_TABLE in this file. Function mm_order_find_Gx0_via_v1_mod3 computes the group element g**-1 from a vector v = v_1 * g in the representation \(\rho_3\) of the Monster. Vector v must be given as in the description of the mmgroup.mm_op extension. The element g**-1 is returned as a word of generators as described in file mmgroup_generators.h. It is encoded so that inversion of it with function mm_group_invert_word leads to a short encoding of element g.
For future extensions, we want to separate the access to the vector v from the calculations required to obtain g. It would be natural to use coroutines for implementing this concept, as in the Python module mmgroup.dev.mm_reduce.vector_v1_mod3; but coroutines are not available in C. So we use a state machine instead. Here the state is stored in a structure of type mm_order_find_Gx0_type. Function mm_order_find_Gx0_v1_mod3_state performs the action of the state machine. The user has to enter data obtained from vector v into the state machine.
The implementation of function mm_order_find_Gx0_via_v1_mod3 is the basic reference for using the state machine. The following code sample briefly describes the operation of the state machine.
// Input is a vector v = v_1 * g in the representation of the Monster
// mod 3. Output is the inverse g**-1 of g given as a word of
// generators.
// Initialize structure for state machine
mm_order_find_Gx0_type s;
mm_order_find_Gx0_v1_mod3_state(&s, 0);
// Compute the kernel of part 'A' of vector v. That kernel is of
// dimension 1 and spanned by a type-4 vector w3 in the Leech lattice
// mod 3. Convert w3 to the corresponding vector w2 of type 4 in the
// Leech lattice mod 2, using function gen_leech3to2_type4().
// Store w2 in s.data[0].
mm_order_find_Gx0_v1_mod3_state(&s, 1);
// Transform a copy of part 'A' of vector v with the element of G_x0
// given as a word of generators in s.data[0],...,s.data[s.length-1].
// Watermark the 24 rows of the transformed part 'A' as described
// below, and store the watermarks in s.data[0],...,s.data[23].
mm_order_find_Gx0_v1_mod3_state(&s, 2);
// Here entries s.data[0],...,s.data[s.length-1] describe entries of
// the transformed part 'A' computed in the previous step. Replace
// entry s.data[i] by the corresponding entry of the transformed part.
mm_order_find_Gx0_v1_mod3_state(&s, 3);
// Here entries s.data[0],...,s.data[s.length-1] describe entries of
// the input vector v in *sparse representation*. Replace each entry
// s.data[i] by the corresponding entry of input vector v.
mm_order_find_Gx0_v1_mod3_state(&s, 4);
// Same action as in previous step
mm_order_find_Gx0_v1_mod3_state(&s, 5);
// Now g**-1 is available as a word of generators in
// s.data[0],...,s.data[s.length-1]
Remarks
Part ‘A’ of vector v has a natural interpretation of a 24 times 24 matrix acting on the Leech lattice mod 3.
Watermark of row i is a pair (d, w), where d is the value of the diagonal entry of the row; and w is the weight of the row, i.e. the number of its nonzero entries. Here we have to store 0x100 * d + w in s.data[i]. This watermarking is coarser than the corresponding watermarking in [Sey22], Section 6. But it still allows us to identify a sufficient number of rows of matrix ‘A’. A value d = 3 is interpreted as d = 0.
Indices of entries of v or of the transformed part A in s.data are given in sparse representation.
Functions
-
void mm_order_load_vector_v1_mod3(uint_mmv_t *p_dest)
Load order vector from tables to a buffer.
The function stores the precomputed vector
v_1(mod 3) into the array referred byp_dest. That array must must be sufficiently long to store a vector of the representation \(\rho_{3}\).
-
int32_t mm_order_compare_v1_mod3(uint_mmv_t *v)
Compare vector with precomputed order vector.
The function compares the vector \(v\) in the representation \(\rho_{3}\) of the monster group referred by
vwith the precomputed vectorv_1.The function returns 0 in case of equality and 1 otherwise. It destroys the vector in the buffer
v.
-
int32_t mm_order_find_Gx0_v1_mod3_state(mm_order_find_Gx0_type *st, int32_t state)
State machine for finding an element of the group \(G_{x0}\).
The operation of the state machine is documented in the header of this file.
-
void mm_order_find_Gx0_v1_mod3_init(mm_order_find_Gx0_type *st, mm_order_data_Gx0_type *pdata)
Initialize state machine for a different vector
v_1In case
pdata == NULLthis function is equivalent tomm_order_find_Gx0_v1_mod3_state(st, 0). In future extensions, the same calculation as in the state machine operated by functionmm_order_find_Gx0_v1_mod3_statemay also be performed for a vectorv_2instead of a vectorv_1. Then the user must callmm_order_find_Gx0_v1_mod3_init(st, &data)instead of ofmm_order_find_Gx0_v1_mod3_state(st, 0)for initializing the state machine. Heredatamust be a structure of typemm_order_data_Gx0_typethat is suitable for dealing withv_2instead ofv_1.
-
int32_t mm_order_find_Gx0_via_v1_mod3(uint_mmv_t *v, uint32_t *g)
Find an element \(g\) of the group \(G_{x0}\).
The function computes the element
g**-1of the subgroup \(G_{x0}\) of the Monster from a vectorv = v_1 * g. Herev_1is as described in the header of this file. Vectorvmust be given as a vector in the representation \(\rho_3\) of the Monster as in the description of themmgroup.mm_opextension. The elementg**-1is returned as a word of generators in the arraygas described in filemmgroup_generators.h. The function returns the length of elementg**-1in case of success, and a negative value in case failure.Buffer
gmust have length at least 10.
Variables
-
static mm_order_data_Gx0_type ORDER_DATA_STD = {{0}, {0, 0}}
-
const uint32_t MM_VECTOR_V1_MOD3_TABLE[]
Table containing the fixed vector \(v_1\).
The image \(v_1 \cdot g\) of a fixed vector \(v_1\) in the representation \(\rho\) of the Monster under the action of an element \(g\) of \(G_{x0}\) can be used to determine \(g\). The functions in this module support the computation of \(g\) from \(v_1 \cdot g\). Here it suffices to know the entries of \(v_1\) and of \(v_1 \cdot g\) modulo 3.
The following table contains a suitable vector \(v_1\) in sparse representation, preceded by a length indicator. Thus the length
nof that representation is stored in entry 0 of the table, and the sparse representation of \(v_1\) is stored in entries 1,…,n.
C interface for file mm_profile_abc_mod3.c
Basic operation of this module
The centralizer of the fourgroup \(V_4 = \{1, x_{-1}, x_{\Omega}, x_{-\Omega}\}\) in the Monster is a group \(N_{xyz}\) of structure \(2^{2+11+22}.M_{24}\). Let \(N_2 := O_2(N_{xyz})\) be the normal subgroup of \(N_{xyz}\) of structure \(2^{2+11+22}\). Let \(\rho_3\) be the standard 196884-dimensional rational representation \(\rho\) of the Monster with entries taken modulo 3. We mainly deal with vectors \(v \in \rho_3\) as that are 2A axes. The purpose of this module is to watermark the orbits of 2A axes under the action of the group \(N_{xyz}\). We may also watermark orbits under the action of a few specific subgroups of \(N_{xyz}\).
Given a vector \(v\) as above, the functions in this module first compute a symmetric \(24 \times 24\) matrix \(M = M(v)\) that is invariant under the centralizer of \(v\) in \(N_{xyz}\), and also under \(N_2\). Here the factor group \(M_{24} = N_{xyz} / N_2\) acts naturally on the space of symmetric \(24 \times 24\) matrices as a permutation group. As a first step, information from the parts ‘A’, ‘B’, ‘C’ of a vector \(v \in \rho_3\) is used to obtain \(M(v)\). These parts of a vector are described in Section The representation of the Monster group in the API reference. Note that these parts are already symmetric \(24 \times 24\) matrices. The group \(N_{2}\) acts on the triple (‘A’, ‘B’ + ‘C’, ‘B’ - ‘C’) by sign changes; and the factor group \(M_{24}\) acts on each entry of that triple naturally as a permutation group on 24 elements, up to sign. By stripping off sign information and merging the corresponing entries of these matrices we obtain a first approximation \(M_0 = M_0(v)\) of \(M(v)\) that is invariant under \(N_{2}\). By construction, \(M_0(v)\) is also invariant under the centralizer of \(v\).
Matrix \(M_0\) can be considered as an undirected labelled graph, with vertices labelled by the diagonal elements and edges labelled by off-diagonal elements of \(M_0\). We may refine the labelling of \(M_0\) by assigning a new label to each orbit of a vertex or edge under the action of the isomorphism group of the labelled graph corresponding to \(M_0\). The matrix with such a refined labelling is still invariant under the action of the centralizer of \(v\). Computing the full isomorphism group of the graph would take too much time; but we may do a few steps in that direction in order to refine the watermarking. This way we compute a matrix \(M = M(v)\) that refines the labelling given by \(M_0\).
From \(M(v)\) we also want to compute a data structure \(H = H(v)\) that watermarks the orbit of \(v\) under the action of \(N_{xyz}\). For a suitably refined labelled graph \(M(v)\) we may assume that the multiset of labels of all edges incident to a vertex depends on the label of the vertex only. So the multiset of labels of the vertices can be used as a watermark for the orbit of \(v\). It turns out that this multiset can be stored in a \(24 \times 24\) matrix. Some details of this construction are given in the documentation of file mm_profile_graph24.c.
Function mm_profile_mod3_load computes the triple (‘A’, ‘B’ + ‘C’, ‘B’ - ‘C’) from the vector \(v\) of the representation of the Monster. Function mm_profile_mod3_hash computes the matrices \(M(v)\) and \(H(v)\) from that triple. It also computes a 63-bit hash value over the matrix \(H(v)\).
Extensions
From \(v\) we may compute \(M(w)\) and \(H(w)\) for \(w = v \cdot \tau^e x_\delta^f\), for any odd cocode element \(x_\delta\), without computing \(w\). (These matrices are invariant under \(x_\delta\) for \(\delta\) even). Here the arguments \(e\) and \(f\) are passed to function mm_profile_mod3_load.
We may also watermark orbits of \(v\) under the action of a few fixed subgroups \(N'\) of \(N_{xyz}\). Parameter mode of function mm_profile_mod3_hash allows to specify a subgroup \(N'\) of \(N_{xyz}\), such that the computed matrix M will be invariant under the centralizer of \(v\) in \(N'\) only. Here \(N'\) is the subgroup of \(N\) centralizing a set \(\{x_\delta \mid \delta \in S\}\) of 2A involutions pointwise, where \(S\) is a set of Golay cocode words depending of parameter mode. Legal values for mode are:
mode |
\(N'\) centralizes \(\{x_\delta \mid \delta \in S\}\) |
|---|---|
0 |
\(S = \{ \}\), i.e. \(N' = N_{xyz}\) |
1 |
\(S = \{ [2,3] \}\) |
2 |
\(S = \{ [1,2], [2,3] \}\) |
Warning
The functions in this module may differ between versions!
They are desigend for the internal needs of the mmgroup package.
Functions
-
int32_t mm_profile_mod3_load(uint32_t p, uint_mmv_t *v, uint64_t *a, uint32_t t)
Load parts of a representation representation of the Monster.
Let
vpoint to a vector of the representation \(\rho_{p}\) of the Monster, with \(p\) given by parameterp. The function loads the triple of the parts (‘A’, ‘B+C’, ‘B-C’) of that vector into the array of length 72 referred bya, as described in the header of this file. The function returns 0 in case of success and -1 in case of failure. Legal values for \(p\) are 3 and 15.A nonzero value
tis interpreted as follows:Before loading the vector
v, multiply it with \(\tau^f\), where \(f\) is(t / 2) & 3. Iftis odd then multiplyvwith \(x_\delta\) afterwards, where \(\delta\) is any odd Golay cocode element. All these multiplications are done internally, without changing the input vectorv.
-
int64_t mm_profile_mod3_hash(uint64_t *a, uint16_t *b, uint32_t mode)
Watermark orbit of a vector in the representation of the Monster.
Let
arefer to an array of length 72 containing the output of functionmm_profile_mod3_load. That output is a triple of the parts (‘A’, ‘B+C’, ‘B-C’) of a vector \(v\) in the representation of the Monster (modulo 3), as described in the documentation in the header of this file.From this input the function computes the matrices
MandH, as described in the header of this file. The function returns a 63-bit hash value of matrixHin case of success and a negative value in case of failure. The matrixHand its hash value may be used to watermark the orbit of \(v\) under the action of the group \(N_{xyz}\).Output array
bmust have size 2 * 24 * 24. Entryi, jof matrixMis stored inb[24 * i + j]. Entryi, jof matrixHis stored inb[24*24 + 24 * i + j].If is
modeis zero then the computed matrixHwatermarks the orbit of \(v\) under the action of \(N_{xyz}\). In casemode = 1, 2the matrixHwatermarks the orbit of \(v\) under the action of a subgroup of \(N_{xyz}\), as described in the header of this file.
-
int32_t mm_profile_mod3_permute24(uint16_t *b, uint8_t *p, uint16_t *b1)
Permute rows and columns 24 times 24 matrix.
Permute the rows and columns of the 24 times 24 matrix
bwith permutationpand store result in bufferb1. Entryi, jof a matrix is stored at index24 * i + j. Buffersbandb1have size 24 * 24; these buffers may overlap.The function returns 0 in case of success and a negative value in case of failure, e.g. if
pis not a legal permutation.
C interface for file mm_profile_graph24.c
Functions exported from this module
The function mm_profile_graph24 exported by this file is an auxiliary funtion of function mm_profile_mod3_hash in file mm_profile_abc_mod3.c.
Basic operation of this module
Here we assume that the Mathieu group \(M_{24}\) (as a subgroup of the symmetric permutation group \(S_{24}\)) acts naturally on the space of symmetric \(24 \times 24\) matrices by a permutation of the rows and the columns of such a matrix. Let \(A\) be a symmetric \(24 \times 24\) matrix. We want to watermark the orbit of \(A\) under the action of \(M_{24}\), or at least of \(S_{24}\). The current version in this file deals with \(S_{24}\) only. Such a symmtric matrix \(A\) occurs e.g. when dealing with 2A axes in the representation of the Monster.
Therefore we consider matrix \(A\) as an undirected labelled graph, with vertices labelled by the diagonal elements and edges labelled by off-diagonal elements of \(A\). Let \(C_S(A)\) be the isomorphism group of \(A\) under the action of \(S_{24}\). Then \(C_S(A)\) is the isomrhism group of the labelled graph corrsponding to \(A\). We may refine the given labelling of \(A\) in a suitable way by assigning new labels without changing \(C_S(A)\). E.g. we may augment the label of a vertex with information about the labels of the edges incident with that vertex, and vice versa. In priciple, the process may be iterated; but this will take too much time. For our purposes we first augment the labels of the edges with the labels of the incident vertices. Then we augment the labels of the vertices with the labels of the incident edges, and stop the process afterwards. This way we compute a matrix \(B = B(A)\) that refines the labelling given by \(A\). Details are out of the scope of this documentation; but one may check the documentation of the subfunctions in this module for more information.
We use a two-dimensional array of 16-bit integers of shape (24, 24) to store the matrices \(A\) and \(B\). The original labels of matrix \(A\) are stored in the lower 6 bits of the entries. Matrix \(B\) is obained from \(A\) by refining the labels corresponding to the original entries of \(A\). In matrix \(B\) the original entry taken from \(A\) is stored in the lower 6 bits of an entry; and the refined part of a label is stored in the upper 10 bits of an entry.
From \(B\) we also want to compute a data structure \(H = H(B)\) that watermarks the orbit of \(B\) under the action of \(C_S(A)\). Therefore we first sort the entries each row of \(B\) separately, putting the diagonal entry of each row at the first place. Then we sort the rows. The sorted matrix \(H\) depends on the orbit of \(B\) under \(S_{24}\) only. Also, by construction, it depends on the orbit of \(A\) under \(S_{24}\) only. Our construction also ensures that renaming the labels in \(A\) leads to a renaming of the labels in \(H\). The keys used for sorting in the computation of matrix \(H\) are implementation dependent and undocumented.
Warning
The functions in this module may differ between versions!
They are desigend for the internal needs of the mmgroup package.
Functions
-
void mm_profile_graph24(uint16_t *b)
Watermark orbit of a symmetric \(24 \times 24\) matrix.
Let \(A\) be a symmetric \(24 \times 24\) matrix. We compute a (usually non-symmetric) \(24 \times 24\) matrix \(H\) that watermarks the orbit of matrix \(A\) under the action of the symmetric permutation group \(S_{24}\). Here \(S_{24}\) naturally by permuting the rows and columns of a symmetric matrix.
For this purpose it is natural to consider the entries of matrix \(H\) as labels. Before computing \(H\), we first compute a matrix \(B\) containing a refinement of the labelling given by matrix \(A\) as described in the comment at the beginning of this file. We compute \(B\) from \(A\) in place. Here we do not change the lower 6 bits of an entry of \(A\). The upper bits of an entry will contain a refinement of an original lable. Such upper bit in matrix \(A\) will be considered, but may be changed.
Buffer
bmust have size2 * 24 * 24. Entry(i,j)of matrix \(A\), and also of the output matrix \(B\), is stored inb[24*i + j]. Entry(i,j)of the output matrix \(H\) is stored inb[24*24 + 24*i + j].