We introduce here the necessary definitions and results which lie behind the methods about primitive embeddings. Most of the content is taken from [Nik79].

# Nikulin's theory on primitive embeddings

## Primitive embeddings

Given an embedding $i\colon S\hookrightarrow T$ of non-degenerate integral integer lattices, we call $i$ *primitive* if its cokernel $T/i(S)$ is torsion free. Two primitive embeddings $i_1\colon S\hookrightarrow M_1$ and $i_2\colon S \hookrightarrow M_2$ of $S$ into two lattices $M_1$ and $M_2$ are called *isomorphic* if there exists an isometry $M_1 \to M_2$ which restricts to the identity of $S$. Moreover, if there exists an isometry between $M_1$ and $M_2$ which maps $S$ to itself (not necessarily identically), we say that $i_1$ and $i_2$ defines *isomorphic primitive sublattices* [Nik79].

In his paper, V. V. Nikulin gives necessary and sufficient condition for an even integral lattice $M$ to embed primitively into an even unimodular lattice with given invariants (see Theorem 1.12.2 in [Nik79]). More generally, the author also provides methods to compute primitive embeddings of any even lattice into an even lattice of a given genus (see Proposition 1.15.1 in [Nik79]). In the latter proposition, it is explained how to classify such embeddings as isomorphic embeddings or as isomorphic sublattices. Moreover, with enough care, one can generalize the previous results for embeddings in odd lattices.

A general method to compute primitive embeddings between integral lattices can be algorithmically implemented, however it tends to be slow and inefficient in general for large rank or determinant. But, in the case where the discriminant groups are (elementary) $p$-groups, the method can be made more efficient.

We provide 4 kinds of output:

- A boolean, which only returns whether there exists a primitive embedding;
- A single primitive embedding as soon as the algorithm computes one;
- A list of representatives of isomorphism classes of primitive embeddings;
- A list of representatives of isomorphism classes of primitive sublattices.

`primitive_embeddings`

— Method```
primitive_embeddings(L::ZZLat, M::ZZLat; classification::Symbol = :sub,
check::Bool = true)
-> Bool, Vector{Tuple{ZZLat, ZZLat, ZZLat}}
```

Given an integral integer lattice $L$, which is unique in its genus, and an integral integer lattice $M$, return whether $M$ embeds primitively in $L$.

The first output of the function is a boolean `T`

stating whether $M$ embeds primitively in $L$. The second output $V$ consists of triples $(L', M', N')$ where $L'$ is isometric to $L$, $M'$ is a primitive sublattice of $L'$ isometric to $M$, and $N'$ is the orthogonal complement of $M'$ in $L'$.

If `T == false`

, then $V$ will always be the empty list. If `T == true`

, then the content of $V$ depends on the value of the symbol `classification`

. There are 4 possibilities:

`classification == :none`

: $V$ is the empty list;`classification == :first`

: $V$ consists of the first primitive embedding found;`classification == :sub`

: $V$ consists of representatives for all isomorphism classes of primitive embeddings of $M$ in $L$, up to the actions of $O(M)$ and $O(q)$ where $q$ is the discriminant group of $L$;`classification == :emb`

: $V$ consists of representatives for all isomorphism classes of primitive embeddings of $M$ in $L$ up to the action of $O(q)$ where $q$ is the discriminant group of $L$.

If `check`

is set to `true`

, the function determines whether $L$ is in fact unique in its genus.

We follow the algorithm described in the proof of Proposition 1.15.1 of [Nik79]. The classification methods for the symbols `:sub`

and `:emb`

correspond to the different classes of primitive embeddings defined in the same proposition: for `:sub`

we classify sublattices of $L$ which are isometric to $M$, and for `:emb`

we classify the different embeddings of $M$ into $L$.

**Examples**

We can use such primitive embeddings algorithm to classify embedding in unimodular lattices

```
julia> E8 = root_lattice(:E,8);
julia> A4 = root_lattice(:A,4);
julia> bool, pe = primitive_embeddings(E8, A4)
(true, Tuple{ZZLat, ZZLat, ZZLat}[(Integer lattice of rank 8 and degree 8, Integer lattice of rank 4 and degree 8, Integer lattice of rank 4 and degree 8)])
julia> pe
1-element Vector{Tuple{ZZLat, ZZLat, ZZLat}}:
(Integer lattice of rank 8 and degree 8, Integer lattice of rank 4 and degree 8, Integer lattice of rank 4 and degree 8)
julia> genus(pe[1][2]) == genus(pe[1][3])
true
```

To be understood: there exists a unique class of embedding of the root lattice $A_4$ into the root lattice $E_8$, and the orthogonal primitive sublattice is isometric to $A_4$.

This function is part of the experimental code in Oscar. Please read here for more details.

Note that the previous two functions require the first lattice of the input to be unique in its genus. Otherwise, one can specify a genus, or its invariants, as a first input:

`primitive_embeddings`

— Method```
primitive_embeddings(G::ZZGenus, M::ZZLat; classification::Symbol = :sub)
-> Bool, Vector{Tuple{ZZLat, ZZLat, ZZLat}}
```

Given a genus symbol $G$ for integral integer lattices and an integral integer lattice $M$, return whether $M$ embeds primitively in a lattice in $G$.

The first output of the function is a boolean `T`

stating whether $M$ embeds primitively in a lattice in $G$. The second output $V$ consists of triples $(L', M', N')$ where $L'$ is a lattice in $G$, $M'$ is a sublattice of $L'$ isometric to $M$, and $N'$ is the orthogonal complement of $M'$ in $L'$.

If `T == false`

, then $V$ will always be the empty list. If `T == true`

, then the content of $V$ depends on the value of `classification`

. There are 4 possibilities:

`classification == :none`

: $V$ is the empty list;`classification == :first`

: $V$ consists of the first primitive embedding found;`classification == :sub`

: $V$ consists of representatives for all isomorphism classes of primitive embeddings of $M$ in lattices in $G$, up to the actions of $O(M)$ and $O(q)$ where $q$ is the discriminant group of a lattice in $G$;`classification == :emb`

: $V$ consists of representatives for all isomorphism classes of primitive embeddings of $M$ in of lattices in $G$, up to the action of $O(q)$ where $q$ is the discriminant group of a lattice in $G$.

We follow the algorithm described in the proof of Proposition 1.15.1 of [Nik79]. The classification methods for `:sub`

and `:emb`

correspond to the different classes of primitive embeddings defined in the same proposition: for `:sub`

we classify sublattices of lattices in $G$ which are isometric to $M$, and for `:emb`

we classify the different embeddings of $M$ into lattices in $G$.

This function is part of the experimental code in Oscar. Please read here for more details.

`primitive_embeddings`

— Method```
primitive_embeddings(q::TorQuadModule, sign::Tuple{Int, Int}, M::ZZLat;
classification::Symbol = :sub)
-> Bool, Vector{Tuple{ZZLat, ZZLat, ZZLat}}
```

Given a tuple `sign`

of non-negative integers and a torsion quadratic module $q$ which define a genus symbol $G$ for integral integer lattices, return whether the integral integer lattice $M$ embeds primitively in a lattice in $G$.

The first output of the function is a boolean `T`

stating whether $M$ embeds primitively in a lattice in $G$. The second output $V$ consists of triples $(L', M', N')$ where $L'$ is a lattice in $G$, $M'$ is a sublattice of $L'$ isometric to $M$, and $N'$ is the orthogonal complement of $M'$ in $L'$.

If `T == false`

, then $V$ will always be the empty list. If `T == true`

, then the content of $V$ depends on the value of the symbol `classification`

. There are 4 possibilities:

`classification == :none`

: $V$ is the empty list;`classification == :first`

: $V$ consists of the first primitive embedding found;`classification == :sub`

: $V$ consists of representatives for all isomorphism classes of primitive embeddings of $M$ in lattices in $G$, up to the actions of $O(M)$ and $O(q)$;`classification == :emb`

: $V$ consists of representatives for all isomorphism classes of primitive embeddings of $M$ in lattices in $G$ $G$, up to the action of $O(q)$.

If the pair `(q, sign)`

does not define a non-empty genus for integer lattices, an error is thrown.

We follow the algorithm described in the proof of Proposition 1.15.1 of [Nik79]. The classification methods for the symbols `:sub`

and `:emb`

correspond to the different classes of primitive embeddings defined in the same proposition: for `:sub`

we classify sublattices of lattices in $G$ which are isometric to $M$, and for `:emb`

we classify the different embeddings of $M$ into lattices in $G$.

This function is part of the experimental code in Oscar. Please read here for more details.

In order to compute such primitive embeddings of a lattice $M$ into a lattice $L$, we follow the proof of Proposition 1.15.1 of [Nik79].

Note: for the implementation of the algorithm, we construct a lattice $T$ which is unique in its genus, such that $D_T$ and $D_M(-1)$ are isometric and $O(T)\to O(D_T)$ is surjective. We then classify all primitive extensions of $M\oplus T$ modulo $O(D_T)$ (and modulo $O(M)$ for a classification of primitive sublattices). To classify such primitive extensions, we use Proposition 1.5.1 of [Nik79]:

`primitive_extensions`

— Method```
primitive_extensions(M::ZZLat, N::ZZLat; glue_order::Union{IntegerUnion, Nothing} = nothing,
q::Union{TorQuadModule, Nothing} = nothing,
even::Bool = is_even(M) && is_even(N),
classification::Symbol = :subsub)
-> Bool, Vector{Tuple{ZZLat, ZZLat, ZZLat}}
```

Given two integral integer lattices $M$ and $N$, return a boolean `T`

and a list $V$ of representatives of isomorphism classes of primitive extensions $M \oplus N \subseteq L$.

One can decide to choose the index of $[L:(M\oplus N)]$, which should be a positive integer by setting `glue_order`

to the desired value. One can also decide on the isometry class of the discriminant form of the primitive extension by setting `q`

to the desired value. If there are no primitive extensions of $M$ and $N$ satisfying the conditions imposed by the choice of `glue_order`

or `q`

, then `T = false`

and $V$ is the empty list.

Otherwise, `T = true`

and $V$ consists of triple $(L, M', N')$ such that $M'$ is isometric to $M$, $N'$ is isometric to $N$ and $L$ is a primitive extension of $M'\oplus N'$ satisfying conditions `glue_order`

or `q`

if assigned.

The content of $V$ depends on the value `classification`

. There are 6 possibilities:

`classification == :none`

: $V$ is the empty list;`classification == :first`

: $V$ consists of the first primitive extension computed;`classification == :subsub`

: $V$ consists of representatives for all isomorphism classes of primitive extensions of $M\oplus N$ satisfying the given conditions, up to the actions of $O(M)$ and $O(N)$;`classification == :subemb`

: $V$ consists of representatives for all isomorphism classes of primitive extensions of $M\oplus N$ satisfying the given conditions, up to the action of $O(M)$;`classification == :embsub`

: $V$ consists of representatives for all isomorphism classes of primitive extensions of $M\oplus N$ satisfying the given conditions, up to the action of $O(N)$;`classification == :embemb`

: $V$ consists of representatives for all isomorphism classes of primitive extensions of $M\oplus N$ satisfying the given conditions.

If `even = true`

, then each primitive extension in output is selected to be even.

This function is part of the experimental code in Oscar. Please read here for more details.

We recall that a *primitive extension* of the orthogonal direct sum of two integral integer lattices $M$ and $N$ is an overlattice $L$ of $M\oplus N$ such that both $M$ and $N$ embed primitively in $L$ (via the natural embeddings $M,N \to M\oplus N\subseteq L$). Such primitive extensions are obtained, and classified, by classifying *gluings* between anti-isometric subgroups of the respective discriminant groups of $M$ and $N$. The construction of an overlattice is determined by the graph of such gluing.

## Equivariant primitive extensions

An *equivariant primitive extension* of a pair of integer lattices with isometries $(M, f_M)$ and $(N, f_N)$ is a primitive extension of $M$ and $N$ obtained by gluing two subgroups which are respectively $D_{f_M}$ and $D_{f_N}$ stable along a glue map which commutes with these two actions. If such a gluing exists, then the overlattice $L$ of $M\oplus N$ is equipped with an isometry $f_L$ which preserves both $M$ and $N$, and restricts to $f_M$ and $f_N$ respectively.

`equivariant_primitive_extensions`

— Method```
equivariant_primitive_extensions(M::Union{ZZLat, ZZLatWithIsom},
N::Union{ZZLat, ZZLatWithIsom};
glue_order::Union{IntegerUnion, Nothing} = nothing,
q::Union{IntegerUnion, Nothing} = nothing,
even::Bool = is_even(M) && is_even(N),
classification::Symbol = :subsub,
compute_bar_Gf::Bool = true)
-> Bool, Vector{Tuple{ZZLatWithIsom,
ZZLatWithIsom,
ZZLatWithIsom}}
```

Given two integral integer lattices $M$ and $N$, where at least one of them is equiped with an isometry, return a boolean `T`

and a list $V$ of representatives of isomorphism classes of equivariant primitive extensions $(M, fM) \oplus (N, fN) \subseteq (L, fL)$. Note that if $M$ (resp $N$) is not equiped with an isometry, then $M$ (resp. $N$) has to be definite.

One can decide to choose the index of $[L:(M\oplus N)]$ which should be a positive integer by setting `glue_order`

to the desired value. One can also decide on the isometry class of the discriminant form of a primitive extension by setting `q`

to the desired value. If there are no equivariant primitive extensions of $M$ and $N$ satisfying the conditions imposed by the choice of `glue_order`

or `q`

, then `T = false`

and $V$ is the empty list.

Otherwise, `T = true`

and $V$ consists of triples $((L, f_L), (M', f_M'), (N', f_N'))$ such that $M'$ is isometric to $M$, $N'$ is isometric to $N$ and $(L, f_L)$ is an equivariant primitive extension of $(M', f_M')\oplus (N', f_N')$ such that $L$ satisfies conditions `glue_order`

or `q`

if assigned. If $M$ (resp. $N$) is equiped with an isometry $f_M$ (resp. $f_N$), then $(M', f_M')$ and $(M, f_M)$ (resp. $(N', f_N')$ and $(N, f_N)$) are isomorphic as lattices with isometry.

The content of $V$ depends on the value of `classification`

. There are 6 possibilities:

`classification == :none`

: $V$ is empty by default;`classification == :first`

: $V$ consists of the first equivariant primitive extension computed;`classification == :subsub`

: $V$ consists of representatives for all isomorphism classes of equivariant primitive extensions of $(M, f_M)\oplus (N, f_N)$ satisfying the given conditions, up to the actions of $O(M, f_M)$ and $O(N, f_N)$;`classification == :subemb`

: $V$ consists of representatives for all isomorphism classes of equivariant primitive extensions of $(M, f_M)\oplus (N, f_N)$ satisfying the given conditions, up to the action of $O(M, f_M)$;`classification == :embsub`

: $V$ consists of representatives for all isomorphism classes of equivariant primitive extensions of $(M, f_M)\oplus (N, f_N)$ satisfying the given conditions, up to the action of $O(N, f_N)$;`classification == :embemb`

: $V$ consists of representatives for all isomorphism classes of equivariant primitive extensions of $(M, f_M)\oplus (N, f_N)$ satisfying the given conditions;

If $M$ (resp. $N$) is not equiped with an isometry, then the previous classifications are done modulo the action of $O(M)$ (resp. $O(N)$) instead of $O(M, f_M)$ (resp. $O(N, f_N)$). Moreover, the function extends representatives of conjugacy classes of isometries of $M$ (resp. $N$) which can be glued equivariantly with $f_N$ (resp. $f_M$) in a certain coset of $O(M)$ determined by `classification`

. Note that this can be expensive if $M$ (resp. $N$) as large isometry group.

If `even = true`

, then each primitive extension in output is selected to be even.

If `compute_bar_Gf`

is set to `true`

, then for each pair $(L, f_L)$ of an output triple in $V$, the algorithm compute the image of the natural map $O(L, f_L) \to O(D_L, D_{f_L})$ (see `image_centralizer_in_Oq`

).

This function is part of the experimental code in Oscar. Please read here for more details.

## Admissible equivariant primitive extensions

The following function is a major tool provided by [BH23]. Given a triple of even integer lattices with isometry $((A, a), (B, b), (C, c))$ and two prime numbers $p$ and $q$ (possibly equal), if $(A, B, C)$ is $p$-admissible, this function returns representatives of isomorphism classes of equivariant primitive extensions $(A, a)\oplus (B, b)\to (D, d)$ such that the type of $(D, d^q)$ is equal to the type of $(C, c)$ (see `type(::ZZLatWithIsom)`

).

`admissible_equivariant_primitive_extensions`

— Method```
admissible_equivariant_primitive_extensions(Afa::ZZLatWithIsom,
Bfb::ZZLatWithIsom,
Cfc::ZZLatWithIsom,
p::IntegerUnion,
q::IntegerUnion = p; check::Bool = true)
-> Vector{ZZLatWithIsom}
```

Given a triple of lattices with isometry $(A, f_A)$, $(B, f_B)$ and $(C, f_C)$, and a prime number $p$, such that $(A, B, C)$ is $p$-admissible, return a set of representatives of the double coset $G_B\backslash S/G_A$ where:

- $G_A$ and $G_B$ are the respective images of the morphisms $O(A, f_A) \to O(D_A, D_{f_A})$ and $O(B, f_B) \to O(D_B, D_{f_B})$;
- $S$ is the set of all primitive extensions $A \oplus B \subseteq C'$ with isometry $f_C'$ where $p\cdot C' \subseteq A\oplus B$ and such that the type of $(C', (f_C')^q)$ is equal to the type of $(C, f_C)$.

If `check == true`

the input triple is checked to a $p$-admissible triple of integral lattices (with isometry) with $f_A$ and $f_B$ having relatively coprime irreducible minimal polynomials. Moreover, the function checks that $A$ and $B$ are orthogonal if $A$, $B$ and $C$ lie in the same ambient quadratic space.

Note moreover that the function computes the image of the natural map $O(C, f_C) \to O(D_C, D_{f_C})$ along the primitive extension $A\oplus B\subseteq C$ (see Algorithm 2, Line 22 of [BH23]).

This function is part of the experimental code in Oscar. Please read here for more details.