###############################################################################
#
#   Submodule.jl : Submodules of modules
#
###############################################################################

###############################################################################
#
#   Reduced form
#
###############################################################################

reduced_form(mat::MatElem{T}) where T <: RingElement = hnf(mat)

function reduced_form(mat::MatElem{T}) where T <: FieldElement
  r, m = rref(mat)
  return m
end

isreduced_form(mat::MatElem{T}) where T <: RingElement = is_hnf(mat)

isreduced_form(mat::MatElem{T}) where T <: FieldElement = is_rref(mat)

###############################################################################
#
#   Submodule constructor
#
###############################################################################

@doc raw"""
    sub(m::FPModule{T}, gens::Vector{<:FPModuleElem{T}}) where T <: RingElement

Return the submodule of the module `m` generated by the given generators,
given as elements of `m`.
"""
function sub(m::FPModule{T}, gens::Vector{S}) where {T <: RingElement, S <: FPModuleElem{T}}
   return Generic.sub(m, gens)
end

# Handles empty vector of elements
function sub(m::FPModule{T}, gens::Vector{Any}) where T <: RingElement
   return Generic.sub(m, gens)
end

# Also see sub in AbstractAlgebra.jl (must be defined after Generic)


