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_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.Generate a sequence of statements that replaces
v1by the bit parity ofv1 & 0xfff.
-
mat24_def_octad_to_gcode(o)
Eqivalent to
mat24_def_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_def_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_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.
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_2
C functions for the Mathieu group \(M_{24}\)
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_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, parameter
u_tetradmust satisfy0 <= u_tetrad < 24; otherwise the function fails.The function returns
(uint32_t)(-1)in case of failure.
-
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_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_suboctad_to_cocode(uint32_t u_sub, uint32_t v1)
Convert even suboctad of octad to cocode representation.
The function converts a suboctad
u_sub(insuboctadrepresentation) of an octadv1(ingcoderepresentation) to a cocode element. It returns that cocode element incocoderepresentation.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 natural order. 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 with its complement.The function returns the suboctad of
v1with numberu_subincocoderepresentation. Octadv1must be given ingcoderepresentation. Ifv1is a complement of an octadotheois taken instead ofv1.The function fails if
v1does not represent an octad. It returns(uint32_t)(-1)in case of failure.
-
uint32_t mat24_cocode_to_suboctad(uint32_t c1, uint32_t v1)
Convert cocode element
c1to suboctad of octadv1The function converts a cocode element
c1(incocoderepresentation) of an octadv1(ingcoderepresentation) to a suboctad.This is an inverse of function mat24_suboctad_to_cocode(). The function returns the suboctad number corresponding to the cocode element
c1, ifv1is an octad andc1is an even subset ofv1. See documentation of function mat24_suboctad_to_cocode() for the numbering of the suboctads.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. The function returns(uint32_t)(-1)in case of failure.
-
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 mapsh1to `h2.Caution:
Some input mappings allow several output permutations. Changing the specification of this function such that the same input leads to a different output permutation destroys the interoperability between different versions of the project!!
-
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_cocode_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().
Variables
-
const uint16_t MAT24_OCT_DEC_TABLE[759]
Table for converting
octadtogcoderepresentation.The public macro
mat24_def_octad_to_gcodeuses this table
-
const uint8_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.
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 sets all bits inu_modecorresponding to groups containing \(H\). Furthermore, the function clears all unused bits in parameteru_mode.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
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 elementsx1andx2of \(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 powerx1**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 vectorsx1andx2in 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. The element \(q_0\) and its image under \(g\) 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\).
Parameter \({q_0}\) and the result are given Leech lattice encoding.
-
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
a[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 ofathat 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_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
-
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_union_find.c
The functions in file gen_union_find.c implement a union-find algorithm. This may be used e.g. for computing the orbits of the Leech lattice mod 2 under the action of a group.
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.
-
void 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.
-
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.
-
int32_t gen_ufind_partition(uint32_t *table, uint32_t length, uint32_t *ind, uint32_t len_ind)
Output the partition computed by 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.We assume that the partition stored in the array
tablecontainsn_setssets. Then we overwrite the arraytablewith a list of lists, where each list corresponds to a set in the partition. We write some index infomation for interpreting these lists into the arrayindof lengthlen_ind.Array
tablewill contain thelengthelements of the setS(length)in such a way that for0 <= i < n_setsthei-th set in the partition is equal to the set of integers given bytable[ind[i]], ..., table[ind[i+1] - 1].So the array
indmust have size at leastn_sets + 1; i.e. we must havelen_ind > n_sets. Functiongen_ufind_find_all_minmust be called beford calling this function. Note that functiongen_ufind_find_all_minreturnsn_setsin case of success.The entries
table[ind[i]], ..., table[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.
-
void gen_ufind_union_affine(uint32_t *table, uint32_t length, uint32_t *m, uint32_t len_m, uint32_t v)
Perform affine union operations in 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.In this function the entries of
S(length)are interpreted as bit vectors. The function joins the set containingiwith the set containgi * M + vfor alli. HereMthe bit matrix over GF(2) referred bymwithlen_mrows, andva bit vector. All bit vector arithmetic is done over GF(2).
-
int32_t gen_ufind_union_leech2(uint32_t *table, uint32_t *g, uint32_t len_g)
Join orbits of the Leech lattice mod 2.
The Conway group \(\mbox{Co}_1\) has a natural action on on \(\Lambda / 2 \Lambda\), i.e. on the Leech lattice mod 2. The subgroup \(G_{x0}\) of the Monster (of structure \(2^{1+24}.\mbox{Co}_1\)) has the same action on on \(\Lambda / 2 \Lambda\).
In this function we assume that the array
tablecontains a partition of the set \(\{i \mid 0 \leq i < 2^{24}\}\) as described in functiongen_ufind_init. In that function the arraytableshould have been initialized with a length of \(2^{24}\).Here each integer \(i\) is interpreted as an element of \(\Lambda / 2 \Lambda\) in Leech lattice encoding, as described in the document The C interface of the mmgroup project, section Description of the mmgroup.generators extension.
Let \(g \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\) is given as a word of generators of lengthlen_gin the arrayg. Each atom of the word \(g\) is encoded as defined in the header filemmgroup_generators.h.Then the function joins the set containing \(i\) with the set containing \(i \cdot g\) for all \(i\), using the union-find algorithm.
The function returns 0 in case of success and a negative value in case of failure (e.g. if \(g\) is not in \(G_{x0}\)).
C functions for the generator \(\xi\) of the monster group
The functions in module gen_xi_functions.c 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. \(G_{x0}\) operates on its normal subgroup \(Q_{x0}\) of of structure \(2^{1+24}\) by conjugation as described in the Guide, section Computations in the Leech lattice modulo 2. \(Q_{x0}\) is extraspecial and has center \(\{\pm1\}\). We have \(Q_{x0} / \{\pm 1\} \cong \Lambda / 2 \Lambda\). An element \(x\) of \(Q_{x0}\) is short if it corresponds to a vector in the Leech lattice \(\Lambda\) of norm 4. \(G_{x0}\) also operates on the \(2 \cdot 98280\) short elements of \(Q_{x0}\).
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}\). So the basis vectors of \(98280_x\) (together with their opposite vectors) can be identified with the short elements of \(Q_{x0}\).
The functions in module gen_xi_functions.c are also used for
computing tables describing the monomial operation of
\(\xi^e, e=1,2\) on \(98280_x\).
Module mmgroup.dev.generators.gen_xi_ref is a pure python
substitute for this set of C functions; but calculating the tables
with python takes a rather long time.
In section The representation of the Monster group we use the following names and tags for the basis vectors of \(98280_x\).
Name
Tag
Entries
Remarks
\(X^+_{ij}\)
B
i, j; 0 <= j < i < 24
\(X_{ij}\)
C
i, j; 0 <= j < i < 24
\(X_{o,s}\)
T
o, s; 0 <= o < 759, 0 <= s < 64
\(X_{d,j}\)
X
d, j; 0 <= d < 2**11, 0 <= j < 24
(1),(3)
Remarks
i and j, 0 <= i,j < 24 refer to basis vectors of the Boolean vector space in which the Golay code is defined.
o is one of 759 octads, s is one of 64 even subsets of octad d (modulo its complement in d), as described in section Octads and suboctads.
d with 0 <= d < 2048 refers to the Parker loop element d. For larger values d we have:
\[ \begin{align}\begin{aligned}X_{2048+k,j} = X_{k,j}, \; Y_{2048+k,j} = -Y_{k,j}, \; Z_{2048+k,j} = Z_{k,j},\\U_{4096+k,j} = -U_{k,j}, \quad \mbox{for} \; U = X, Y, Z; \; 0 <= k < 2048 \, .\end{aligned}\end{align} \]
We group these basis vectrors into 5 boxes (labelled 1,…,5) with each box containing at most \(3 \cdot 2^{13}\) entries. Element \(\xi\) permutes these boxes as follows:
Box1 -> Box1, Box2 -> Box2, Box3 -> Box4 -> Box5 -> Box3 . (1)
The mapping from the basis vectors to entries in boxes is:
Basis vector
Box
Entry
B[i,j]
1
0 + 32 * i + j
C[i,j]
1
768 + 32 * i + j
T[o,s], o < 15
1
1536 + 64 * o + j
T[o,s], 15 <= o < 375
2
64 * (o - 15) + j
T[o,s], o >= 375
3
64 * (o - 375) + j
X[d,j], d < 1024
4
32 * d + j
X[d,j], d >= 1024
5
32 * (d - 1024) + j
This subdivision looks weird, but is has quite a few advantages:
The lower index (j or s) has stride 1, and the the stride of the higher index (i, o or d) is the lowest possible power of two. So accessing an entry is easy. In the C code for a representation derived from \(\rho\) the entries of a vector of such a representation are strided in the same way. So the tables computed in this module can be used in the C code for operator \(\xi\).
An entry in a box is always less than \(2^{15}\), so any entry can be stored in a 16-bit integer, together with a sign bit.
Boxes are permuted as above, so 4 tables of 16-bit integers and size <= \(3 \cdot 2^{15}\) are sufficent to encode the operation of \(\xi\).
We remark that boxes 3 and 5 contain the short vectors with odd Golay code words; the other boxes contain those with even code words. Here the parity (even/odd) of a Golay code word means the scalar product with the cocode word \(\omega\) which has six 1-bits in column 0 of the MOG, see [Sey20], section 2.2. Short vectors with an odd cocode element occur precisely in boxes 4 and 5.
A similar, but finer subdivision of the whole space \(\rho\) (and not only of the subspace \(98280_x\)) is given in [Iva09], section 3.4.
The operation of the generator \(\xi\) on the group \(Q_{x0}\)
Using [Sey20], Lemma 9.5, we can easily compute the values \(\xi^{-e} x \xi^e\) for all short \(x \in Q_{x0}\) and \(e = 1,2\). Here we represent an \(x \in Q_{x0}\) as a 25-bit integer in Leech lattice encoding as described above.
Let \(\mathcal{C}\) and \(\mathcal{C}^*\) be the Golay code and its cocode. In [Sey20], section 2.2 we give decompositions \(\mathcal{C} = \mathcal{G} \oplus \mathcal{H}\) and \(\mathcal{C}^* = \mathcal{G}^* \oplus \mathcal{H}^*\).
The formulas in ibid., Lemma 9.5 use auxiliary functions \(\gamma : \mathcal{G} \rightarrow \mathcal{G^*}\) and \(w_2 : \mathcal{G} \cup \mathcal{G^*} \rightarrow \mathbb{F}_2\) defined in ibid., section 3.3. Using the decompositions above, we may extend \(\gamma\) to \(\mathcal{C}\) and \(w_2\) to \(\mathcal{C} \cup \mathcal{C^*}\).
Short vector encoding of the short vectors in \(Q_{x0}\)
For each short vector in \(Q_{x0}\) we compute the number of the box and the entry in the box using the information given in (2). Then we store the vector in the lowest 19 bits of a 32-bit integer as follows:
Bit 18…16: number of the box
Bit 15: sign bit
Bit 14…0: Entry in the box
Tables for the operation of \(\xi\) and \(\xi^2\) contain the lower 16 bits of that encoding. Bits 18…16 can be reconstructed from the permutation of the boxes given by (1).
We precomute a set of tables containing \(2 \cdot 98260\) values \(\xi^{-e} x \xi^e\), where the short element \(x\) of \(Q_{x0}\) is given in Short vector encoding.
C interface for file gen_xi_functions.c
The functions in file gen_xi_function.c implement the operation of the generator \(\xi\) on the group \(Q_{x0}\).
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_rnd` or 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.
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
The subgroup G_{x0} of the Monster and the Clifford group.
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. This comprises the following C modules:{0}.
Defines
- QSTATE12_UNDEF_ROW
Marker for an undefined row index in function qstate12_row_table()
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 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.
- 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)\).
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
transpose(v) * m = xIf 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_h.
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.
- 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.
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)
Auxiliary function for function qstate12_reduce().
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.
- 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_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 function in this module are coded according the conventions in module
qstate12.c.Functions
- 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.
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.
- 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.
- 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 enrties 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.
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 differnt 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 The subgroup G_{x0} of the Monster and the Clifford group 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 The subgroup G_{x0} of the Monster and the Clifford group. 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\).
- 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_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)
Auxiliary function for function
xsp2co1_add_short_3_leechThe 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.
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)\).
- 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 transfromed 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.
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 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 represenation of the monster, for elechonization ofm, for computing the kernel ofmetc.Functions
- void 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.
- 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.
- 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 thencolstimesncolsmatrix of all accepted rowsa[i],0 <= i < ncols; and letIbe thencolstimencolsunit matrix. We left multiplyAwith a matrixTsuch thatT * A = I. ThusT = A**(-1). Technically, we perform row operations on the matrixA[:nrows]containing the firstnrowslines already accepted, such thatT * A[:rnows]is in reduced echelon form. We also perform the same row operations on the unit matrix to obtainT. We storeT[:rnows]in columns0,...,ncols-1of matrixMandT*A[:rnows]in columnsncols,...,2*ncols-1of matrixM.One may use function
leech2matrix_solve_eqnfor solving a system of linear equations obtained in that way.
- uint32_t leech2matrix_solve_eqn(uint32_t *m, uint32_t ncols, uint64_t v)
Solve a system of linear bit equations.
Let
Abe a nonsingularncolstimesncolsbit matrix stored in the arraymin the special form as described in functionleech2matrix_add_eqn.The function returns the solution
wof the equationw * A = v.Caution:
Here
mis of of typeuint32_t *, but the corresponding parameter in functionleech2matrix_add_eqnis of typeuint64_t *. This simplifies the use of this function in most pplications.
- 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
- 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; othereise 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 appeded 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
guideshould usually be zero. Ifguideis a type-4 vector in the Leech lattice mod 2 satisfying the assumptions the return valuevthen the function returnsv = guide. Otherwise parameterguideis ignored.
- 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 the return valuevthen the function returnsv = guide. Otherwise parameterguideis ignored. It is also ignored in case \(g \in Q_{x0}\).
- int32_t xsp2co1_elem_conj_G_x0_to_Q_x0(uint64_t *elem, uint32_t *a)
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.
- 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.
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..15
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-diemnsional 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 an 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_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.
-
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. Dtails 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.
-
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.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_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.
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)
Compute hash value of vector in internal.
The function returns a hash value of the vector
mvwith modulusp. It also tries to distinguish between different sparse vectors. Therefore it tries to hash over about 100 nonzero integers of typeuint_mmv_t. So ifmvis sparse then the function might have to scan considerably more zero entries.
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.
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.
Variables
-
const uint8_t MM_SUB_OCTAD_ELEMENT_TABLE[759 * 8]
For
0 <= i < 759, the entries8*i,...8*i+7in the tableMM_SUB_OCTAD_ELEMENT_TABLEare the bit positions of the octad with the numberi(in natural order).
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_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.
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
modulea 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
-
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_i. This must be one of the following:If
c_irepresents a type-4 vector in Leech lattice encoding then this encodes the element of \(G_{x0}\) computed by applying the C functiongen_leech2_reduce_type4toc_i.If
c_irepresents a type-2 vector in Leech lattice encoding then this encodes the element of \(G_{x0}\) computed by applying the C functiongen_leech2_reduce_type2toc_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
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 n, 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. A size parameterbuf_size = 128is sufficient for all cases ofn.In case
n = 0the function returns the arrayTAG_VECTORof length 97. The tag vector is documented in filemm_order.c.In case
n > 0the function returns data required for verifying the precomputed order vector \(v_1\). The order vector is discussed in [Sey22].In case
n = 1,2,3the function returns the values \(g_{71} \in \mathbb{M}, v^0_{71} \in \rho_{3}, g \in \mathbb{M} \), respecively, in the internal sparse format. With these data we can compute:\(v_{71} = \sum_{i=0}^{70} v^0_{71} \cdot g_{71}^i g\pmod{3}\).
In case
n = 4the function returns the integer \(D\) in entry 0 of the buffer. In casen = 5, 6the function returns the values \(g_{94} \in \mathbb{M}, v^0_{94}\), respectively. With this data we can compute:\(v_{94} = \sum_{i=0}^{93} (-1)^i \cdot v^0_{94} \cdot g_{94}^i \pmod{5}\).
\(v_1 = 10 \cdot v_{71} + 6 \cdot v_{94} + 5 \cdot D \cdot 1_\rho \pmod{15}\).
Here \(1_\rho\) is defined as in [Sey22]. We can also check that the order vector \(v_1\) satisfies the properties required in [Sey22].
In case
n = 7, 8, 9, the function returnes the partsTAGS_Y,TAGS_X, andTAG_SIGN, respectively, of theTAG_VECTOR. For a description of theTAG_VECTORsee the description ofenum tag_offsetsin fileorder_vector.c.
-
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_data(0, buf, 97)in the same module, withbufof typeuint32_t[97].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_NORM_A
Sum of the squares of the A part of \(v_1\) (mod 15)
-
enumerator OFS_DIAG_VA
For compatibly with older versions, always equal to 0
-
enumerator OFS_WATERMARK_PERM
Watermark of the A part of \(v_1\) (mod 15)
-
enumerator OFS_TAGS_Y
Entries of \(v_1\) used for computing \(y_e\)
-
enumerator OFS_SOLVE_Y
Equation system used for computing \(y_e\)
-
enumerator OFS_TAGS_X
Entries of \(v_1\) used for computing \(x_d\)
-
enumerator OFS_SOLVE_X
Equation system used for computing \(x_e\)
-
enumerator OFS_TAG_SIGN
Entry of \(v_1\) used for computing sign of \(x_d\)
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.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.Details are yet to be documented!!!
Caution:
This is a quick analyis of a 2A axis. The function returns 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.
-
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 functionmalloc`fails 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.
C interface for file mm_compress.c
This file contains functions for compressing a word of generators of the Monster group to an integer.
TODO: Documentation yet missing!
Functions
-
void mm_compress_pc_init(mm_compress_type *pc, uint32_t back)
yet to be documented
-
int32_t mm_compress_pc_add_nx(mm_compress_type *pc, uint32_t *m, uint32_t len)
yet to be documented
-
int32_t mm_compress_pc_add_type2(mm_compress_type *pc, uint32_t c)
yet to be documented
-
int32_t mm_compress_pc_add_type4(mm_compress_type *pc, uint32_t c)
yet to be documented
-
int32_t mm_compress_pc_add_t(mm_compress_type *pc, uint32_t t)
yet to be documented
-
int32_t mm_compress_pc(mm_compress_type *pc, uint64_t *p_n)
yet to be documented
-
int32_t mm_compress_pc_expand_int(uint64_t *p_n, uint32_t *m)
yet to be documented
C interface for file mm_vector_v1_mod3.c
File mm_vector_v1_mod3 contains a precomuted vector v1_mod3 of the representation of the monster group (mod 3). This vector can be used for obtaining an (unknown) element \(g\) of the subgroup \(G_{x0}\) of the monster from and image of that vector under \(g\).
So the functions in this module are similar to those in module mm_order.c, but faster.
Note that we cannot check membership in \(G_{x0}\) with the functions in this module!
This module is yet a stub!!!
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
v1_mod3into 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 \(v_1\) , where \(v_1\) is the precomute vectorv1_mod3.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_via_v1_mod3(uint_mmv_t *v, uint32_t *g)
Find an element \(g\) of the subgroup \(G_{x0}\).
Yet to be documented!!!