# Subspaces and Decomposition

## `EisensteinSubspace(M): ModBrdt -> ModBrdt`

Returns the Eisenstein subspace of the Brandt module $M$. When the level of $M$ is square-free this will be the submodule generated by a vector of the form $(w/w_1,\dots,w/w_n)$, if it exists in $M$, where $w_i$ is the number of automorphisms of the $i$-th basis ideal and $w = {\rm LCM}(\{ w_i \})$.

## `CuspidalSubspace(M): ModBrdt -> ModBrdt`

Returns the cuspidal subspace, defined to be the orthogonal complement of the Eisenstein subspace of the Brandt module $M$. If the discriminant of $M$ is coprime to the conductor, then the cuspidal subspace consists of the vectors in $M$ of the form $(a_1,\dots,a_n)$, where $\sum_i a_i = 0$.

## `OrthogonalComplement(M): ModBrdt -> ModBrdt`

The Brandt module orthogonal to the given module $M$ in the ambient module of $M$.

## `M meet N: ModBrdt, ModBrdt -> ModBrdt`

Returns the intersection of the Brandt modules $M$ and $N$.

## `Decomposition(M, B): ModBrdt, RngIntElt -> [ModBrdt]`

```magma
Sort: BoolElt                    Default: false
```

Returns a decomposition of the Brandt module with respect to the Atkin–Lehner operators and Hecke operators up to the bound $B$. The parameter `Sort` can be set to `true` to return a sequence sorted under the operator `lt` as defined below.

## `SortDecomposition(D): [ModBrdt] -> SeqEnum`

Sort the sequence $D$ of spaces of Brandt modules with respect to the `lt` comparison operator.

## `Example: Mod Brdt:Decomposition (ex-5a913e)`

```magma
> M := BrandtModule(2*3*17);
> Decomp := Decomposition(M,11 : Sort := true);
> Decomp;
[
    Brandt module of level (102,1), dimension 1, and degree 4 over Integer Ring,
    Brandt module of level (102,1), dimension 1, and degree 4 over Integer Ring,
    Brandt module of level (102,1), dimension 1, and degree 4 over Integer Ring,
    Brandt module of level (102,1), dimension 1, and degree 4 over Integer Ring
]
> [ IsEisenstein(N) : N in Decomp ];
[ true, false, false, false ]

```

## Boolean Tests on Subspaces

### `IsEisenstein(M): ModBrdt -> BoolElt`

Returns `true` if and only if the Brandt module $M$ is contained in the Eisenstein subspace of the ambient module.

### `IsCuspidal(M): ModBrdt -> BoolElt`

Returns `true` if and only if the Brandt module $M$ is contained in the cuspidal subspace of the ambient module.

### `IsIndecomposable(M, B): ModBrdt, RngIntElt -> BoolElt`

Returns `true` if an only if the Brandt module $M$ does not decompose into complementary Hecke-invariant submodules under the Atkin-Lehner operators, nor under the Hecke operators $T_n$, for $n \le B$.

### `M1 subset M2: ModBrdt, ModBrdt -> BoolElt`

Returns `true` if and only if $M1$ is contained in the module $M2$.

### `M1 lt M2: ModBrdt, ModBrdt -> BoolElt`

```magma
Bound: RngIntElt                    Default: 101
```

Given two indecomposable subspaces, $M_1$ and $M_2$, returns `true` if and only if $M_1 < M_2$ under the following ordering:

(1) Order by dimension, with smaller dimension being less.

(2) An Eisenstein subspace is less than a cuspidal subspace of the same dimension.

(3) Order by Atkin–Lehner eigenvalues, starting with *smallest* prime dividing the level and with ‘+’ being less than ‘–‘.

(4) Order by $|{\operatorname{Tr}}(T_{p^i}(M_j)))|$, p not dividing the level, and $1 \le i \le g$, where $g$ is `Dimension`($M_1$), with the positive one being smaller in the event of equality.

Condition (4) differs from the similar one for modular symbols, but permits the comparison of arbitrary Brandt modules. The algorithm returns `false` if all primes up to value of the parameter `Bound` fail to differentiate the arguments.

### `M1 gt M2: ModBrdt, ModBrdt -> BoolElt`

```magma
Bound: RngIntElt                    Default: 101
```

Returns the complement of `lt` for Brandt modules $M1$ and $M2$.

### `Example: Mod Brdt:Eisenstein Subspace (ex-577acc)`

```magma
> M := BrandtModule(7,7);
> E := EisensteinSubspace(M);
> Basis(E);
[
    (1 1 0 0),
    (0 0 1 1)
]
> S := CuspidalSubspace(M);
> Basis(S);
[
    ( 1 -1  0  0),
    ( 0  0  1 -1)
]
> PS<q> := LaurentSeriesRing(RationalField());
> qExpansionBasis(S,100);
[
    q + q^2 - q^4 - 3*q^8 - 3*q^9 + 4*q^11 - q^16 - 3*q^18 + 4*q^22 + 8*q^23
        - 5*q^25 + 2*q^29 + 5*q^32 + 3*q^36 - 6*q^37 - 12*q^43 - 4*q^44 +
        8*q^46 - 5*q^50 - 10*q^53 + 2*q^58 + 7*q^64 + 4*q^67 + 16*q^71 +
        9*q^72 - 6*q^74 + 8*q^79 + 9*q^81 - 12*q^86 - 12*q^88 - 8*q^92 -
        12*q^99 + 5*q^100 + O(q^101)
]

```
