# Internal documentation

This page documents the internal types and methods of `Manifolds.jl`

's that might be of use for writing your own manifold.

## Functions

`Manifolds.eigen_safe`

— Function`eigen_safe(x)`

Compute the eigendecomposition of `x`

. If `x`

is a `StaticMatrix`

, it is converted to a `Matrix`

before the decomposition.

`Manifolds.find_pv`

— Function`find_pv(x...)`

`A = find_pv(x...)`

returns the first `ProductArray`

among the arguments.

`Manifolds.isnormal`

— Function`isnormal(x; kwargs...) -> Bool`

Check if the matrix or number `x`

is normal, that is, if it commutes with its adjoint:

\[x x^\mathrm{H} = x^\mathrm{H} x.\]

By default, this is an equality check. Provide `kwargs`

for `isapprox`

to perform an approximate check.

`Manifolds.log_safe`

— Function`log_safe(x)`

Compute the matrix logarithm of `x`

. If `x`

is a `StaticMatrix`

, it is converted to a `Matrix`

before computing the log.

`Manifolds.log_safe!`

— Function`log_safe!(y, x)`

Compute the matrix logarithm of `x`

. If the eltype of `y`

is real, then the imaginary part of `x`

is ignored, and a `DomainError`

is raised if `real(x)`

has no real logarithm.

`Manifolds.mul!_safe`

— Function`mul!_safe(Y, A, B) -> Y`

Call `mul!`

safely, that is, `A`

and/or `B`

are permitted to alias with `Y`

.

`Manifolds.nzsign`

— Function`nzsign(z[, absz])`

Compute a modified `sign(z)`

that is always nonzero, i.e. where

\[\operatorname(nzsign)(z) = \begin{cases} 1 & \text{if } z = 0\\ \frac{z}{|z|} & \text{otherwise} \end{cases}\]

`Manifolds.realify`

— Function`realify(X::AbstractMatrix{T𝔽}, 𝔽::AbstractNumbers) -> Y::AbstractMatrix{<:Real}`

Given a matrix $X ∈ 𝔽^{n × n}$, compute $Y ∈ ℝ^{m × m}$, where $m = n \operatorname{dim}_𝔽$, and $\operatorname{dim}_𝔽$ is the `real_dimension`

of the number field $𝔽$, using the map $ϕ \colon X ↦ Y$, that preserves the matrix product, so that for all $C,D ∈ 𝔽^{n × n}$,

\[ϕ(C) ϕ(D) = ϕ(CD).\]

See `realify!`

for an in-place version, and `unrealify!`

to compute the inverse of $ϕ$.

`Manifolds.realify!`

— Function`realify!(Y::AbstractMatrix{<:Real}, X::AbstractMatrix{T𝔽}, 𝔽::AbstractNumbers)`

In-place version of `realify`

.

`realify!(Y::AbstractMatrix{<:Real}, X::AbstractMatrix{<:Complex}, ::typeof(ℂ))`

Given a complex matrix $X = A + iB ∈ ℂ^{n × n}$, compute its realified matrix $Y ∈ ℝ^{2n × 2n}$, written where

\[Y = \begin{pmatrix}A & -B \\ B & A \end{pmatrix}.\]

`ManifoldsBase.size_to_tuple`

— Function`size_to_tuple(::Type{S}) where S<:Tuple`

Converts a size given by `Tuple{N, M, ...}`

into a tuple `(N, M, ...)`

.

`Manifolds.select_from_tuple`

— Function`select_from_tuple(t::NTuple{N, Any}, positions::Val{P})`

Selects elements of tuple `t`

at positions specified by the second argument. For example `select_from_tuple(("a", "b", "c"), Val((3, 1, 1)))`

returns `("c", "a", "a")`

.

`Manifolds.unrealify!`

— Function`unrealify!(X::AbstractMatrix{T𝔽}, Y::AbstractMatrix{<:Real}, 𝔽::AbstractNumbers[, n])`

Given a real matrix $Y ∈ ℝ^{m × m}$, where $m = n \operatorname{dim}_𝔽$, and $\operatorname{dim}_𝔽$ is the `real_dimension`

of the number field $𝔽$, compute in-place its equivalent matrix $X ∈ 𝔽^{n × n}$. Note that this function does not check that $Y$ has a valid structure to be un-realified.

See `realify!`

for the inverse of this function.

`Manifolds.usinc`

— Function`usinc(θ::Real)`

Unnormalized version of `sinc`

function, i.e. $\operatorname{usinc}(θ) = \frac{\sin(θ)}{θ}$. This is equivalent to `sinc(θ/π)`

.

`Manifolds.usinc_from_cos`

— Function`usinc_from_cos(x::Real)`

Unnormalized version of `sinc`

function, i.e. $\operatorname{usinc}(θ) = \frac{\sin(θ)}{θ}$, computed from $x = cos(θ)$.

`Manifolds.vec2skew!`

— Function`vec2skew!(X, v, k)`

create a skew symmetric matrix inplace in `X`

of size $k\times k$ from a vector `v`

, for example for `v=[1,2,3]`

and `k=3`

this yields

```
[ 0 1 2;
-1 0 3;
-2 -3 0
]
```

`Manifolds.ziptuples`

— Function`ziptuples(a, b[, c[, d[, e]]])`

Zips tuples `a`

, `b`

, and remaining in a fast, type-stable way. If they have different lengths, the result is trimmed to the length of the shorter tuple.