Repository: JuliaLang/julia
File: stdlib/LinearAlgebra/src/symmetric.jl (Julia)

Code before:
!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
symmetricpart!(A::AbstractMatrix, uplo::Symbol=:U) =
    Symmetric(_hermorsympart!(symmetricpart, transpose, A, char_uplo(uplo)), uplo)

"""
    hermitianpart(A, uplo=:U, full=false) -> Hermitian

Return the Hermitian part of the square matrix `A`, defined as `(A + A') / 2`,
as a [`Hermitian`](@ref) matrix. For real matrices `A`, this is also known as the symmetric
part of `A`. The first optional argument `uplo` controls whether the upper
(`uplo = :U`) or lower (`uplo = :L`) triangle of the matrix underlying the [`Hermitian`](@ref)
view is explicitly filled. Unless the second optional argument `full=true` (in which case the
full underlying matrix is filled with the Hermitian part), the opposite triangle is then
only implicitly filled via the [`Hermitian`](@ref) view. For real matrices, the latter is
equivalent to a [`Symmetric`](@ref) view.

See also [`hermitianpart!`](@ref) for the corresponding in-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix{T}, uplo=:U, full::Bool = false) where {T} =
    hermitianpart!(copy_similar(A, typeof(one(T) / 2)), uplo, full)
hermitianpart(x::Number, uplo=:U, full::Bool=false) = real(x)

"""
    hermitianpart!(A, uplo=:U, full=false) -> Hermitian

Overwrite the upper (`uplo = :U`) or lower (`uplo = :L`) triangle of the square matrix `A`
with its Hermitian part `(A + A') / 2`, and return `Hermitian(A, uplo)`. For real matrices
`A`, this is also known as the symmetric part of `A`.

See also [`hermitianpart`](@ref).

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U, full::Bool = false) =
    Hermitian(_hermorsympart!(a -> hermitianpart(a, uplo, full), adjoint, A, char_uplo(uplo), full), uplo)

@inline function _hermorsympart!(real::Function, conj::Function, A::AbstractMatrix, uplo::Char, full::Bool)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = real(A[j, j])
        for i in (uplo === 'U' ? (1:(j - 1)) : ((j + 1):n))
            A[i, j] = val = (A[i, j] + conj(A[j, i])) / 2
            full && (A[j, i] = conj(val))
        end

Review comment (suggestion):
This seems like a strange API — why should you need to pass `uplo` in order to set`full=true`?

Could it be `uplo=:both` or similar?  Either that or `full` should be a keyword argument.

Code after:
    This function requires Julia 1.10 or later.
"""
hermitianpart(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart(A), uplo)

"""
    hermitianpart!(A, uplo=:U) -> Hermitian

Overwrite the square matrix `A` in-place with its Hermitian part `(A + A') / 2`, and return
[`Hermitian(A, uplo)`](@ref). For real matrices `A`, this is also known as the symmetric
part of `A`.

See also [`hermitianpart`](@ref) for the corresponding out-of-place operation.

!!! compat "Julia 1.10"
    This function requires Julia 1.10 or later.
"""
hermitianpart!(A::AbstractMatrix, uplo::Symbol=:U) = Hermitian(_hermitianpart!(A), uplo)

_hermitianpart(A::AbstractMatrix) = _hermitianpart!(copy_similar(A, Base.promote_op(/, eltype(A), Int)))
_hermitianpart(a::Number) = real(a)

function _hermitianpart!(A::AbstractMatrix)
    require_one_based_indexing(A)
    n = checksquare(A)
    @inbounds for j in 1:n
        A[j, j] = _hermitianpart(A[j, j])
        for i in 1:j-1
            A[i, j] = val = (A[i, j] + adjoint(A[j, i])) / 2
            A[j, i] = adjoint(val)
        end
    end
    return A
end