# Direct Sums

AbstractAlgebra allows the construction of the external direct sum of any nonempty vector of finitely presented modules.

Note that external direct sums are considered equal iff they are the same object.

## Generic direct sum type

AbstractAlgebra provides a generic direct sum type `Generic.DirectSumModule{T}`

where `T`

is the element type of the base ring. The implementation is in `src/generic/DirectSum.jl`

Elements of direct sum modules have type `Generic.DirectSumModuleElem{T}`

.

## Abstract types

Direct sum module types belong to the abstract type `FPModule{T}`

and their elements to `FPModuleElem{T}`

.

## Constructors

`direct_sum`

— Function`direct_sum(M::ModuleFP{T}...; task::Symbol = :sum) where T`

Given modules $M_1\dots M_n$, say, return the direct sum $\bigoplus_{i=1}^n M_i$.

Additionally, return

- a vector containing the canonical injections $M_i\to\bigoplus_{i=1}^n M_i$ if
`task = :sum`

(default), - a vector containing the canonical projections $\bigoplus_{i=1}^n M_i\to M_i$ if
`task = :prod`

, - two vectors containing the canonical injections and projections, respectively, if
`task = :both`

, - none of the above maps if
`task = :none`

.

`direct_sum(M::Matroid, N::Matroid)`

The `direct sum`

of the matroids `M`

and `N`

. Optionally one can also pass a vector of matroids.

See Section 4.2 of James Oxley (2011).

To obtain the direct sum of the Fano and a uniform matroid type:

**Examples**

```
julia> direct_sum(fano_matroid(), uniform_matroid(2,4))
Matroid of rank 5 on 11 elements
```

To take the sum of three uniform matroids use:

**Examples**

```
julia> matroids = Vector([uniform_matroid(2,4), uniform_matroid(1,3), uniform_matroid(3,4)]);
julia> M = direct_sum(matroids)
Matroid of rank 6 on 11 elements
```

```
direct_sum(m::Vector{<:FPModule{T}}) where T <: RingElement
direct_sum(vals::FPModule{T}...) where T <: RingElement
```

Return a tuple $M, f, g$ consisting of $M$ the direct sum of the modules `m`

(supplied as a vector of modules), a vector $f$ of the injections of the $m[i]$ into $M$ and a vector $g$ of the projections from $M$ onto the $m[i]$.

`direct_sum(G::GrpAbFinGen...) -> GrpAbFinGen, Vector{GrpAbFinGenMap}`

Return the direct sum $D$ of the (finitely many) abelian groups $G_i$, together with the injections $G_i \to D$.

For finite abelian groups, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain $D$ as a direct product together with the projections $ D \to G*i$, one should call `direct*product(G...)`. If one wants to obtain $D$ as a biproduct together with the projections and the injections, one should call`

biproduct(G...)`.

Otherwise, one could also call `canonical_injections(D)`

or `canonical_projections(D)`

later on.

```
direct_sum(x::Vararg{T}) where T <: AbstractSpace -> T, Vector{AbstractSpaceMor}
direct_sum(x::Vector{T}) where T <: AbstractSpace -> T, Vector{AbstractSpaceMor}
```

Given a collection of quadratic or hermitian spaces $V_1, \ldots, V_n$, return their direct sum $V := V_1 \oplus \ldots \oplus V_n$, together with the injections $V_i \to V$.

For objects of type `AbstractSpace`

, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain `V`

as a direct product with the projections $V \to V_i$, one should call `direct_product(x)`

. If one wants to obtain `V`

as a biproduct with the injections $V_i \to V$ and the projections $V \to V_i$, one should call `biproduct(x)`

.

```
direct_sum(x::Vararg{T}) where T <: AbstractLat -> T, Vector{AbstractSpaceMor}
direct_sum(x::Vector{T}) where T <: AbstractLat -> T, Vector{AbstractSpaceMor}
```

Given a collection of quadratic or hermitian lattices $L_1, \ldots, L_n$, return their direct sum $L := L_1 \oplus \ldots \oplus L_n$, together with the injections $L_i \to L$ (seen as maps between the corresponding ambient spaces).

For objects of type `AbstractLat`

, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain `L`

as a direct product with the projections $L \to L_i$, one should call `direct_product(x)`

. If one wants to obtain `L`

as a biproduct with the injections $L_i \to L$ and the projections $L \to L_i$, one should call `biproduct(x)`

.

```
direct_sum(x::Vararg{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}
direct_sum(x::Vector{TorQuadModule}) -> TorQuadModule, Vector{TorQuadModuleMor}
```

Given a collection of torsion quadratic modules $T_1, \ldots, T_n$, return their direct sum $T := T_1\oplus \ldots \oplus T_n$, together with the injections $T_i \to T$.

For objects of type `TorQuadModule`

, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain `T`

as a direct product with the projections $T \to T_i$, one should call `direct_product(x)`

. If one wants to obtain `T`

as a biproduct with the injections $T_i \to T$ and the projections $T \to T_i$, one should call `biproduct(x)`

.

`direct_sum(g1::QuadSpaceCls, g2::QuadSpaceCls) -> QuadSpaceCls`

Return the isometry class of the direct sum of two representatives.

```
direct_sum(x::Vararg{ZLat}) -> ZLat, Vector{AbstractSpaceMor}
direct_sum(x::Vector{ZLat}) -> ZLat, Vector{AbstractSpaceMor}
```

Given a collection of $\mathbb Z$-lattices $L_1, \ldots, L_n$, return their direct sum $L := L_1 \oplus \ldots \oplus L_n$, together with the injections $L_i \to L$. (seen as maps between the corresponding ambient spaces).

For objects of type `ZLat`

, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain `L`

as a direct product with the projections $L \to L_i$, one should call `direct_product(x)`

. If one wants to obtain `L`

as a biproduct with the injections $L_i \to L$ and the projections $L \to L_i$, one should call `biproduct(x)`

.

`direct_sum(S1::ZpGenus, S2::ZpGenus) -> ZpGenus`

Return the local genus of the direct sum of two representatives.

`direct_sum(G1::ZGenus, G2::ZGenus) -> ZGenus`

Return the genus of the direct sum of `G1`

and `G2`

.

The direct sum is defined via representatives.

`direct_sum(g1::HermLocalGenus, g2::HermLocalGenus) -> HermLocalGenus`

Given two local genus symbols `g1`

and `g2`

for hermitian lattices over $E/K$ at the same prime ideal $\mathfrak p$ of $\mathcal O_K$, return their direct sum. It corresponds to the local genus symbol of the $\mathfrak p$-adic completion of the direct sum of respective representatives of `g1`

and `g2`

.

`direct_sum(G1::HermGenus, G2::HermGenus) -> HermGenus`

Given two global genus symbols `G1`

and `G2`

for hermitian lattices over $E/K$, return their direct sum. It corresponds to the global genus symbol of the direct sum of respective representatives of `G1`

and `G2`

.

**Examples**

```
julia> F = FreeModule(ZZ, 5)
Free module of rank 5 over Integers
julia> m1 = F(BigInt[4, 7, 8, 2, 6])
(4, 7, 8, 2, 6)
julia> m2 = F(BigInt[9, 7, -2, 2, -4])
(9, 7, -2, 2, -4)
julia> S1, f1 = sub(F, [m1, m2])
(Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: Free module of rank 5 over Integers)
julia> m1 = F(BigInt[3, 1, 7, 7, -7])
(3, 1, 7, 7, -7)
julia> m2 = F(BigInt[-8, 6, 10, -1, 1])
(-8, 6, 10, -1, 1)
julia> S2, f2 = sub(F, [m1, m2])
(Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: Free module of rank 5 over Integers)
julia> m1 = F(BigInt[2, 4, 2, -3, -10])
(2, 4, 2, -3, -10)
julia> m2 = F(BigInt[5, 7, -6, 9, -5])
(5, 7, -6, 9, -5)
julia> S3, f3 = sub(F, [m1, m2])
(Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: Free module of rank 5 over Integers)
julia> D, f = direct_sum(S1, S2, S3)
(DirectSumModule over Integers, AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: DirectSumModule over Integers, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: DirectSumModule over Integers, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: DirectSumModule over Integers], AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Module homomorphism with
Domain: DirectSumModule over Integers
Codomain: Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: DirectSumModule over Integers
Codomain: Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: DirectSumModule over Integers
Codomain: Submodule over Integers with 2 generators and no relations])
```

## Functionality for direct sums

In addition to the Module interface, AbstractAlgebra direct sums implement the following functionality.

### Basic manipulation

`summands`

— Method`summands(M::DirectSumModule{T}) where T <: RingElement`

Return the modules that this module is a direct sum of.

**Examples**

```
julia> F = FreeModule(ZZ, 5)
Free module of rank 5 over Integers
julia> m1 = F(BigInt[4, 7, 8, 2, 6])
(4, 7, 8, 2, 6)
julia> m2 = F(BigInt[9, 7, -2, 2, -4])
(9, 7, -2, 2, -4)
julia> S1, f1 = sub(F, [m1, m2])
(Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: Free module of rank 5 over Integers)
julia> m1 = F(BigInt[3, 1, 7, 7, -7])
(3, 1, 7, 7, -7)
julia> m2 = F(BigInt[-8, 6, 10, -1, 1])
(-8, 6, 10, -1, 1)
julia> S2, f2 = sub(F, [m1, m2])
(Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: Free module of rank 5 over Integers)
julia> m1 = F(BigInt[2, 4, 2, -3, -10])
(2, 4, 2, -3, -10)
julia> m2 = F(BigInt[5, 7, -6, 9, -5])
(5, 7, -6, 9, -5)
julia> S3, f3 = sub(F, [m1, m2])
(Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: Free module of rank 5 over Integers)
julia> D, f = direct_sum(S1, S2, S3)
(DirectSumModule over Integers, AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: DirectSumModule over Integers, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: DirectSumModule over Integers, Module homomorphism with
Domain: Submodule over Integers with 2 generators and no relations
Codomain: DirectSumModule over Integers], AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Module homomorphism with
Domain: DirectSumModule over Integers
Codomain: Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: DirectSumModule over Integers
Codomain: Submodule over Integers with 2 generators and no relations, Module homomorphism with
Domain: DirectSumModule over Integers
Codomain: Submodule over Integers with 2 generators and no relations])
julia> summands(D)
3-element Vector{AbstractAlgebra.Generic.Submodule{BigInt}}:
Submodule over Integers with 2 generators and no relations
Submodule over Integers with 2 generators and no relations
Submodule over Integers with 2 generators and no relations
```

` (D::DirectSumModule{T}(::Vector{<:FPModuleElem{T}}) where T <: RingElement`

Given a vector (or $1$-dim array) of module elements, where the $i$-th entry has to be an element of the $i$-summand of $D$, create the corresponding element in $D$.

**Examples**

```
julia> N = FreeModule(QQ, 2);
julia> M = FreeModule(QQ, 1);
julia> D, _ = direct_sum(M, N, M);
julia> D([gen(M, 1), gen(N, 1), gen(M, 2)])
(1//1, 1//1, 0//1, 0//1)
```

### Special Homomorphisms

Due to the special structure as direct sums, homomorphisms can be created by specifying homomorphisms for all summands. In case of the codmain being a direct sum as well, any homomorphism may be thought of as a matrix containing maps from the $i$-th source summand to the $j$-th target module:

`ModuleHomomorphism(D::DirectSumModule{T}, S::DirectSumModule{T}, m::Matrix{Any}) where T <: RingElement`

Given a matrix $m$ such that the $(i,j)$-th entry is either $0$ (`Int(0)`

) or a `ModuleHomomorphism`

from the $i$-th summand of $D$ to the $j$-th summand of $S$, construct the corresponding homomorphism.

`ModuleHomomorphism(D::DirectSumModule{T}, S::FPModuleElem{T}, m::Vector{ModuleHomomorphism})`

Given an array $a$ of `ModuleHomomorphism`

such that $a_i$, the $i$-th entry of $a$ is a `ModuleHomomorphism`

from the $i$-th summand of `D`

into `S`

, construct the direct sum of the components.

Given a matrix $m$ such that the $(i,j)$-th entry is either $0$ (`Int(0)`

) or a `ModuleHomomorphism`

from the $i$-th summand of $D$ to the $j$-th summand of $S$, construct the corresponding homomorphism.

**Examples**

```
julia> N = FreeModule(QQ, 2);
julia> D, _ = direct_sum(N, N);
julia> p = ModuleHomomorphism(N, N, [3,4] .* basis(N));
julia> q = ModuleHomomorphism(N, N, [5,7] .* basis(N));
julia> phi = ModuleHomomorphism(D, D, [p 0; 0 q])
Module homomorphism with
Domain: DirectSumModule over Rationals
Codomain: DirectSumModule over Rationals
julia> r = ModuleHomomorphism(N, D, [2,3] .* gens(D)[1:2])
Module homomorphism with
Domain: Vector space of dimension 2 over Rationals
Codomain: DirectSumModule over Rationals
julia> psi = ModuleHomomorphism(D, D, [r, r])
Module homomorphism with
Domain: DirectSumModule over Rationals
Codomain: DirectSumModule over Rationals
```