Repository: JuliaManifolds/ManifoldsBase.jl
Pull request #32 (2020-03-28 16:06:32)

Parametrize Manifold by number field
This PR solves #30, though there is a point of discussion left.

Since the inner manifold of for example `EmbeddedManifold` should be the same as the embedded manifold (similar for array manifold), we have to type as follows

```julia
struct EmbeddedManifold{𝔽,MT<:Manifold{𝔽},NT<:Manifold,ET} <: AbstractEmbeddedManifold{ET,𝔽}
```

i.e. the field has to be placed before the manifold, while in all other cases (especially the abstract types, but also for the basic manifolds over at `Manifolds.jl`) the field is always the last parameter.
Note that eben for the abstract case, I went for the putting the field last.
 I feel this is a little inconsistent and should still be documented properly somewhere, if we do this change. 
What do you think? Is this inconcistency worth this (rather fundamental) change of the type?

Good news is, the main change despite this was, that all test manifolds had to be subtype to `Manifold{ℝ}` instead of just `Manifold`, but I feel that even makes the code a little nicer, since the definition directly helps to see whether the manifold is real or complex.


Patch:
diff --git a/Project.toml b/Project.toml
index 16873504..31c9281f 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
 name = "ManifoldsBase"
 uuid = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb"
 authors = ["Seth Axen <seth.axen@gmail.com>", "Mateusz Baran <mateuszbaran89@gmail.com>", "Ronny Bergmann <manopt@ronnybergmann.net>", "Antoine Levitt <antoine.levitt@gmail.com>"]
-version = "0.7.3"
+version = "0.8.0"
 
 [deps]
 LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
diff --git a/README.md b/README.md
index afed74fe..13cd4710 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,6 @@
 # ManifoldsBase.jl
-[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://juliamanifolds.github.io/Manifolds.jl/stable/interface.html)
-[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://juliamanifolds.github.io/Manifolds.jl/latest/interface.html)
-[![Build Status](https://travis-ci.org/JuliaManifolds/ManifoldsBase.jl.svg?branch=master)](https://travis-ci.org/JuliaManifolds/ManifoldsBase.jl/)
-[![codecov.io](http://codecov.io/github/JuliaManifolds/ManifoldsBase.jl/coverage.svg?branch=master)](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/)
+
+[![Build Status](https://travis-ci.org/JuliaManifolds/ManifoldsBase.jl.svg?branch=master)](https://travis-ci.org/JuliaManifolds/ManifoldsBase.jl/) [![codecov.io](http://codecov.io/github/JuliaManifolds/ManifoldsBase.jl/coverage.svg?branch=master)](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/)
 [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://julianlsolvers.github.io/Manifolds.jl/latest/)
 
 Basic interface for manifolds in Julia.
@@ -19,10 +17,10 @@ A further type to represent the field of quaternions (`ℍ`) can also be used.
 
 ## Bases
 
-Several different types of bases for a tangent space at `p` on a [`Manifold`](https://juliamanifolds.github.io/Manifolds.jl/stable/interface.html#ManifoldsBase.Manifold) are provided.
+Several different types of bases for a tangent space at `p` on a [`Manifold`](@ref) are provided.
 Methods are provided to obtain such a basis, to represent a tangent vector in a basis and to reconstruct a tangent vector from coefficients with respect to a basis.
 The last two can be performed without computing the complete basis.
-Further a basis can be cached and hence be reused, see [`CachedBasis`](https://juliamanifolds.github.io/Manifolds.jl/stable/interface.html#ManifoldsBase.CachedBasis).
+Further a basis can be cached and hence be reused, see [`CachedBasis`](https://juliamanifolds.github.io/Manifolds.jl/latest/interface.html#ManifoldsBase.CachedBasis).
 
 ## `DecoratorManifold`
 
@@ -35,7 +33,7 @@ passes to `:parent` in order to fill default values.
 ## `DefaultManifold`
 
 This interface includes a simple `DefaultManifold`, which is a reduced version
-of the [`Euclidean`](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/euclidean.html)
+of the [`Euclidean`](https://github.com/JuliaManifolds/Manifolds.jl/blob/master/src/Euclidean.jl)
 manifold from [`Manifolds.jl`](https://github.com/JuliaManifolds/Manifolds.jl),
 such that the interface functions can be tested.
 
@@ -46,15 +44,15 @@ This way a manifold can benefit from existing implementations.
 One example is the `TransparentIsometricEmbeddingType` where a manifold uses the metric,
 `inner`, from its embedding.
 
-## `ArrayManifold`
+## `ValidationManifold`
 
-The `ArrayManifold` further illustrates how one can also used types to
+The `ValidationManifold` further illustrates how one can also used types to
 represent points on a manifold, tangent vectors, and cotangent vectors,
 where values are encapsulated in a certain type.
 
-In general, `ArrayManifold` might be used for manifolds where these three types are represented
+In general, `ValidationManifold` might be used for manifolds where these three types are represented
 by more complicated data structures or when it is necessary to distinguish these
 by type.
 
 This adds a semantic layer to the interface, and the default implementation of
-`ArrayManifold` adds checks to all inputs and outputs of typed data.
+`ValidationManifold` adds checks to all inputs and outputs of typed data.
diff --git a/src/DecoratorManifold.jl b/src/DecoratorManifold.jl
index 6cd09338..fa58ac7e 100644
--- a/src/DecoratorManifold.jl
+++ b/src/DecoratorManifold.jl
@@ -80,10 +80,10 @@ end
 # Type
 #
 """
-    AbstractDecoratorManifold <: Manifold
+    AbstractDecoratorManifold{𝔽} <: Manifold{𝔽}
 
 An `AbstractDecoratorManifold` indicates that to some extent a manifold subtype
-decorates another manifold in the sense that it either
+decorates another [`Manifold`](@ref) in the sense that it either
 
 * it extends the functionality of a manifold with further features
 * it defines a new manifold that internally uses functions from the decorated manifold
@@ -99,7 +99,7 @@ Transparency of functions with respect to decorators can be specified using the
 [`@decorator_transparent_fallback`](@ref), [`@decorator_transparent_function`](@ref) and
 [`@decorator_transparent_signature`](@ref).
 """
-abstract type AbstractDecoratorManifold <: Manifold end
+abstract type AbstractDecoratorManifold{𝔽} <: Manifold{𝔽} end
 
 #
 # Macros
diff --git a/src/DefaultManifold.jl b/src/DefaultManifold.jl
index f97cbaea..8d47b321 100644
--- a/src/DefaultManifold.jl
+++ b/src/DefaultManifold.jl
@@ -9,7 +9,7 @@ This manifold further illustrates how to type your manifold points and tangent v
 that the interface does not require this, but it might be handy in debugging and educative
 situations to verify correctness of involved variabes.
 """
-struct DefaultManifold{T<:Tuple, 𝔽} <: Manifold where {T, 𝔽} end
+struct DefaultManifold{T<:Tuple, 𝔽} <: Manifold{𝔽} end
 DefaultManifold(n::Vararg{Int,N}; field = ℝ) where {N} = DefaultManifold{Tuple{n...}, field}()
 
 function check_manifold_point(M::DefaultManifold, p; kwargs...)
diff --git a/src/EmbeddedManifold.jl b/src/EmbeddedManifold.jl
index d1d3e83d..9a27feb1 100644
--- a/src/EmbeddedManifold.jl
+++ b/src/EmbeddedManifold.jl
@@ -6,7 +6,7 @@ A type used to specify properties of an [`AbstractEmbeddedManifold`](@ref).
 abstract type AbstractEmbeddingType end
 
 """
-    AbstractEmbeddedManifold{T<:AbstractEmbeddingType} <: AbstractDecoratorManifold
+    AbstractEmbeddedManifold{T<:AbstractEmbeddingType,𝔽} <: AbstractDecoratorManifold{𝔽}
 
 An abstract type for embedded manifolds, which acts as an [`AbstractDecoratorManifold`](@ref).
 The functions of the manifold that is embedded can hence be just passed on to the embedding.
@@ -16,8 +16,8 @@ This means, that technically an embedded manifold is a decorator for the embeddi
 functions of this type get, in the semi-transparent way of the
 [`AbstractDecoratorManifold`](@ref), passed on to the embedding.
 """
-abstract type AbstractEmbeddedManifold{T<:AbstractEmbeddingType} <:
-              AbstractDecoratorManifold end
+abstract type AbstractEmbeddedManifold{𝔽,T<:AbstractEmbeddingType} <:
+              AbstractDecoratorManifold{𝔽} end
 
 """
 DefaultEmbeddingType <: AbstractEmbeddingType
@@ -57,7 +57,7 @@ and logarithmic maps.
 struct TransparentIsometricEmbedding <: AbstractIsometricEmbeddingType end
 
 """
-    EmbeddedManifold{MT <: Manifold, NT <: Manifold, ET} <: AbstractEmbeddedManifold{ET}
+    EmbeddedManifold{𝔽, MT <: Manifold, NT <: Manifold, ET} <: AbstractEmbeddedManifold{𝔽, ET}
 
 A type to represent that a [`Manifold`](@ref) `M` of type `MT` is indeed an emebedded
 manifold and embedded into the manifold `N` of type `NT`.
@@ -77,7 +77,7 @@ Generate the `EmbeddedManifold` of the [`Manifold`](@ref) `M` into the
 [`Manifold`](@ref) `N` with [`AbstractEmbeddingType`](@ref) `e` that by default is the most
 transparent [`TransparentIsometricEmbedding`](@ref)
 """
-struct EmbeddedManifold{MT<:Manifold,NT<:Manifold,ET} <: AbstractEmbeddedManifold{ET}
+struct EmbeddedManifold{𝔽,MT<:Manifold{𝔽},NT<:Manifold,ET} <: AbstractEmbeddedManifold{𝔽,ET}
     manifold::MT
     embedding::NT
 end
@@ -85,8 +85,8 @@ function EmbeddedManifold(
     M::MT,
     N::NT,
     e::ET = TransparentIsometricEmbedding(),
-) where {MT<:Manifold,NT<:Manifold,ET<:AbstractEmbeddingType}
-    return EmbeddedManifold{MT,NT,ET}(M, N)
+) where {𝔽,MT<:Manifold{𝔽}, NT<:Manifold,ET<:AbstractEmbeddingType}
+    return EmbeddedManifold{𝔽,MT,NT,ET}(M, N)
 end
 
 """
@@ -131,7 +131,13 @@ end
 check that `embed(M,p,X)` is a valid tangent to `embed(p,X)`, where `check_base_point`
 determines whether the validity of `p` is checked, too.
 """
-function check_tangent_vector(M::AbstractEmbeddedManifold, p, X; check_base_point = true, kwargs...)
+function check_tangent_vector(
+    M::AbstractEmbeddedManifold,
+    p,
+    X;
+    check_base_point = true,
+    kwargs...,
+)
     if check_base_point
         mpe = check_manifold_point(M, p; kwargs...)
         mpe === nothing || return mpe
@@ -164,8 +170,8 @@ end
 
 function show(
     io::IO,
-    M::EmbeddedManifold{MT,NT,ET},
-) where {MT<:Manifold,NT<:Manifold,ET<:AbstractEmbeddingType}
+    M::EmbeddedManifold{𝔽,MT,NT,ET},
+) where {𝔽, MT<:Manifold{𝔽},NT<:Manifold,ET<:AbstractEmbeddingType}
     print(io, "EmbeddedManifold($(M.manifold), $(M.embedding), $(ET()))")
 end
 
@@ -221,9 +227,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(exp),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -235,9 +241,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(exp!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -284,9 +290,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(inner),
-    ::AbstractEmbeddedManifold{<:AbstractIsometricEmbeddingType},
+    ::AbstractEmbeddedManifold{𝔽,<:AbstractIsometricEmbeddingType},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -298,9 +304,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(inverse_retract),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -312,16 +318,16 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(inverse_retract!),
-    ::AbstractEmbeddedManifold{<:AbstractIsometricEmbeddingType},
+    ::AbstractEmbeddedManifold{𝔽,<:AbstractIsometricEmbeddingType},
     args...,
-)
+) where {𝔽}
     return Val(:parent)
 end
 function decorator_transparent_dispatch(
     ::typeof(inverse_retract!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 
@@ -334,9 +340,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(log),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -348,9 +354,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(log!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(::typeof(norm), ::AbstractEmbeddedManifold, args...)
@@ -358,9 +364,9 @@ function decorator_transparent_dispatch(::typeof(norm), ::AbstractEmbeddedManifo
 end
 function decorator_transparent_dispatch(
     ::typeof(norm),
-    ::AbstractEmbeddedManifold{<:AbstractIsometricEmbeddingType},
+    ::AbstractEmbeddedManifold{𝔽,<:AbstractIsometricEmbeddingType},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -379,9 +385,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(project!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -393,9 +399,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(project),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -407,9 +413,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(retract),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -421,16 +427,16 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(retract!),
-    ::AbstractEmbeddedManifold{<:AbstractIsometricEmbeddingType},
+    ::AbstractEmbeddedManifold{𝔽,<:AbstractIsometricEmbeddingType},
     args...,
-)
+) where {𝔽}
     return Val(:parent)
 end
 function decorator_transparent_dispatch(
     ::typeof(retract!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -442,9 +448,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(vector_transport_along),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -456,9 +462,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(vector_transport_along!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -470,9 +476,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(vector_transport_direction),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -484,9 +490,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(vector_transport_direction!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -498,9 +504,9 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(vector_transport_to),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
 function decorator_transparent_dispatch(
@@ -512,8 +518,8 @@ function decorator_transparent_dispatch(
 end
 function decorator_transparent_dispatch(
     ::typeof(vector_transport_to!),
-    ::AbstractEmbeddedManifold{<:TransparentIsometricEmbedding},
+    ::AbstractEmbeddedManifold{𝔽,<:TransparentIsometricEmbedding},
     args...,
-)
+) where {𝔽}
     return Val(:transparent)
 end
diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl
index c02bfaff..18d4c151 100644
--- a/src/ManifoldsBase.jl
+++ b/src/ManifoldsBase.jl
@@ -7,14 +7,21 @@ import Markdown: @doc_str
 using LinearAlgebra
 
 """
-    Manifold
+    Manifold{F}
 
 A manifold type. The `Manifold` is used to dispatch to different functions on a manifold,
 usually as the first argument of the function. Examples are the [`exp`](@ref)onential and
 [`log`](@ref)arithmic maps as well as more general functions that are built on them like the
 [`geodesic`](@ref).
+
+The manifold is parametrized by an [`AbstractNumbers`](@ref) to distinguish for example
+real (ℝ) and complex (ℂ) manifolds.
+
+For subtypes the preferred order of parameters is: size and simple value parameters,
+followed by the [`AbstractNumbers`](@ref) `field`, followed by data type parameters,
+which might depend on the abstract number field type.
 """
-abstract type Manifold end
+abstract type Manifold{𝔽} end
 
 """
     AbstractEstimationMethod
@@ -901,18 +908,21 @@ end
 include("numbers.jl")
 include("DecoratorManifold.jl")
 include("bases.jl")
-include("ArrayManifold.jl")
+include("ValidationManifold.jl")
 include("EmbeddedManifold.jl")
 include("DefaultManifold.jl")
 
 export Manifold, MPoint, TVector, CoTVector
-export AbstractDecoratorManifold, ArrayManifold, ArrayMPoint, ArrayTVector, ArrayCoTVector
+export AbstractDecoratorManifold
+export ValidationManifold, ValidationMPoint, ValidationTVector, ValidationCoTVector
 export AbstractEmbeddingType,
     TransparentIsometricEmbedding,
     DefaultIsometricEmbeddingType,
     DefaultEmbeddingType
 export AbstractEmbeddedManifold, EmbeddedManifold, TransparentIsometricEmbedding
 
+export OutOfInjectivityRadiusError
+
 export AbstractRetractionMethod,
     ExponentialRetraction,
     QRRetraction,
diff --git a/src/ArrayManifold.jl b/src/ValidationManifold.jl
similarity index 54%
rename from src/ArrayManifold.jl
rename to src/ValidationManifold.jl
index fce3c6c1..9c553d31 100644
--- a/src/ArrayManifold.jl
+++ b/src/ValidationManifold.jl
@@ -1,5 +1,5 @@
 """
-    ArrayManifold{M<:Manifold} <: Manifold
+    ValidationManifold{M<:Manifold} <: Manifold
 
 A manifold to encapsulate manifolds working on array representations of `MPoints` and
 `TVectors` in a transparent way, such that for these manifolds it's not necessary to
@@ -9,126 +9,126 @@ encapsulated/stripped automatically when needed.
 This manifold is a decorator for a manifold, i.e. it decorates a manifold `M` with types
 points, vectors, and covectors.
 """
-struct ArrayManifold{M<:Manifold} <: AbstractDecoratorManifold
+struct ValidationManifold{𝔽,M<:Manifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
     manifold::M
 end
 
 """
-    ArrayMPoint <: MPoint
+    ValidationMPoint <: MPoint
 
-Represent a point on an [`ArrayManifold`](@ref), i.e. on a manifold where data can be
+Represent a point on an [`ValidationManifold`](@ref), i.e. on a manifold where data can be
 represented by arrays. The array is stored internally and semantically. This distinguished
-the value from [`ArrayTVector`](@ref)s and [`ArrayCoTVector`](@ref)s.
+the value from [`ValidationTVector`](@ref)s and [`ValidationCoTVector`](@ref)s.
 """
-struct ArrayMPoint{V<:AbstractArray{<:Number}} <: MPoint
+struct ValidationMPoint{V<:AbstractArray{<:Number}} <: MPoint
     value::V
 end
 
 """
-    ArrayTVector <: TVector
+    ValidationTVector <: TVector
 
-Represent a tangent vector to a point on an [`ArrayManifold`](@ref), i.e. on a manifold
+Represent a tangent vector to a point on an [`ValidationManifold`](@ref), i.e. on a manifold
 where data can be represented by arrays. The array is stored internally and semantically.
-This distinguished the value from [`ArrayMPoint`](@ref)s and [`ArrayCoTVector`](@ref)s.
+This distinguished the value from [`ValidationMPoint`](@ref)s and [`ValidationCoTVector`](@ref)s.
 """
-struct ArrayTVector{V<:AbstractArray{<:Number}} <: TVector
+struct ValidationTVector{V<:AbstractArray{<:Number}} <: TVector
     value::V
 end
 
 """
-    ArrayCoTVector <: CoTVector
+    ValidationCoTVector <: CoTVector
 
-Represent a cotangent vector to a point on an [`ArrayManifold`](@ref), i.e. on a manifold
+Represent a cotangent vector to a point on an [`ValidationManifold`](@ref), i.e. on a manifold
 where data can be represented by arrays. The array is stored internally and semantically.
-This distinguished the value from [`ArrayMPoint`](@ref)s and [`ArrayTVector`](@ref)s.
+This distinguished the value from [`ValidationMPoint`](@ref)s and [`ValidationTVector`](@ref)s.
 """
-struct ArrayCoTVector{V<:AbstractArray{<:Number}} <: TVector
+struct ValidationCoTVector{V<:AbstractArray{<:Number}} <: TVector
     value::V
 end
 
-(+)(X::ArrayCoTVector, Y::ArrayCoTVector) = ArrayCoTVector(X.value + Y.value)
-(-)(X::ArrayCoTVector, Y::ArrayCoTVector) = ArrayCoTVector(X.value - Y.value)
-(-)(X::ArrayCoTVector) = ArrayCoTVector(-X.value)
-(*)(a::Number, X::ArrayCoTVector) = ArrayCoTVector(a * X.value)
+(+)(X::ValidationCoTVector, Y::ValidationCoTVector) = ValidationCoTVector(X.value + Y.value)
+(-)(X::ValidationCoTVector, Y::ValidationCoTVector) = ValidationCoTVector(X.value - Y.value)
+(-)(X::ValidationCoTVector) = ValidationCoTVector(-X.value)
+(*)(a::Number, X::ValidationCoTVector) = ValidationCoTVector(a * X.value)
 
-(+)(X::ArrayTVector, Y::ArrayTVector) = ArrayTVector(X.value + Y.value)
-(-)(X::ArrayTVector, Y::ArrayTVector) = ArrayTVector(X.value - Y.value)
-(-)(X::ArrayTVector) = ArrayTVector(-X.value)
-(*)(a::Number, X::ArrayTVector) = ArrayTVector(a * X.value)
+(+)(X::ValidationTVector, Y::ValidationTVector) = ValidationTVector(X.value + Y.value)
+(-)(X::ValidationTVector, Y::ValidationTVector) = ValidationTVector(X.value - Y.value)
+(-)(X::ValidationTVector) = ValidationTVector(-X.value)
+(*)(a::Number, X::ValidationTVector) = ValidationTVector(a * X.value)
 
 
-allocate(p::ArrayMPoint) = ArrayMPoint(allocate(p.value))
-allocate(p::ArrayMPoint, ::Type{T}) where {T} = ArrayMPoint(allocate(p.value, T))
-allocate(X::ArrayTVector) = ArrayTVector(allocate(X.value))
-allocate(X::ArrayTVector, ::Type{T}) where {T} = ArrayTVector(allocate(X.value, T))
+allocate(p::ValidationMPoint) = ValidationMPoint(allocate(p.value))
+allocate(p::ValidationMPoint, ::Type{T}) where {T} = ValidationMPoint(allocate(p.value, T))
+allocate(X::ValidationTVector) = ValidationTVector(allocate(X.value))
+allocate(X::ValidationTVector, ::Type{T}) where {T} = ValidationTVector(allocate(X.value, T))
 
 """
     array_value(p)
 
-Return the internal array value of an [`ArrayMPoint`](@ref), [`ArrayTVector`](@ref), or
-[`ArrayCoTVector`](@ref) if the value `p` is encapsulated as such. Return `p` if it is
+Return the internal array value of an [`ValidationMPoint`](@ref), [`ValidationTVector`](@ref), or
+[`ValidationCoTVector`](@ref) if the value `p` is encapsulated as such. Return `p` if it is
 already an array.
 """
 array_value(p::AbstractArray) = p
-array_value(p::ArrayMPoint) = p.value
-array_value(X::ArrayTVector) = X.value
-array_value(ξ::ArrayCoTVector) = ξ.value
+array_value(p::ValidationMPoint) = p.value
+array_value(X::ValidationTVector) = X.value
+array_value(ξ::ValidationCoTVector) = ξ.value
 
-function check_manifold_point(M::ArrayManifold, p; kwargs...)
+function check_manifold_point(M::ValidationManifold, p; kwargs...)
     return check_manifold_point(M.manifold, array_value(p); kwargs...)
 end
-function check_manifold_point(M::ArrayManifold, p::MPoint; kwargs...)
+function check_manifold_point(M::ValidationManifold, p::MPoint; kwargs...)
     return check_manifold_point(M.manifold, array_value(p); kwargs...)
 end
 
-function check_tangent_vector(M::ArrayManifold, p, X; kwargs...)
+function check_tangent_vector(M::ValidationManifold, p, X; kwargs...)
     return check_tangent_vector(M.manifold, array_value(p), array_value(X); kwargs...)
 end
-function check_tangent_vector(M::ArrayManifold, p::MPoint, X::TVector; kwargs...)
+function check_tangent_vector(M::ValidationManifold, p::MPoint, X::TVector; kwargs...)
     return check_tangent_vector(M.manifold, array_value(p), array_value(X); kwargs...)
 end
 
-convert(::Type{V}, X::ArrayCoTVector{V}) where {V<:AbstractArray{<:Number}} = X.value
-function convert(::Type{ArrayCoTVector{V}}, X::V) where {V<:AbstractArray{<:Number}}
-    return ArrayCoTVector{V}(X)
+convert(::Type{V}, X::ValidationCoTVector{V}) where {V<:AbstractArray{<:Number}} = X.value
+function convert(::Type{ValidationCoTVector{V}}, X::V) where {V<:AbstractArray{<:Number}}
+    return ValidationCoTVector{V}(X)
 end
-convert(::Type{M}, m::ArrayManifold{M}) where {M<:Manifold} = m.manifold
-convert(::Type{ArrayManifold{M}}, m::M) where {M<:Manifold} = ArrayManifold(m)
-convert(::Type{V}, p::ArrayMPoint{V}) where {V<:AbstractArray{<:Number}} = p.value
-convert(::Type{ArrayMPoint{V}}, x::V) where {V<:AbstractArray{<:Number}} = ArrayMPoint{V}(x)
-convert(::Type{V}, X::ArrayTVector{V}) where {V<:AbstractArray{<:Number}} = X.value
-function convert(::Type{ArrayTVector{V}}, X::V) where {V<:AbstractArray{<:Number}}
-    return ArrayTVector{V}(X)
+convert(::Type{M}, m::ValidationManifold{𝔽,M}) where {𝔽,M<:Manifold{𝔽}} = m.manifold
+convert(::Type{ValidationManifold{𝔽,M}}, m::M) where {𝔽,M<:Manifold{𝔽}} = ValidationManifold(m)
+convert(::Type{V}, p::ValidationMPoint{V}) where {V<:AbstractArray{<:Number}} = p.value
+convert(::Type{ValidationMPoint{V}}, x::V) where {V<:AbstractArray{<:Number}} = ValidationMPoint{V}(x)
+convert(::Type{V}, X::ValidationTVector{V}) where {V<:AbstractArray{<:Number}} = X.value
+function convert(::Type{ValidationTVector{V}}, X::V) where {V<:AbstractArray{<:Number}}
+    return ValidationTVector{V}(X)
 end
 
-function copyto!(p::ArrayMPoint, q::ArrayMPoint)
+function copyto!(p::ValidationMPoint, q::ValidationMPoint)
     copyto!(p.value, q.value)
     return p
 end
-function copyto!(p::ArrayCoTVector, q::ArrayCoTVector)
+function copyto!(p::ValidationCoTVector, q::ValidationCoTVector)
     copyto!(p.value, q.value)
     return p
 end
-function copyto!(Y::ArrayTVector, X::ArrayTVector)
+function copyto!(Y::ValidationTVector, X::ValidationTVector)
     copyto!(Y.value, X.value)
     return Y
 end
 
-function distance(M::ArrayManifold, p, q; kwargs...)
+function distance(M::ValidationManifold, p, q; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_manifold_point(M, q, true; kwargs...)
     return distance(M.manifold, array_value(p), array_value(q))
 end
 
-function exp(M::ArrayManifold, p, X; kwargs...)
+function exp(M::ValidationManifold, p, X; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_tangent_vector(M, p, X, true; kwargs...)
     y = exp(M.manifold, array_value(p), array_value(X))
     is_manifold_point(M, y, true; kwargs...)
-    return ArrayMPoint(y)
+    return ValidationMPoint(y)
 end
 
-function exp!(M::ArrayManifold, q, p, X; kwargs...)
+function exp!(M::ValidationManifold, q, p, X; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_tangent_vector(M, p, X, true; kwargs...)
     exp!(M.manifold, array_value(q), array_value(p), array_value(X))
@@ -136,7 +136,7 @@ function exp!(M::ArrayManifold, q, p, X; kwargs...)
     return q
 end
 
-function get_basis(M::ArrayManifold, p, B::AbstractBasis; kwargs...)
+function get_basis(M::ValidationManifold, p, B::AbstractBasis; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     Ξ = get_basis(M.manifold, array_value(p), B)
     bvectors = get_vectors(M, p, Ξ)
@@ -157,13 +157,13 @@ function get_basis(M::ArrayManifold, p, B::AbstractBasis; kwargs...)
     return Ξ
 end
 function get_basis(
-    M::ArrayManifold,
+    M::ValidationManifold,
     p,
-    B::Union{AbstractOrthogonalBasis,CachedBasis{<:AbstractOrthogonalBasis}};
+    B::Union{AbstractOrthogonalBasis,CachedBasis{𝔽,<:AbstractOrthogonalBasis{𝔽}}};
     kwargs...,
-)
+) where {𝔽}
     is_manifold_point(M, p, true; kwargs...)
-    Ξ = invoke(get_basis, Tuple{ArrayManifold,Any,AbstractBasis}, M, p, B; kwargs...)
+    Ξ = invoke(get_basis, Tuple{ValidationManifold,Any,AbstractBasis}, M, p, B; kwargs...)
     bvectors = get_vectors(M, p, Ξ)
     N = length(bvectors)
     for i = 1:N
@@ -177,13 +177,13 @@ function get_basis(
     return Ξ
 end
 function get_basis(
-    M::ArrayManifold,
+    M::ValidationManifold,
     p,
-    B::Union{AbstractOrthonormalBasis,CachedBasis{<:AbstractOrthonormalBasis}};
+    B::Union{AbstractOrthonormalBasis,CachedBasis{𝔽,<:AbstractOrthonormalBasis{𝔽}}};
     kwargs...,
-)
+) where {𝔽}
     is_manifold_point(M, p, true; kwargs...)
-    Ξ = invoke(get_basis, Tuple{ArrayManifold,Any,AbstractOrthogonalBasis}, M, p, B; kwargs...)
+    Ξ = invoke(get_basis, Tuple{ValidationManifold,Any,AbstractOrthogonalBasis}, M, p, B; kwargs...)
     bvectors = get_vectors(M, p, Ξ)
     N = length(bvectors)
     for i = 1:N
@@ -195,41 +195,41 @@ function get_basis(
     return Ξ
 end
 for BT in DISAMBIGUATION_BASIS_TYPES
-    if BT <: Union{AbstractOrthonormalBasis,CachedBasis{<:AbstractOrthonormalBasis}}
+    if BT <: Union{AbstractOrthonormalBasis,CachedBasis{𝔽,<:AbstractOrthonormalBasis} where 𝔽}
         CT = AbstractOrthonormalBasis
-    elseif BT <: Union{AbstractOrthogonalBasis,CachedBasis{<:AbstractOrthogonalBasis}}
+    elseif BT <: Union{AbstractOrthogonalBasis,CachedBasis{𝔽,<:AbstractOrthogonalBasis} where 𝔽}
         CT = AbstractOrthogonalBasis
     else
         CT = AbstractBasis
     end
     eval(quote
-        @invoke_maker 3 $CT get_basis(M::ArrayManifold, p, B::$BT; kwargs...)
+        @invoke_maker 3 $CT get_basis(M::ValidationManifold, p, B::$BT; kwargs...)
     end)
 end
 
-function get_coordinates(M::ArrayManifold, p, X, B::AbstractBasis; kwargs...)
+function get_coordinates(M::ValidationManifold, p, X, B::AbstractBasis; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_tangent_vector(M, p, X, true; kwargs...)
     return get_coordinates(M.manifold, p, X, B)
 end
 for BT in DISAMBIGUATION_BASIS_TYPES
     eval(quote
-        @invoke_maker 4 AbstractBasis get_coordinates(M::ArrayManifold, p, X, B::$BT; kwargs...)
+        @invoke_maker 4 AbstractBasis get_coordinates(M::ValidationManifold, p, X, B::$BT; kwargs...)
     end)
 end
 
-function get_coordinates!(M::ArrayManifold, Y, p, X, B::AbstractBasis; kwargs...)
+function get_coordinates!(M::ValidationManifold, Y, p, X, B::AbstractBasis; kwargs...)
     is_tangent_vector(M, p, X, true; kwargs...)
     get_coordinates!(M.manifold, Y, p, X, B)
     return Y
 end
 for BT in DISAMBIGUATION_BASIS_TYPES
     eval(quote
-        @invoke_maker 5 AbstractBasis get_coordinates!(M::ArrayManifold, Y, p, X, B::$BT; kwargs...)
+        @invoke_maker 5 AbstractBasis get_coordinates!(M::ValidationManifold, Y, p, X, B::$BT; kwargs...)
     end)
 end
 
-function get_vector(M::ArrayManifold, p, X, B::AbstractBasis; kwargs...)
+function get_vector(M::ValidationManifold, p, X, B::AbstractBasis; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     size(X) == (manifold_dimension(M),) || error("Incorrect size of coefficient vector X")
     Y = get_vector(M.manifold, p, X, B)
@@ -238,11 +238,11 @@ function get_vector(M::ArrayManifold, p, X, B::AbstractBasis; kwargs...)
 end
 for BT in DISAMBIGUATION_BASIS_TYPES
     eval(quote
-        @invoke_maker 4 AbstractBasis get_vector(M::ArrayManifold, p, X, B::$BT; kwargs...)
+        @invoke_maker 4 AbstractBasis get_vector(M::ValidationManifold, p, X, B::$BT; kwargs...)
     end)
 end
 
-function get_vector!(M::ArrayManifold, Y, p, X, B::AbstractBasis; kwargs...)
+function get_vector!(M::ValidationManifold, Y, p, X, B::AbstractBasis; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     size(X) == (manifold_dimension(M),) || error("Incorrect size of coefficient vector X")
     get_vector!(M.manifold, Y, p, X, B)
@@ -251,20 +251,20 @@ function get_vector!(M::ArrayManifold, Y, p, X, B::AbstractBasis; kwargs...)
 end
 for BT in DISAMBIGUATION_BASIS_TYPES
     eval(quote
-        @invoke_maker 5 AbstractBasis get_vector!(M::ArrayManifold, Y, p, X, B::$BT; kwargs...)
+        @invoke_maker 5 AbstractBasis get_vector!(M::ValidationManifold, Y, p, X, B::$BT; kwargs...)
     end)
 end
 
-injectivity_radius(M::ArrayManifold) = injectivity_radius(M.manifold)
-function injectivity_radius(M::ArrayManifold, method::AbstractRetractionMethod)
+injectivity_radius(M::ValidationManifold) = injectivity_radius(M.manifold)
+function injectivity_radius(M::ValidationManifold, method::AbstractRetractionMethod)
     return injectivity_radius(M.manifold, method)
 end
-function injectivity_radius(M::ArrayManifold, p; kwargs...)
+function injectivity_radius(M::ValidationManifold, p; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     return injectivity_radius(M.manifold, array_value(p))
 end
 function injectivity_radius(
-    M::ArrayManifold,
+    M::ValidationManifold,
     p,
     method::AbstractRetractionMethod;
     kwargs...,
@@ -272,42 +272,42 @@ function injectivity_radius(
     is_manifold_point(M, p, true; kwargs...)
     return injectivity_radius(M.manifold, array_value(p), method)
 end
-function injectivity_radius(M::ArrayManifold, method::ExponentialRetraction)
+function injectivity_radius(M::ValidationManifold, method::ExponentialRetraction)
     return injectivity_radius(M.manifold, method)
 end
-function injectivity_radius(M::ArrayManifold, p, method::ExponentialRetraction; kwargs...)
+function injectivity_radius(M::ValidationManifold, p, method::ExponentialRetraction; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     return injectivity_radius(M.manifold, array_value(p), method)
 end
 
-function inner(M::ArrayManifold, p, X, Y; kwargs...)
+function inner(M::ValidationManifold, p, X, Y; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_tangent_vector(M, p, X, true; kwargs...)
     is_tangent_vector(M, p, Y, true; kwargs...)
     return inner(M.manifold, array_value(p), array_value(X), array_value(Y))
 end
 
-function isapprox(M::ArrayManifold, p, q; kwargs...)
+function isapprox(M::ValidationManifold, p, q; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_manifold_point(M, q, true; kwargs...)
     return isapprox(M.manifold, array_value(p), array_value(q); kwargs...)
 end
-function isapprox(M::ArrayManifold, p, X, Y; kwargs...)
+function isapprox(M::ValidationManifold, p, X, Y; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_tangent_vector(M, p, X, true; kwargs...)
     is_tangent_vector(M, p, Y, true; kwargs...)
     return isapprox(M.manifold, array_value(p), array_value(X), array_value(Y); kwargs...)
 end
 
-function log(M::ArrayManifold, p, q; kwargs...)
+function log(M::ValidationManifold, p, q; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_manifold_point(M, q, true; kwargs...)
     X = log(M.manifold, array_value(p), array_value(q))
     is_tangent_vector(M, p, X, true; kwargs...)
-    return ArrayTVector(X)
+    return ValidationTVector(X)
 end
 
-function log!(M::ArrayManifold, X, p, q; kwargs...)
+function log!(M::ValidationManifold, X, p, q; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     is_manifold_point(M, q, true; kwargs...)
     log!(M.manifold, array_value(X), array_value(p), array_value(q))
@@ -315,29 +315,29 @@ function log!(M::ArrayManifold, X, p, q; kwargs...)
     return X
 end
 
-number_eltype(::Type{ArrayMPoint{V}}) where {V} = number_eltype(V)
-number_eltype(p::ArrayMPoint) = number_eltype(p.value)
-number_eltype(::Type{ArrayCoTVector{V}}) where {V} = number_eltype(V)
-number_eltype(p::ArrayCoTVector) = number_eltype(p.value)
-number_eltype(::Type{ArrayTVector{V}}) where {V} = number_eltype(V)
-number_eltype(X::ArrayTVector) = number_eltype(X.value)
+number_eltype(::Type{ValidationMPoint{V}}) where {V} = number_eltype(V)
+number_eltype(p::ValidationMPoint) = number_eltype(p.value)
+number_eltype(::Type{ValidationCoTVector{V}}) where {V} = number_eltype(V)
+number_eltype(p::ValidationCoTVector) = number_eltype(p.value)
+number_eltype(::Type{ValidationTVector{V}}) where {V} = number_eltype(V)
+number_eltype(X::ValidationTVector) = number_eltype(X.value)
 
-function project!(M::ArrayManifold, Y, p, X; kwargs...)
+function project!(M::ValidationManifold, Y, p, X; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     project!(M.manifold, array_value(Y), array_value(p), array_value(X))
     is_tangent_vector(M, p, Y, true; kwargs...)
     return Y
 end
 
-similar(p::ArrayMPoint) = ArrayMPoint(similar(p.value))
-similar(p::ArrayMPoint, ::Type{T}) where {T} = ArrayMPoint(similar(p.value, T))
-similar(p::ArrayCoTVector) = ArrayCoTVector(similar(p.value))
-similar(p::ArrayCoTVector, ::Type{T}) where {T} = ArrayCoTVector(similar(p.value, T))
-similar(X::ArrayTVector) = ArrayTVector(similar(X.value))
-similar(X::ArrayTVector, ::Type{T}) where {T} = ArrayTVector(similar(X.value, T))
+similar(p::ValidationMPoint) = ValidationMPoint(similar(p.value))
+similar(p::ValidationMPoint, ::Type{T}) where {T} = ValidationMPoint(similar(p.value, T))
+similar(p::ValidationCoTVector) = ValidationCoTVector(similar(p.value))
+similar(p::ValidationCoTVector, ::Type{T}) where {T} = ValidationCoTVector(similar(p.value, T))
+similar(X::ValidationTVector) = ValidationTVector(similar(X.value))
+similar(X::ValidationTVector, ::Type{T}) where {T} = ValidationTVector(similar(X.value, T))
 
 function vector_transport_along!(
-    M::ArrayManifold,
+    M::ValidationManifold,
     Y,
     p,
     X,
@@ -359,7 +359,7 @@ function vector_transport_along!(
 end
 
 function vector_transport_to!(
-    M::ArrayManifold,
+    M::ValidationManifold,
     Y,
     p,
     X,
@@ -382,7 +382,7 @@ function vector_transport_to!(
 end
 
 function vector_transport_to!(
-    M::ArrayManifold,
+    M::ValidationManifold,
     Y,
     p,
     X,
@@ -404,14 +404,14 @@ function vector_transport_to!(
     return Y
 end
 
-function zero_tangent_vector(M::ArrayManifold, p; kwargs...)
+function zero_tangent_vector(M::ValidationManifold, p; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     w = zero_tangent_vector(M.manifold, array_value(p))
     is_tangent_vector(M, p, w, true; kwargs...)
     return w
 end
 
-function zero_tangent_vector!(M::ArrayManifold, X, p; kwargs...)
+function zero_tangent_vector!(M::ValidationManifold, X, p; kwargs...)
     is_manifold_point(M, p, true; kwargs...)
     zero_tangent_vector!(M.manifold, array_value(X), array_value(p); kwargs...)
     is_tangent_vector(M, p, X, true; kwargs...)
diff --git a/src/bases.jl b/src/bases.jl
index b6bece01..fbd5d4e1 100644
--- a/src/bases.jl
+++ b/src/bases.jl
@@ -93,7 +93,7 @@ function ProjectedOrthonormalBasis(method::Symbol, 𝔽::AbstractNumbers = ℝ)
 end
 
 @doc raw"""
-    DiagonalizingOrthonormalBasis(frame_direction, 𝔽::AbstractNumbers = ℝ)
+    DiagonalizingOrthonormalBasis{𝔽,TV} <: AbstractOrthonormalBasis{𝔽}
 
 An orthonormal basis `Ξ` as a vector of tangent vectors (of length determined by
 [`manifold_dimension`](@ref)) in the tangent space that diagonalizes the curvature
@@ -101,12 +101,15 @@ tensor $R(u,v)w$ and where the direction `frame_direction` $v$ has curvature `0`
 
 The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be used
 for the vectors elements.
+
+# Constructor
+    DiagonalizingOrthonormalBasis(frame_direction, 𝔽::AbstractNumbers = ℝ)
 """
-struct DiagonalizingOrthonormalBasis{TV,𝔽} <: AbstractOrthonormalBasis{𝔽}
+struct DiagonalizingOrthonormalBasis{𝔽, TV} <: AbstractOrthonormalBasis{𝔽}
     frame_direction::TV
 end
 function DiagonalizingOrthonormalBasis(X, 𝔽::AbstractNumbers = ℝ)
-    return DiagonalizingOrthonormalBasis{typeof(X),𝔽}(X)
+    return DiagonalizingOrthonormalBasis{𝔽,typeof(X)}(X)
 end
 struct DiagonalizingBasisData{D,V,ET}
     frame_direction::D
@@ -118,17 +121,21 @@ const DefaultOrDiagonalizingBasis =
     Union{DefaultOrthonormalBasis,DiagonalizingOrthonormalBasis}
 
 """
-    CachedBasis(basis::AbstractBasis, data)
+    CachedBasis{𝔽,V,<:AbstractBasis{𝔽}} <: AbstractBasis{𝔽}
 
 A cached version of the given `basis` with precomputed basis vectors. The basis vectors
 are stored in `data`, either explicitly (like in cached variants of
 [`ProjectedOrthonormalBasis`](@ref)) or implicitly.
+
+# Constructor
+
+    CachedBasis(basis::AbstractBasis, data)
 """
-struct CachedBasis{B,V,𝔽} <: AbstractBasis{𝔽} where {BT<:AbstractBasis,V}
+struct CachedBasis{𝔽,B,V} <: AbstractBasis{𝔽} where {B<:AbstractBasis{𝔽},V}
     data::V
 end
 function CachedBasis(basis::B, data::V) where {V,𝔽,B<:AbstractBasis{𝔽}}
-    return CachedBasis{B,V,𝔽}(data)
+    return CachedBasis{𝔽,B,V}(data)
 end
 function CachedBasis(basis::CachedBasis) # avoid double encapsulation
     return basis
@@ -149,10 +156,10 @@ function get_vector end
 const all_uncached_bases = Union{AbstractBasis, DefaultBasis, DefaultOrthogonalBasis, DefaultOrthonormalBasis}
 const DISAMBIGUATION_BASIS_TYPES = [
     CachedBasis,
-    CachedBasis{<:AbstractBasis{ℝ}},
-    CachedBasis{<:AbstractBasis{ℂ}},
-    CachedBasis{<:AbstractOrthogonalBasis{ℝ}},
-    CachedBasis{<:AbstractOrthonormalBasis{ℝ}},
+    CachedBasis{ℝ,<:AbstractBasis{ℝ}},
+    CachedBasis{ℂ,<:AbstractBasis{ℂ}},
+    CachedBasis{ℝ,<:AbstractOrthogonalBasis{ℝ}},
+    CachedBasis{ℝ,<:AbstractOrthonormalBasis{ℝ}},
     DefaultBasis,
     DefaultOrthonormalBasis,
     DefaultOrthogonalBasis,
@@ -347,18 +354,12 @@ end
 function get_coordinates!(M::Manifold, Y, p, X, B::DefaultOrthogonalBasis)
     return get_coordinates!(M, Y, p, X, DefaultOrthonormalBasis(number_system(B)))
 end
-function get_coordinates!(
-    M::Manifold,
-    Y,
-    p,
-    X,
-    B::CachedBasis,
-)
-    if number_system(M) === number_system(B)
-        map!(vb -> real(inner(M, p, X, vb)), Y, get_vectors(M, p, B))
-    else
-        map!(vb -> conj(inner(M, p, X, vb)), Y, get_vectors(M, p, B))
-    end
+function get_coordinates!(M::Manifold{𝔾}, Y, p, X, C::CachedBasis{𝔽,B,V}) where {B,V,𝔾,𝔽}
+    map!(vb -> conj(inner(M, p, X, vb)), Y, get_vectors(M, p, C))
+    return Y
+end
+function get_coordinates!(M::Manifold{𝔽}, Y, p, X, C::CachedBasis{𝔽,B,V}) where {B,V,𝔽}
+    map!(vb -> real(inner(M, p, X, vb)), Y, get_vectors(M, p, C))
     return Y
 end
 
@@ -414,7 +415,7 @@ function get_vector!(M::Manifold, Y, p, X, B::CachedBasis)
     # quite convoluted but:
     #  1) preserves the correct `eltype`
     #  2) guarantees a reasonable array type `Y`
-    #     (for example scalar * `SizedArray` is an `SArray`)
+    #     (for example scalar * `SizedValidation` is an `SArray`)
     bvectors = get_vectors(M, p, B)
     if _get_vector_cache_broadcast(bvectors[1]) === Val(false)
         Xt = X[1] * bvectors[1]
@@ -449,8 +450,8 @@ function get_vectors(
     return _get_vectors(B)
 end
 #internal for directly cached basis i.e. those that are just arrays – used in show
-_get_vectors(B::CachedBasis{<:AbstractBasis,<:AbstractArray}) = B.data
-_get_vectors(B::CachedBasis{<:AbstractBasis,<:DiagonalizingBasisData}) = B.data.vectors
+_get_vectors(B::CachedBasis{𝔽,<:AbstractBasis,<:AbstractArray}) where {𝔽} = B.data
+_get_vectors(B::CachedBasis{𝔽,<:AbstractBasis,<:DiagonalizingBasisData}) where {𝔽} = B.data.vectors
 
 @doc raw"""
     hat(M::Manifold, p, Xⁱ)
@@ -524,11 +525,10 @@ end
 function show(
     io::IO,
     mime::MIME"text/plain",
-    B::CachedBasis{T,D,𝔽},
-) where {T<:AbstractBasis,D,𝔽}
+    B::CachedBasis{𝔽,T,D},
+) where {𝔽,T<:AbstractBasis,D}
     print(
         io,
-
         "$(T()) with $(length(_get_vectors(B))) basis vector$(length(_get_vectors(B)) == 1 ? "" : "s"):",
     )
     _show_basis_vector_range_noheader(
@@ -542,8 +542,8 @@ end
 function show(
     io::IO,
     mime::MIME"text/plain",
-    B::CachedBasis{T,D,𝔽},
-) where {T<:DiagonalizingOrthonormalBasis,D<:DiagonalizingBasisData,𝔽}
+    B::CachedBasis{𝔽,T,D},
+) where {𝔽,T<:DiagonalizingOrthonormalBasis,D<:DiagonalizingBasisData}
     vectors = _get_vectors(B)
     nv = length(vectors)
     sk = sprint(show, "text/plain", T(B.data.frame_direction), context = io, sizehint = 0)
diff --git a/src/numbers.jl b/src/numbers.jl
index e0d878dd..2acc663f 100644
--- a/src/numbers.jl
+++ b/src/numbers.jl
@@ -54,9 +54,8 @@ real_dimension(::ComplexNumbers) = 2
 real_dimension(::QuaternionNumbers) = 4
 
 @doc raw"""
-    number_system(M::Manifold)
+    number_system(M::Manifold{𝔽})
 
-Return the number system the manifold `M` is based on. The default of the number system is
-real-valued, i.e. `number_system(M) = ℝ`.
+Return the number system the manifold `M` is based on, i.e. the parameter `𝔽`.
 """
-number_system(M::Manifold) = ℝ
+number_system(M::Manifold{𝔽}) where {𝔽} = 𝔽


Test patch:
diff --git a/test/allocation.jl b/test/allocation.jl
index 1abd9a4f..9863a4d6 100644
--- a/test/allocation.jl
+++ b/test/allocation.jl
@@ -1,8 +1,9 @@
 using ManifoldsBase
 using Test
-using ManifoldsBase: combine_allocation_promotion_functions, allocation_promotion_function
+using ManifoldsBase: combine_allocation_promotion_functions, allocation_promotion_function, ℝ
 
-struct AllocManifold <: Manifold end
+struct AllocManifold{𝔽} <: Manifold{𝔽} end
+AllocManifold() = AllocManifold{ℝ}()
 
 function ManifoldsBase.exp!(::AllocManifold, v, x, y)
     v[1] .= x[1] .+ y[1]
diff --git a/test/bases.jl b/test/bases.jl
index 0d18b743..bf420f84 100644
--- a/test/bases.jl
+++ b/test/bases.jl
@@ -4,7 +4,7 @@ using ManifoldsBase: DefaultManifold, ℝ, ℂ
 using Test
 import Base: +, -, *, copyto!, isapprox
 
-struct ProjManifold <: Manifold end
+struct ProjManifold <: Manifold{ℝ} end
 
 ManifoldsBase.inner(::ProjManifold, x, w, v) = dot(w, v)
 ManifoldsBase.project!(S::ProjManifold, w, x, v) = (w .= v .- dot(x, v) .* x)
@@ -37,7 +37,8 @@ ManifoldsBase.get_vector(::ProjManifold, x, v, ::DefaultOrthonormalBasis) = reve
     ) === Val(:transparent)
 end
 
-struct ProjectionTestManifold <: Manifold end
+struct ProjectionTestManifold <: Manifold{ℝ} end
+
 ManifoldsBase.inner(::ProjectionTestManifold, ::Any, X, Y) = dot(X, Y)
 function ManifoldsBase.project!(::ProjectionTestManifold, Y, p, X)
     Y .= X .- dot(p, X) .* p
@@ -85,7 +86,7 @@ ManifoldsBase.manifold_dimension(::ProjectionTestManifold) = 100
     end
 end
 
-struct NonManifold <: Manifold end
+struct NonManifold <: Manifold{ℝ} end
 struct NonBasis <: ManifoldsBase.AbstractBasis{ℝ} end
 
 struct NonBroadcastBasisThing{T}
@@ -210,9 +211,9 @@ DiagonalizingBasisProxy() = DiagonalizingOrthonormalBasis([1.0, 0.0, 0.0])
         b = get_basis(M, pts[1], BT())
         if BT != DiagonalizingBasisProxy
             if pts[1] isa Array
-                @test isa(b, CachedBasis{BT{ℝ},Vector{Vector{Float64}},ℝ})
+                @test isa(b, CachedBasis{ℝ,BT{ℝ},Vector{Vector{Float64}}})
             else
-                @test isa(b, CachedBasis{BT{ℝ},Vector{NonBroadcastBasisThing{Vector{Float64}}},ℝ})
+                @test isa(b, CachedBasis{ℝ,BT{ℝ},Vector{NonBroadcastBasisThing{Vector{Float64}}}})
             end
         end
         @test get_basis(M, pts[1], b) === b
diff --git a/test/complex_manifold.jl b/test/complex_manifold.jl
index 026cf3f9..df849472 100644
--- a/test/complex_manifold.jl
+++ b/test/complex_manifold.jl
@@ -3,7 +3,7 @@ import ManifoldsBase: representation_size, manifold_dimension, inner
 using LinearAlgebra
 using Test
 
-struct ComplexEuclidean{N} <: Manifold where {N} end
+struct ComplexEuclidean{N} <: Manifold{ℂ} where {N} end
 ComplexEuclidean(n::Int) = ComplexEuclidean{n}()
 representation_size(::ComplexEuclidean{N}) where {N} = (N,)
 manifold_dimension(::ComplexEuclidean{N}) where {N} = 2N
diff --git a/test/decorator_manifold.jl b/test/decorator_manifold.jl
index 187efb26..04976a78 100644
--- a/test/decorator_manifold.jl
+++ b/test/decorator_manifold.jl
@@ -7,27 +7,27 @@ using ManifoldsBase: @decorator_transparent_function,
     @decorator_transparent_signature,
     is_decorator_transparent
 
-struct TestDecorator{M<:Manifold} <: AbstractDecoratorManifold
+struct TestDecorator{M<:Manifold{ℝ}} <: AbstractDecoratorManifold{ℝ}
     manifold::M
 end
 
-abstract type AbstractTestDecorator <: AbstractDecoratorManifold end
+abstract type AbstractTestDecorator <: AbstractDecoratorManifold{ℝ} end
 
-struct TestDecorator2{M<:Manifold} <: AbstractTestDecorator
+struct TestDecorator2{M<:Manifold{ℝ}} <: AbstractTestDecorator
     manifold::M
 end
 
-struct TestDecorator3{M<:Manifold} <: AbstractTestDecorator
+struct TestDecorator3{M<:Manifold{ℝ}} <: AbstractTestDecorator
     manifold::M
 end
 
-abstract type AbstractParentDecorator <: AbstractDecoratorManifold end
+abstract type AbstractParentDecorator <: AbstractDecoratorManifold{ℝ} end
 
-struct ChildDecorator{M<:Manifold} <: AbstractParentDecorator
+struct ChildDecorator{M<:Manifold{ℝ}} <: AbstractParentDecorator
     manifold::M
 end
 
-struct DefaultDecorator{M<:Manifold} <: AbstractDecoratorManifold
+struct DefaultDecorator{M<:Manifold{ℝ}} <: AbstractDecoratorManifold{ℝ}
     manifold::M
 end
 ManifoldsBase.default_decorator_dispatch(::DefaultDecorator) = Val(true)
@@ -138,7 +138,7 @@ decorator_transparent_dispatch(::typeof(test18), M::ChildDecorator, args...) = V
 
 @testset "Testing decorator manifold functions" begin
     M = ManifoldsBase.DefaultManifold(3)
-    A = ArrayManifold(M)
+    A = ValidationManifold(M)
 
     @test (@inferred base_manifold(M)) == M
     @test (@inferred base_manifold(A)) == M
diff --git a/test/domain_errors.jl b/test/domain_errors.jl
index ff036ebd..df835715 100644
--- a/test/domain_errors.jl
+++ b/test/domain_errors.jl
@@ -1,7 +1,7 @@
 using ManifoldsBase
 using Test
 
-struct ErrorTestManifold <: Manifold end
+struct ErrorTestManifold <: Manifold{ℝ} end
 
 function ManifoldsBase.check_manifold_point(::ErrorTestManifold, x)
     if any(u -> u < 0, x)
diff --git a/test/embedded_manifold.jl b/test/embedded_manifold.jl
index cfd77e39..df0d2b6a 100644
--- a/test/embedded_manifold.jl
+++ b/test/embedded_manifold.jl
@@ -1,4 +1,4 @@
-struct PlaneManifold <: AbstractEmbeddedManifold{TransparentIsometricEmbedding} end
+struct PlaneManifold <: AbstractEmbeddedManifold{ℝ,TransparentIsometricEmbedding} end
 
 ManifoldsBase.decorated_manifold(::PlaneManifold) = ManifoldsBase.DefaultManifold(3)
 ManifoldsBase.base_manifold(::PlaneManifold) = ManifoldsBase.DefaultManifold(2)
@@ -9,14 +9,14 @@ ManifoldsBase.project!(::PlaneManifold, q, p) = (q .= [p[1] p[2] 0.0])
 ManifoldsBase.project!(::PlaneManifold, Y, p, X) = (Y .= [X[1] X[2] 0.0])
 
 struct NotImplementedEmbeddedManifold <:
-       AbstractEmbeddedManifold{TransparentIsometricEmbedding} end
+       AbstractEmbeddedManifold{ℝ,TransparentIsometricEmbedding} end
 ManifoldsBase.decorated_manifold(::NotImplementedEmbeddedManifold) = ManifoldsBase.DefaultManifold(2)
 ManifoldsBase.base_manifold(::NotImplementedEmbeddedManifold) = ManifoldsBase.DefaultManifold(2)
 
 struct NotImplementedEmbeddedManifold2 <:
-       AbstractEmbeddedManifold{DefaultIsometricEmbeddingType} end
+       AbstractEmbeddedManifold{ℝ,DefaultIsometricEmbeddingType} end
 
-struct NotImplementedEmbeddedManifold3 <: AbstractEmbeddedManifold{DefaultEmbeddingType} end
+struct NotImplementedEmbeddedManifold3 <: AbstractEmbeddedManifold{ℝ,DefaultEmbeddingType} end
 
 @testset "Embedded Manifolds" begin
     @testset "EmbeddedManifold basic tests" begin
diff --git a/test/empty_manifold.jl b/test/empty_manifold.jl
index 9793f908..33c86b25 100644
--- a/test/empty_manifold.jl
+++ b/test/empty_manifold.jl
@@ -2,7 +2,7 @@ using ManifoldsBase
 
 using Test
 import Base: *
-struct NonManifold <: Manifold end
+struct NonManifold <: Manifold{ℝ} end
 struct NonMPoint <: MPoint end
 struct NonTVector <: TVector end
 struct NonCoTVector <: CoTVector end
diff --git a/test/runtests.jl b/test/runtests.jl
index 04db725c..077d3460 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -11,7 +11,7 @@ using ManifoldsBase
     include("empty_manifold.jl")
     include("default_manifold.jl")
     include("complex_manifold.jl")
-    include("array_manifold.jl")
+    include("validation_manifold.jl")
     include("embedded_manifold.jl")
     include("domain_errors.jl")
 end
diff --git a/test/array_manifold.jl b/test/validation_manifold.jl
similarity index 90%
rename from test/array_manifold.jl
rename to test/validation_manifold.jl
index 7cf7b5a1..938514c4 100644
--- a/test/array_manifold.jl
+++ b/test/validation_manifold.jl
@@ -2,31 +2,31 @@ using ManifoldsBase
 using LinearAlgebra
 using Test
 
-struct CustomArrayManifoldRetraction <: ManifoldsBase.AbstractRetractionMethod end
+struct CustomValidationManifoldRetraction <: ManifoldsBase.AbstractRetractionMethod end
 
 function ManifoldsBase.injectivity_radius(
     ::ManifoldsBase.DefaultManifold,
-    ::CustomArrayManifoldRetraction,
+    ::CustomValidationManifoldRetraction,
 )
     return 10.0
 end
 function ManifoldsBase.injectivity_radius(
     ::ManifoldsBase.DefaultManifold,
     p,
-    ::CustomArrayManifoldRetraction,
+    ::CustomValidationManifoldRetraction,
 )
     return 11.0
 end
 
-@testset "Array manifold" begin
+@testset "Validation manifold" begin
     M = ManifoldsBase.DefaultManifold(3)
-    A = ArrayManifold(M)
+    A = ValidationManifold(M)
     x = [1.0, 0.0, 0.0]
     y = 1 / sqrt(2) * [1.0, 1.0, 0.0]
     z = [0.0, 1.0, 0.0]
     v = log(M, x, y)
-    x2 = ArrayMPoint(x)
-    y2 = ArrayMPoint(y)
+    x2 = ValidationMPoint(x)
+    y2 = ValidationMPoint(y)
     v2 = log(A, x, y) # auto convert
     y2 = exp(A, x, v2)
     w = log(M, x, z)
@@ -40,7 +40,7 @@ end
         @test ManifoldsBase.representation_size(A) == (3,)
         @test manifold_dimension(A) == manifold_dimension(M)
         @test manifold_dimension(A) == 3
-        for T in [ArrayMPoint, ArrayTVector, ArrayCoTVector]
+        for T in [ValidationMPoint, ValidationTVector, ValidationCoTVector]
             p = T(x)
             @test convert(typeof(x), p) == x
             @test convert(typeof(p), y) == T(y)
@@ -62,7 +62,7 @@ end
         end
     end
     @testset "Vector functions" begin
-        for T in [ArrayTVector, ArrayCoTVector]
+        for T in [ValidationTVector, ValidationCoTVector]
             a = T(v)
             b = T(w)
             @test isapprox(A, a + b, T(v + w))
@@ -114,11 +114,11 @@ end
         @test injectivity_radius(A, x) == Inf
         @test injectivity_radius(A, ManifoldsBase.ExponentialRetraction()) == Inf
         @test injectivity_radius(A, x, ManifoldsBase.ExponentialRetraction()) == Inf
-        @test injectivity_radius(A, CustomArrayManifoldRetraction()) == 10
-        @test injectivity_radius(A, x, CustomArrayManifoldRetraction()) == 11
+        @test injectivity_radius(A, CustomValidationManifoldRetraction()) == 10
+        @test injectivity_radius(A, x, CustomValidationManifoldRetraction()) == 11
     end
 
-    @testset "ArrayManifold basis" begin
+    @testset "ValidationManifold basis" begin
         b = [Matrix(I,3,3)[:,i] for i=1:3]
         for BT in (DefaultBasis, DefaultOrthonormalBasis, DefaultOrthogonalBasis)
             @testset "Basis $(BT)" begin