Repository: JuliaManifolds/ManifoldsBase.jl
Pull request #59 (2021-01-17 17:23:05)

Bases of vector spaces
Some work on adding bases of cotangent spaces. This is supposed to solve problems with `flat!` and `sharp!` from this PR: https://github.com/JuliaManifolds/Manifolds.jl/pull/325 .

codecov[bot]: # [Codecov](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59?src=pr&el=h1) Report
> Merging [#59](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59?src=pr&el=desc) (0d1a585) into [master](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/commit/3a367fcd9d3a93e1613a18bade47b03c6c0c4592?el=desc) (3a367fc) will **decrease** coverage by `1.74%`.
> The diff coverage is `57.69%`.

[![Impacted file tree graph](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/graphs/tree.svg?width=650&height=150&src=pr&token=bQsBUU9knE)](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #59      +/-   ##
==========================================
- Coverage   99.61%   97.87%   -1.75%     
==========================================
  Files          10       11       +1     
  Lines        1298     1316      +18     
==========================================
- Hits         1293     1288       -5     
- Misses          5       28      +23     
```


| [Impacted Files](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/vector\_spaces.jl](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree#diff-c3JjL3ZlY3Rvcl9zcGFjZXMuamw=) | `0.00% <0.00%> (ø)` | |
| [src/bases.jl](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree#diff-c3JjL2Jhc2VzLmps) | `97.28% <78.57%> (-2.72%)` | :arrow_down: |
| [src/DecoratorManifold.jl](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree#diff-c3JjL0RlY29yYXRvck1hbmlmb2xkLmps) | `100.00% <100.00%> (ø)` | |
| [src/ManifoldsBase.jl](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree#diff-c3JjL01hbmlmb2xkc0Jhc2Uuamw=) | `98.17% <100.00%> (-1.23%)` | :arrow_down: |
| [src/PowerManifold.jl](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree#diff-c3JjL1Bvd2VyTWFuaWZvbGQuamw=) | `99.12% <100.00%> (+0.43%)` | :arrow_up: |
| [src/ValidationManifold.jl](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree#diff-c3JjL1ZhbGlkYXRpb25NYW5pZm9sZC5qbA==) | `100.00% <100.00%> (ø)` | |
| [src/vector\_transport.jl](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree#diff-c3JjL3ZlY3Rvcl90cmFuc3BvcnQuamw=) | `100.00% <100.00%> (ø)` | |
| ... and [1 more](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59?src=pr&el=footer). Last update [3a367fc...0d1a585](https://codecov.io/gh/JuliaManifolds/ManifoldsBase.jl/pull/59?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

mateuszbaran: > So this basically introduces a second parameter to the basis indicating what the basis is for? Looks ok to me, I just noticed a minor rephrasing of an error message we could do.

Yes, it's essentialy this, as well as moving `FVector` to ManifoldsBase.jl and adding a field in it for the basis. The new parameter for basis is not entirely necessary but it looked weird to have a basis and not knowing what kind of space it is a basis of.
kellertuer: Since it is backwards compatible, I think it's fine to add the parameter.
mateuszbaran: I just noticed that the vector space is indeed needed in the basis, to be able to correctly interpret coordinates in `get_vector`.
kellertuer: That's why I carefully asked – we can surely keep in that order and yes, ambiguity fighting is not nice, for sure. Thanks for the explanations.

> Yes, that's equivalent, I can use this instead of `<:Any`.

Great. I think that looks a little nicer

mateuszbaran: Non-implemented error messages are quite unhelpful when debugging wrong `invoke`s. I've removed one, maybe we should remove all of them?
kellertuer: We discussed that anyways following Lyndons notes, I would say it's reasonable to remove them, yes.
mateuszbaran: I think this is ready now. The one new coverage failure looks like a false positive.
mateuszbaran: While improving documentation I noticed that `vector_space_dimension` is referenced in ManifoldsBase.jl but defined in Manifolds.jl. I think we could change its signature to make it take separately manifold and vector space type and move it to ManifoldsBase.jl as well.
mateuszbaran: CI seems to fail for no reason :disappointed: .
mateuszbaran: Thanks! I'll still wait a bit with merging this, until https://github.com/JuliaManifolds/Manifolds.jl/pull/325#pullrequestreview-615177351 gets more polished.
mateuszbaran: Since this is breaking anyway, I used this PR to clean up `TVector/CoTVector` a bit here.
mateuszbaran: I also think about generalizing `is_tangent_vector` to any vector spaces, similarly to `zero_vector`. What do you think about renaming it to `is_vector`?
kellertuer: Can we maybe (to be nonbreaking) keep `is_tangent_vector` and map it to the more general variant of `is_vector` (I think with a tangent space argument inside?)

I don't like the term `AbstractMVector` what's an MVector? compared to MPoint it is a ManifoldVector? That does not make sense.
I would be fine with calling MPoint as `ManifoldPoint` for completeness, or `AbstractManifoldPoint` to be precise and consistent (MPoint was a name I introduced when I was only vaguely aware of naming schemes).
But this here should be an `AbstractTangentVector` I think, though carrying a type and especially the `Abstract` prefix seem really reasonable

And since we a re at it – if we are precise `Manifold` would also be `AbstractManifold`? But then – this is a lot of other changes for a PR that was concerned with vectors and bases ;)
mateuszbaran: > Can we maybe (to be nonbreaking) keep `is_tangent_vector` and map it to the more general variant of `is_vector` (I think with a tangent space argument inside?)

Yes, we can, though for `zero_vector` we decided earlier to just drop `zero_tangent_vector`, and this is a very similar situation.

> I don't like the term `AbstractMVector` what's an MVector? compared to MPoint it is a ManifoldVector? That does not make sense.
> I would be fine with calling MPoint as `ManifoldPoint` for completeness, or `AbstractManifoldPoint` to be precise and consistent (MPoint was a name I introduced when I was only vaguely aware of naming schemes).
> But this here should be an `AbstractTangentVector` I think, though carrying a type and especially the `Abstract` prefix seem really reasonable

> _edit_: Ah I missed that the abstract case is meant for both cotangent and tangents, then maybe `AbstractFibreVector` or `AbstractManifoldFibreVector` - does that sound reasonable?

I don't really like `AbstractMVector` either (naming is hard :sweat_smile:). It's supposed to be a vector from a fiber of a vector bundle, for example a tangent vector or a cotangent vector -- so that we won't have to repeat everything for tangent vectors, cotangent vectors and other more complicated constructs. 

I can surely change `MPoint` to `AbstractManifoldPoint`. Also `AbstractFibreVector` sounds nice.

> And since we a re at it – if we are precise `Manifold` would also be `AbstractManifold`? But then – this is a lot of other changes for a PR that was concerned with vectors and bases ;)

Sure, why not? If there are many breaking changes, I think it's better to bundle them together instead of making multiple breaking releases one after another :slightly_smiling_face: .

kellertuer: Ah sure, without the manifold, so just `AbstractFibreVector`is fine with me. And sure, if we break something, let's also break the manifold then ;)
mateuszbaran: So, what do we finally do about `is_tangent_vector`?
kellertuer: My small problem, alsready with `zero_vector` is, that the function name does not fully reflect, what the function is doing; while for the `zero_vector` I can see the consistency with all of Julia (and the first two arguments help), I feel the same for `is_vector` – the name itself does not reflect the main thing to check – that it's a tangent (or cotangent check then, too?). With that argument we could also rename `is_manifold_point` to `is_point`, since the `M` is in both cases anyway necessary to unterstand what the function is doing – for the `is_vector` even the `p` is necessary, to see where the tangent space is at, ok.

Maybe that's my concern, that the function name itself does not provide enough detail to understand what the function is doing, but you have to look for the whole signature.
A plut point is, that the function name is shorter. But also that even more yields, that we should then also switch to `is_point(M,p)`, too. The implicit knowledge vor the package would then be that vector means (co)tangent vector and point means point on the manifold.
mateuszbaran: Yes, `is_vector` is supposed to work on cotangent vectors as well.

Another option I can see here is renaming `zero_tangent_vector` -> `zero_fibre_vector` and `is_tangent_vector` -> `is_fibre_vector`.

Maybe @sethaxen has some opinion on naming as well?
mateuszbaran: OK. I think we don't need both `is_manifold_point` and `is_point` so I think we should pick one of them. `is_vector` is needed anyway and one remaining issue here is whether `is_vector` should call `is_tangent_vector` or the other way round. I think it will be extremely rare to overload `is_vector` (or `zero_vector`) for manifolds, for vector spaces other than the tangent space.
kellertuer: > OK. I think we don't need both `is_manifold_point` and `is_point` so I think we should pick one of them. `is_vector` is needed anyway and one remaining issue here is whether `is_vector` should call `is_tangent_vector` or the other way round. I think it will be extremely rare to overload `is_vector` (or `zero_vector`) for manifolds, for vector spaces other than the tangent space.

We overload/define `zero(_tangent)_vector!` quite often, I think; will that get obsolete, so will there be a good default?

So, I think if we drop backwards compatibility, then we should get rid of `is_tangent_vector` and `is_manifold_point` and just use `is_point` and `is_vector`, though both names are not completely self-descriptive (you have to have in mind point->manifold, vector->tangent space or any other fibre).
mateuszbaran: > We overload/define `zero(_tangent)_vector!` quite often, I think; will that get obsolete, so will there be a good default?

Yes, we have some overloads for tangent vectors. What I mean is that for any _other_ fibre there would usually be decent defaults. For tangent vectors it won't be obsolete.

> So, I think if we drop backwards compatibility, then we should get rid of `is_tangent_vector` and `is_manifold_point` and just use `is_point` and `is_vector`, though both names are not completely self-descriptive (you have to have in mind point->manifold, vector->tangent space or any other fibre).

This patch already breaks quite a bit so I wouldn't worry about backwards compatibility. I'll get rid of `is_tangent_vector` and `is_manifold_point` then.
kellertuer: Ok, let's just make sure, that @sethaxen at some point agrees, too; but I imagine he is also quite busy currently.
sethaxen: Sorry, there's a lot of discussion here. Can someone summarize the current proposal/disagreement?
kellertuer: I try to do summarise in order of renaming, since that was a trail of thoughts all this followed. The first is function names

1. `zero_tangent_vector` is renamed to `zero_vector` for consistency with Julia
2. `is_tangent_vector` is renamed to `is_vector` for consistency with 1.

Here my criticism is, that now the function name bears a little less information about what the function is doing, but if you have the full signature `is_vector(M, p, X)` it's fine. Even more these functions can now be used for any fibres – for the first maybe with an optional parameter, for the second depending on the type of `X`. So especially for co tangent vectors, these also should work.

3. `is_manifold_point` is renamed to `is_point` since that is then consistent with 2. – for both one now needs the implicit knowledge either that points are on manifolds and vectors are in tangent spaces or the full signature `is_point(M,p)`. For this I am ok, since I think I Walt to move to using `p ∈ M` anyways

Then we came across types

4. `MPoint` is renamed to `AbstractManifoldPoint`, since that is more informative and the `Abstract` is more consistent with the rest of our naming scheme
5. `TVector` and `CoTVector` get an abstract super type `AbstractFibreVector`, and while I writing this summary, we should actually call them `AbstractTangentVector` and `AbstractCoTangentVector`, respectively.

Finally since it is breaking everything anyways already here

6. `Manifold` is renamed to `AbstractManifold` to be more consistent.

4.-6. were actually names I introduced, I think, when I started Manopt.jl and when I was not completely aware of the Julia naming scheme, so I think, since this is breaking anyways and renames a lot, this is a good time to introduce this consistency.

That‘s the proposal and I think currently there is no disagreement really – I think there is a small tradeoff, that `is_vector` bears a little too less information (without the rest of the signature), but it is good that it then can be used on arbitrary fibers. 

But for sure, we would like to know your opinion, too.
mateuszbaran: That's a good summary :slightly_smiling_face: . I'd just add that I want to do some generalization here for arbitrary fibers because PR https://github.com/JuliaManifolds/Manifolds.jl/pull/325 finally makes it possible to handle them well.
kellertuer: I just noticed, since we are renaming everything to shorten names, what about changing `check_base_point` to `check_point` (and document that a little better in `check_tangent_vector`. What do you think?
mateuszbaran: Sure, that would be consistent with the other changes.
mateuszbaran: I've formatted code locally using JuliaFormatter 0.13.10. Here JuliaFormatter 0.14 was used and it crashed on parsing our files :confused: .
kellertuer: don‘t we have check_base mentioned here somewhere? I think at least is_vector (or check vector) should mention it in its doctoring. I will investigate the Julia<formatter issue tomorrow (can reproduce it even on master locally here).
mateuszbaran: I've submitted an issue: https://github.com/domluna/JuliaFormatter.jl/issues/410 .
mateuszbaran: What do you mean by `check_base`?
kellertuer: Cool, thanks for submitting that.

Ah yes, I mean `check_base_point`which we might want to call `check_point`? That should be mentioned maybe in both doc strings even.
mateuszbaran: OK, I see, that `check_base_point`. I think `check_base_point` is still fine? A little verbosity there doesn't look bad and the name is still correct.
mateuszbaran: I'm also thinking that we probably should just implement something like `_check_vector` for each manifold, and do something like
```julia
function check_vector(M::Manifold, p, X; check_base_point=true, kwargs...)
    if check_base_point
        mpe = check_point(M, p; kwargs...)
        mpe === nothing || return mpe
    end
    return _check_vector(M, p, X; kwargs...)
end
```
so that `check_vector` wouldn't have to duplicate the logic for checking the base point for each manifold.
kellertuer: Maybe the easier solution is to only have `check_base(_point)` for `is_vecor` (i.e. the high level interface) and not for `check_*`(i.e. the lower one)?
kellertuer: Cool, one can see on Manifolds.jl how much redundancy this removes; great!

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9d25799e..97a82b37 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,7 +11,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        julia-version: ["1.0", "1.4", "1.5"]
+        julia-version: ["1.0", "1.4", "1.5", "~1.6.0-0"]
         os: [ubuntu-latest, macOS-latest, windows-latest]
     steps:
       - uses: actions/checkout@v2
diff --git a/Project.toml b/Project.toml
index d7efd01d..0c0f0361 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.10.7"
+version = "0.11"
 
 [deps]
 LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
diff --git a/README.md b/README.md
index ab988c72..98194112 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ 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 [`AbstractManifold`](https://juliamanifolds.github.io/Manifolds.jl/stable/interface.html#ManifoldsBase.AbstractManifold) 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).
diff --git a/src/DecoratorManifold.jl b/src/DecoratorManifold.jl
index 5c0a174c..e2a81552 100644
--- a/src/DecoratorManifold.jl
+++ b/src/DecoratorManifold.jl
@@ -82,15 +82,15 @@ end
 # Type
 #
 """
-    AbstractDecoratorManifold{𝔽} <: Manifold{𝔽}
+    AbstractDecoratorManifold{𝔽} <: AbstractManifold{𝔽}
 
 An `AbstractDecoratorManifold` indicates that to some extent a manifold subtype
-decorates another [`Manifold`](@ref) in the sense that it either
+decorates another [`AbstractManifold`](@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
 
-with the main intent that several or most functions of [`Manifold`](@ref) are transparently
+with the main intent that several or most functions of [`AbstractManifold`](@ref) are transparently
 passed through to the manifold that is decorated. This way a function implemented for a
 decorator acts transparent on all other decorators, i.e. they just pass them through. If
 the decorator the function is implemented for is not among the decorators, an error is
@@ -101,7 +101,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{𝔽} <: AbstractManifold{𝔽} end
 
 #
 # Macros
@@ -264,7 +264,7 @@ macro decorator_transparent_function(fallback_case, input_ex)
                 return error(error_msg)
             end
             function ($fname)(
-                $(argnames[1])::Manifold,
+                $(argnames[1])::AbstractManifold,
                 $(callargs[2:end]...);
                 $(kwargs_list...),
             ) where {$(where_exprs...)}
@@ -418,7 +418,7 @@ end
 For any manifold that is a subtype of [`AbstractDecoratorManifold`](@ref), this function
 indicates whether a certain manifold `M` acts as a default decorator.
 
-This yields that _all_ functions are passed through to the decorated [`Manifold`](@ref)
+This yields that _all_ functions are passed through to the decorated [`AbstractManifold`](@ref)
 if `M` is indicated as default. This overwrites all [`is_decorator_transparent`](@ref)
 values.
 
@@ -430,7 +430,7 @@ the undecorated case.
 Value returned by this function is determined by [`default_decorator_dispatch`](@ref),
 which returns a `Val`-wrapped boolean for type stability of certain functions.
 """
-is_default_decorator(M::Manifold) = _extract_val(default_decorator_dispatch(M))
+is_default_decorator(M::AbstractManifold) = _extract_val(default_decorator_dispatch(M))
 
 """
     default_decorator_dispatch(M) -> Val
@@ -439,12 +439,12 @@ Return whether by default to dispatch the the inner manifold of
 a decorator (`Val(true)`) or not (`Val(false`). For more details see
 [`is_decorator_transparent`](@ref).
 """
-default_decorator_dispatch(M::Manifold) = Val(false)
+default_decorator_dispatch(M::AbstractManifold) = Val(false)
 
 """
-    is_decorator_transparent(f, M::Manifold, args...) -> Bool
+    is_decorator_transparent(f, M::AbstractManifold, args...) -> Bool
 
-Given a [`Manifold`](@ref) `M` and a function `f(M, args...)`, indicate, whether an
+Given a [`AbstractManifold`](@ref) `M` and a function `f(M, args...)`, indicate, whether an
 [`AbstractDecoratorManifold`](@ref) acts transparently for `f`. This means, it
 just passes through down to the internally stored manifold.
 Transparency is only defined for decorator manifolds and by default all decorators are transparent.
@@ -454,22 +454,22 @@ this behaviour, see [`decorator_transparent_dispatch`](@ref).
 If a decorator manifold is not in general transparent, it might still pass down
 for the case that a decorator is the default decorator, see [`is_default_decorator`](@ref).
 """
-function is_decorator_transparent(f, M::Manifold, args...)
+function is_decorator_transparent(f, M::AbstractManifold, args...)
     return decorator_transparent_dispatch(f, M, args...) === Val(:transparent)
 end
 
 """
-    decorator_transparent_dispatch(f, M::Manifold, args...) -> Val
+    decorator_transparent_dispatch(f, M::AbstractManifold, args...) -> Val
 
-Given a [`Manifold`](@ref) `M` and a function `f(M,args...)`, indicate, whether a
+Given a [`AbstractManifold`](@ref) `M` and a function `f(M,args...)`, indicate, whether a
 function is `Val(:transparent)` or `Val(:intransparent)` for the (decorated)
-[`Manifold`](@ref) `M`. Another possibility is, that for `M` and given `args...`
+[`AbstractManifold`](@ref) `M`. Another possibility is, that for `M` and given `args...`
 the function `f` should invoke `M`s `Val(:parent)` implementation, see
 [`@decorator_transparent_function`](@ref) for details.
 """
-decorator_transparent_dispatch(f, M::Manifold, args...) = Val(:transparent)
+decorator_transparent_dispatch(f, M::AbstractManifold, args...) = Val(:transparent)
 
-function _acts_transparently(f, M::Manifold, args...)
+function _acts_transparently(f, M::AbstractManifold, args...)
     return _val_or(
         default_decorator_dispatch(M),
         decorator_transparent_dispatch(f, M, args...),
@@ -489,25 +489,16 @@ function base_manifold(M::AbstractDecoratorManifold, depth::Val{N} = Val(-1)) wh
     return base_manifold(decorated_manifold(M), Val(N - 1))
 end
 
-@decorator_transparent_signature check_manifold_point(
-    M::AbstractDecoratorManifold,
-    p;
-    kwargs...,
-)
+@decorator_transparent_signature check_point(M::AbstractDecoratorManifold, p; kwargs...)
 
-@decorator_transparent_signature check_tangent_vector(
-    M::AbstractDecoratorManifold,
-    p,
-    X;
-    kwargs...,
-)
+@decorator_transparent_signature check_vector(M::AbstractDecoratorManifold, p, X; kwargs...)
 
 """
     decorated_manifold(M::AbstractDecoratorManifold)
 
 Return the manifold decorated by the decorator `M`. Defaults to `M.manifold`.
 """
-decorated_manifold(M::Manifold) = M.manifold
+decorated_manifold(M::AbstractManifold) = M.manifold
 
 @decorator_transparent_signature distance(M::AbstractDecoratorManifold, p, q)
 
@@ -725,5 +716,5 @@ decorated_manifold(M::Manifold) = M.manifold
     m::SchildsLadderTransport,
 )
 
-@decorator_transparent_signature zero_tangent_vector(M::AbstractDecoratorManifold, p)
-@decorator_transparent_signature zero_tangent_vector!(M::AbstractDecoratorManifold, X, p)
+@decorator_transparent_signature zero_vector(M::AbstractDecoratorManifold, p)
+@decorator_transparent_signature zero_vector!(M::AbstractDecoratorManifold, X, p)
diff --git a/src/DefaultManifold.jl b/src/DefaultManifold.jl
index 7f914196..119fd5fd 100644
--- a/src/DefaultManifold.jl
+++ b/src/DefaultManifold.jl
@@ -1,5 +1,5 @@
 """
-    DefaultManifold <: Manifold
+    DefaultManifold <: AbstractManifold
 
 This default manifold illustrates the main features of the interface and provides a skeleton
 to build one's own manifold. It is a simplified/shortened variant of `Euclidean` from
@@ -9,12 +9,12 @@ 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{𝔽} end
+struct DefaultManifold{T<:Tuple,𝔽} <: AbstractManifold{𝔽} end
 function DefaultManifold(n::Vararg{Int,N}; field = ℝ) where {N}
     return DefaultManifold{Tuple{n...},field}()
 end
 
-function check_manifold_point(M::DefaultManifold, p; kwargs...)
+function check_point(M::DefaultManifold, p; kwargs...)
     if size(p) != representation_size(M)
         return DomainError(
             size(p),
@@ -24,11 +24,7 @@ function check_manifold_point(M::DefaultManifold, p; kwargs...)
     return nothing
 end
 
-function check_tangent_vector(M::DefaultManifold, p, X; check_base_point = true, kwargs...)
-    if check_base_point
-        perr = check_manifold_point(M, p)
-        perr === nothing || return perr
-    end
+function check_vector(M::DefaultManifold, p, X; kwargs...)
     if size(X) != representation_size(M)
         return DomainError(
             size(X),
@@ -46,13 +42,21 @@ embed!(::DefaultManifold, Y, p, X) = copyto!(Y, X)
 
 exp!(::DefaultManifold, q, p, X) = (q .= p .+ X)
 
-function get_basis(M::DefaultManifold, p, B::DefaultOrthonormalBasis)
+function get_basis(
+    ::DefaultManifold,
+    p,
+    B::DefaultOrthonormalBasis{𝔽,TangentSpaceType},
+) where {𝔽}
     return CachedBasis(B, [_euclidean_basis_vector(p, i) for i in eachindex(p)])
 end
-function get_basis(M::DefaultManifold, p, B::DefaultOrthogonalBasis)
+function get_basis(
+    ::DefaultManifold,
+    p,
+    B::DefaultOrthogonalBasis{𝔽,TangentSpaceType},
+) where {𝔽}
     return CachedBasis(B, [_euclidean_basis_vector(p, i) for i in eachindex(p)])
 end
-function get_basis(M::DefaultManifold, p, B::DefaultBasis)
+function get_basis(::DefaultManifold, p, B::DefaultBasis{𝔽,TangentSpaceType}) where {𝔽}
     return CachedBasis(B, [_euclidean_basis_vector(p, i) for i in eachindex(p)])
 end
 function get_basis(M::DefaultManifold, p, B::DiagonalizingOrthonormalBasis)
@@ -61,12 +65,24 @@ function get_basis(M::DefaultManifold, p, B::DiagonalizingOrthonormalBasis)
     return CachedBasis(B, DiagonalizingBasisData(B.frame_direction, eigenvalues, vecs))
 end
 
-function get_coordinates!(M::DefaultManifold, Y, p, X, B::DefaultOrthonormalBasis)
+function get_coordinates!(
+    M::DefaultManifold,
+    Y,
+    p,
+    X,
+    ::DefaultOrthonormalBasis{ℝ,TangentSpaceType},
+)
     copyto!(Y, reshape(X, manifold_dimension(M)))
     return Y
 end
 
-function get_vector!(M::DefaultManifold, Y, p, X, B::DefaultOrthonormalBasis)
+function get_vector!(
+    M::DefaultManifold,
+    Y,
+    p,
+    X,
+    ::DefaultOrthonormalBasis{ℝ,TangentSpaceType},
+)
     copyto!(Y, reshape(X, representation_size(M)))
     return Y
 end
@@ -126,4 +142,4 @@ function vector_transport_to!(M::DefaultManifold, Y, p, X, q, ::ProjectionTransp
     return project!(M, Y, q, X)
 end
 
-zero_tangent_vector!(::DefaultManifold, Y, p) = fill!(Y, 0)
+zero_vector!(::DefaultManifold, Y, p) = fill!(Y, 0)
diff --git a/src/EmbeddedManifold.jl b/src/EmbeddedManifold.jl
index 6fc6ddbb..5106603e 100644
--- a/src/EmbeddedManifold.jl
+++ b/src/EmbeddedManifold.jl
@@ -20,12 +20,12 @@ transparently used from the embedding, for example the [`inner`](@ref) product o
 compuation onwards to the embedding (note again, that no [`embed`](@ref) is required)
 and hence avoids to reimplement these methods in the manifold that is embedded.
 
-This should be used for example for [`check_manifold_point`](@ref) or [`check_tangent_vector`](@ref),
+This should be used for example for [`check_point`](@ref) or [`check_vector`](@ref),
 which should first invoke the test of the embedding and then test further constraints
 the representation in the embedding has for these points to be valid.
 
 Technically this is realised by making the [`AbstractEmbeddedManifold`](@ref) is a decorator
-for the [`Manifold`](@ref)s that are subtypes.
+for the [`AbstractManifold`](@ref)s that are subtypes.
 """
 abstract type AbstractEmbeddedManifold{𝔽,T<:AbstractEmbeddingType} <:
               AbstractDecoratorManifold{𝔽} end
@@ -68,9 +68,9 @@ and logarithmic maps.
 struct TransparentIsometricEmbedding <: AbstractIsometricEmbeddingType end
 
 """
-    EmbeddedManifold{𝔽, MT <: Manifold, NT <: Manifold} <: AbstractDecoratorManifold{𝔽}
+    EmbeddedManifold{𝔽, MT <: AbstractManifold, NT <: AbstractManifold} <: AbstractDecoratorManifold{𝔽}
 
-A type to represent an explicit embedding of a [`Manifold`](@ref) `M` of type `MT` embedded
+A type to represent an explicit embedding of a [`AbstractManifold`](@ref) `M` of type `MT` embedded
 into a manifold `N` of type `NT`.
 
 !!!note
@@ -88,10 +88,11 @@ into a manifold `N` of type `NT`.
 
     EmbeddedManifold(M, N)
 
-Generate the `EmbeddedManifold` of the [`Manifold`](@ref) `M` into the
-[`Manifold`](@ref) `N`.
+Generate the `EmbeddedManifold` of the [`AbstractManifold`](@ref) `M` into the
+[`AbstractManifold`](@ref) `N`.
 """
-struct EmbeddedManifold{𝔽,MT<:Manifold{𝔽},NT<:Manifold} <: AbstractDecoratorManifold{𝔽}
+struct EmbeddedManifold{𝔽,MT<:AbstractManifold{𝔽},NT<:AbstractManifold} <:
+       AbstractDecoratorManifold{𝔽}
     manifold::MT
     embedding::NT
 end
@@ -137,14 +138,14 @@ base_manifold(M::EmbeddedManifold, d::Val{N} = Val(-1)) where {N} = M.manifold
 
 
 """
-    check_manifold_point(M::AbstractEmbeddedManifold, p; kwargs)
+    check_point(M::AbstractEmbeddedManifold, p; kwargs)
 
 check whether a point `p` is a valid point on the [`AbstractEmbeddedManifold`](@ref),
 i.e. that `embed(M, p)` is a valid point on the embedded manifold.
 """
-function check_manifold_point(M::AbstractEmbeddedManifold, p; kwargs...)
+function check_point(M::AbstractEmbeddedManifold, p; kwargs...)
     return invoke(
-        check_manifold_point,
+        check_point,
         Tuple{typeof(get_embedding(M)),typeof(p)},
         get_embedding(M),
         p;
@@ -153,29 +154,17 @@ function check_manifold_point(M::AbstractEmbeddedManifold, p; kwargs...)
 end
 
 """
-    check_tangent_vector(M::AbstractEmbeddedManifold, p, X; check_base_point = true, kwargs...)
+    check_vector(M::AbstractEmbeddedManifold, p, X; kwargs...)
 
-check that `embed(M, p, X)` is a valid tangent to `embed(M, p)`, where `check_base_point`
-determines whether the validity of `p` is checked, too.
+Check that `embed(M, p, X)` is a valid tangent to `embed(M, p)`.
 """
-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
-    end
+function check_vector(M::AbstractEmbeddedManifold, p, X; kwargs...)
     return invoke(
-        check_tangent_vector,
+        check_vector,
         Tuple{typeof(get_embedding(M)),typeof(p),typeof(X)},
         get_embedding(M),
         p,
         X;
-        check_base_point = check_base_point,
         kwargs...,
     )
 end
@@ -194,7 +183,7 @@ embed!(::AbstractEmbeddedManifold, Y, p, X) = copyto!(Y, X)
 """
     get_embedding(M::AbstractEmbeddedManifold)
 
-Return the [`Manifold`](@ref) `N` an [`AbstractEmbeddedManifold`](@ref) is embedded into.
+Return the [`AbstractManifold`](@ref) `N` an [`AbstractEmbeddedManifold`](@ref) is embedded into.
 """
 get_embedding(::AbstractEmbeddedManifold)
 
@@ -205,7 +194,7 @@ end
 """
     get_embedding(M::EmbeddedManifold)
 
-Return the [`Manifold`](@ref) `N` an [`EmbeddedManifold`](@ref) is embedded into.
+Return the [`AbstractManifold`](@ref) `N` an [`EmbeddedManifold`](@ref) is embedded into.
 """
 get_embedding(::EmbeddedManifold)
 
@@ -219,7 +208,10 @@ function project(M::EmbeddedManifold, p)
     return q
 end
 
-function show(io::IO, M::EmbeddedManifold{𝔽,MT,NT}) where {𝔽,MT<:Manifold{𝔽},NT<:Manifold}
+function show(
+    io::IO,
+    M::EmbeddedManifold{𝔽,MT,NT},
+) where {𝔽,MT<:AbstractManifold{𝔽},NT<:AbstractManifold}
     return print(io, "EmbeddedManifold($(M.manifold), $(M.embedding))")
 end
 
@@ -227,7 +219,7 @@ function default_decorator_dispatch(::EmbeddedManifold)
     return Val(true)
 end
 
-@doc doc"""
+@doc raw"""
     default_embedding_dispatch(M::AbstractEmbeddedManifold)
 
 This method indicates that an [`AbstractEmbeddedManifold`](@ref) is the default
@@ -239,14 +231,14 @@ By default this is set to `Val(false)`.
 default_embedding_dispatch(M::AbstractEmbeddedManifold) = Val(false)
 
 function decorator_transparent_dispatch(
-    ::typeof(check_manifold_point),
+    ::typeof(check_point),
     ::AbstractEmbeddedManifold,
     args...,
 )
     return Val(:intransparent)
 end
 function decorator_transparent_dispatch(
-    ::typeof(check_tangent_vector),
+    ::typeof(check_vector),
     ::AbstractEmbeddedManifold,
     args...,
 )
diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl
index 3f8d7539..1a05e867 100644
--- a/src/ManifoldsBase.jl
+++ b/src/ManifoldsBase.jl
@@ -21,9 +21,9 @@ import Markdown: @doc_str
 using LinearAlgebra
 
 """
-    Manifold{F}
+    AbstractManifold{F}
 
-A manifold type. The `Manifold` is used to dispatch to different functions on a manifold,
+A manifold type. The `AbstractManifold` 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).
@@ -35,7 +35,7 @@ For subtypes the preferred order of parameters is: size and simple value paramet
 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 AbstractManifold{𝔽} end
 
 """
     AbstractEstimationMethod
@@ -69,7 +69,7 @@ struct ExponentialRetraction <: AbstractRetractionMethod end
     PolarRetraction <: AbstractRetractionMethod
 
 Retractions that are based on singular value decompositions of the matrix / matrices
-for point and tangent vector on a [`Manifold`](@ref)
+for point and tangent vector on a [`AbstractManifold`](@ref)
 """
 struct PolarRetraction <: AbstractRetractionMethod end
 
@@ -84,7 +84,7 @@ struct ProjectionRetraction <: AbstractRetractionMethod end
     QRRetraction <: AbstractRetractionMethod
 
 Retractions that are based on a QR decomposition of the
-matrix / matrices for point and tangent vector on a [`Manifold`](@ref)
+matrix / matrices for point and tangent vector on a [`AbstractManifold`](@ref)
 """
 struct QRRetraction <: AbstractRetractionMethod end
 
@@ -99,7 +99,7 @@ struct LogarithmicInverseRetraction <: AbstractInverseRetractionMethod end
     PolarInverseRetraction <: AbstractInverseRetractionMethod
 
 Inverse retractions that are based on a singular value decomposition of the
-matrix / matrices for point and tangent vector on a [`Manifold`](@ref)
+matrix / matrices for point and tangent vector on a [`AbstractManifold`](@ref)
 """
 struct PolarInverseRetraction <: AbstractInverseRetractionMethod end
 
@@ -114,19 +114,19 @@ struct ProjectionInverseRetraction <: AbstractInverseRetractionMethod end
     QRInverseRetraction <: AbstractInverseRetractionMethod
 
 Inverse retractions that are based on a QR decomposition of the
-matrix / matrices for point and tangent vector on a [`Manifold`](@ref)
+matrix / matrices for point and tangent vector on a [`AbstractManifold`](@ref)
 """
 struct QRInverseRetraction <: AbstractInverseRetractionMethod end
 
 """
-    MPoint
+    AbstractManifoldPoint
 
-Type for a point on a manifold. While a [`Manifold`](@ref) does not necessarily require this
+Type for a point on a manifold. While a [`AbstractManifold`](@ref) does not necessarily require this
 type, for example when it is implemented for `Vector`s or `Matrix` type elements, this type
 can be used for more complicated representations, semantic verification, or even dispatch
 for different representations of points on a manifold.
 """
-abstract type MPoint end
+abstract type AbstractManifoldPoint end
 
 """
     OutOfInjectivityRadiusError
@@ -136,28 +136,6 @@ An error thrown when a function (for example [`log`](@ref)arithmic map or
 """
 struct OutOfInjectivityRadiusError <: Exception end
 
-"""
-    TVector
-
-Type for a tangent vector of a manifold. While a [`Manifold`](@ref) does not necessarily
-require this type, for example when it is implemented for `Vector`s or `Matrix` type
-elements, this type can be used for more complicated representations, semantic verification,
-or even dispatch for different representations of tangent vectors and their types on a
-manifold.
-"""
-abstract type TVector end
-
-"""
-    CoTVector
-
-Type for a cotangent vector of a manifold. While a [`Manifold`](@ref) does not necessarily
-require this type, for example when it is implemented for `Vector`s or `Matrix` type
-elements, this type can be used for more complicated representations, semantic verification,
-or even dispatch for different representations of cotangent vectors and their types on a
-manifold.
-"""
-abstract type CoTVector end
-
 """
     allocate(a)
     allocate(a, dims::Integer...)
@@ -186,84 +164,85 @@ allocate(a::NTuple{N,AbstractArray} where {N}) = map(allocate, a)
 allocate(a::NTuple{N,AbstractArray} where {N}, T::Type) = map(t -> allocate(t, T), a)
 
 """
-    allocate_result(M::Manifold, f, x...)
+    allocate_result(M::AbstractManifold, f, x...)
 
-Allocate an array for the result of function `f` on [`Manifold`](@ref) `M` and arguments
+Allocate an array for the result of function `f` on [`AbstractManifold`](@ref) `M` and arguments
 `x...` for implementing the non-modifying operation using the modifying operation.
 
 Usefulness of passing a function is demonstrated by methods that allocate results of musical
 isomorphisms.
 """
-function allocate_result(M::Manifold, f, x...)
+function allocate_result(M::AbstractManifold, f, x...)
     T = allocate_result_type(M, f, x)
     return allocate(x[1], T)
 end
 
 """
-    allocate_result_type(M::Manifold, f, args::NTuple{N,Any}) where N
+    allocate_result_type(M::AbstractManifold, f, args::NTuple{N,Any}) where N
 
 Return type of element of the array that will represent the result of function `f` and the
-[`Manifold`](@ref) `M` on given arguments `args` (passed as a tuple).
+[`AbstractManifold`](@ref) `M` on given arguments `args` (passed as a tuple).
 """
-function allocate_result_type(M::Manifold, f, args::NTuple{N,Any}) where {N}
+function allocate_result_type(M::AbstractManifold, f, args::NTuple{N,Any}) where {N}
     return typeof(mapreduce(eti -> one(number_eltype(eti)), +, args))
 end
 
 """
-    angle(M::Manifold, p, X, Y)
+    angle(M::AbstractManifold, p, X, Y)
 
 Compute the angle between tangent vectors `X` and `Y` at point `p` from the
-[`Manifold`](@ref) `M` with respect to the inner product from [`inner`](@ref).
+[`AbstractManifold`](@ref) `M` with respect to the inner product from [`inner`](@ref).
 """
-angle(M::Manifold, p, X, Y) = acos(real(inner(M, p, X, Y)) / norm(M, p, X) / norm(M, p, Y))
+function angle(M::AbstractManifold, p, X, Y)
+    return acos(real(inner(M, p, X, Y)) / norm(M, p, X) / norm(M, p, Y))
+end
 
 """
-    base_manifold(M::Manifold, depth = Val(-1))
+    base_manifold(M::AbstractManifold, depth = Val(-1))
 
-Return the internally stored [`Manifold`](@ref) for decorated manifold `M` and the base
+Return the internally stored [`AbstractManifold`](@ref) for decorated manifold `M` and the base
 manifold for vector bundles or power manifolds. The optional parameter `depth` can be used
-to remove only the first `depth` many decorators and return the [`Manifold`](@ref) from that
+to remove only the first `depth` many decorators and return the [`AbstractManifold`](@ref) from that
 level, whether its decorated or not. Any negative value deactivates this depth limit.
 """
-base_manifold(M::Manifold, depth = Val(-1)) = M
+base_manifold(M::AbstractManifold, depth = Val(-1)) = M
 
 """
-    check_manifold_point(M::Manifold, p; kwargs...) -> Union{Nothing,String}
+    check_point(M::AbstractManifold, p; kwargs...) -> Union{Nothing,String}
 
-Return `nothing` when `p` is a point on the [`Manifold`](@ref) `M`. Otherwise, return an
+Return `nothing` when `p` is a point on the [`AbstractManifold`](@ref) `M`. Otherwise, return an
 error with description why the point does not belong to manifold `M`.
 
-By default, `check_manifold_point` returns `nothing`, i.e. if no checks are implemented, the
-assumption is to be optimistic for a point not deriving from the [`MPoint`](@ref) type.
+By default, `check_point` returns `nothing`, i.e. if no checks are implemented, the
+assumption is to be optimistic for a point not deriving from the [`AbstractManifoldPoint`](@ref) type.
 """
-check_manifold_point(M::Manifold, p; kwargs...) = nothing
+check_point(M::AbstractManifold, p; kwargs...) = nothing
 
 """
-    check_tangent_vector(M::Manifold, p, X; kwargs...) -> Union{Nothing,String}
+    check_vector(M::AbstractManifold, p, X; kwargs...) -> Union{Nothing,String}
 
 Check whether `X` is a valid tangent vector in the tangent space of `p` on the
-[`Manifold`](@ref) `M`. An implementation should first call [`check_manifold_point(M, p;
-kwargs...)`](@ref) and then validate `X`. If it is not a tangent vector, an error string
-should be returned.
+[`AbstractManifold`](@ref) `M`. An implementation does not have to validate the point `p`.
+If it is not a tangent vector, an error string should be returned.
 
-By default, `check_tangent_vector` returns `nothing`, i.e. if no checks are implemented, the
+By default, `check_vector` returns `nothing`, i.e. if no checks are implemented, the
 assumption is to be optimistic for tangent vectors not deriving from the [`TVector`](@ref)
 type.
 """
-check_tangent_vector(M::Manifold, p, X; kwargs...) = nothing
+check_vector(M::AbstractManifold, p, X; kwargs...) = nothing
 
 """
-    check_size(M::Manifold, p)
-    check_size(M::Manifold, p, X)
+    check_size(M::AbstractManifold, p)
+    check_size(M::AbstractManifold, p, X)
 
-Check whether `p` has the right [`representation_size`](@ref) for a [`Manifold`](@ref) `M`.
+Check whether `p` has the right [`representation_size`](@ref) for a [`AbstractManifold`](@ref) `M`.
 Additionally if a tangent vector is given, both `p` and `X` are checked to be of
 corresponding correct representation sizes for points and tangent vectors on `M`.
 
 By default, `check_size` returns `nothing`, i.e. if no checks are implemented, the
 assumption is to be optimistic.
 """
-function check_size(M::Manifold, p)
+function check_size(M::AbstractManifold, p)
     n = size(p)
     m = representation_size(M)
     if length(n) != length(m)
@@ -279,7 +258,7 @@ function check_size(M::Manifold, p)
         )
     end
 end
-function check_size(M::Manifold, p, X)
+function check_size(M::AbstractManifold, p, X)
     mse = check_size(M, p)
     mse === nothing || return mse
     n = size(X)
@@ -299,53 +278,53 @@ function check_size(M::Manifold, p, X)
 end
 
 @doc raw"""
-    copyto!(M::Manifold, q, p)
+    copyto!(M::AbstractManifold, q, p)
 
-Copy the value(s) from `p` to `q`, where both are points on the [`Manifold`](@ref) `M`.
+Copy the value(s) from `p` to `q`, where both are points on the [`AbstractManifold`](@ref) `M`.
 This function defaults to calling `copyto!(q, p)`, but it might be useful to overwrite the
 function at the level, where also information from `M` can be accessed.
 """
-copyto!(::Manifold, q, p) = copyto!(q, p)
+copyto!(::AbstractManifold, q, p) = copyto!(q, p)
 
 @doc raw"""
-    copyto!(M::Manifold, Y, p, X)
+    copyto!(M::AbstractManifold, Y, p, X)
 
 Copy the value(s) from `X` to `Y`, where both are tangent vectors from the tangent space at
-`p` on the [`Manifold`](@ref) `M`.
+`p` on the [`AbstractManifold`](@ref) `M`.
 This function defaults to calling `copyto!(Y, X)`, but it might be useful to overwrite the
 function at the level, where also information from `p` and `M` can be accessed.
 """
-copyto!(::Manifold, Y, p, X) = copyto!(Y, X)
+copyto!(::AbstractManifold, Y, p, X) = copyto!(Y, X)
 
 """
-    distance(M::Manifold, p, q)
+    distance(M::AbstractManifold, p, q)
 
-Shortest distance between the points `p` and `q` on the [`Manifold`](@ref) `M`.
+Shortest distance between the points `p` and `q` on the [`AbstractManifold`](@ref) `M`.
 """
-distance(M::Manifold, p, q) = norm(M, p, log(M, p, q))
+distance(M::AbstractManifold, p, q) = norm(M, p, log(M, p, q))
 
 """
-    embed(M::Manifold, p)
+    embed(M::AbstractManifold, p)
 
-Embed point `p` from the [`Manifold`](@ref) `M` into the ambient space.
+Embed point `p` from the [`AbstractManifold`](@ref) `M` into the ambient space.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given.
 Additionally, `embed` includes changing data representation, if applicable, i.e.
 if the points on `M` are not represented in the same way as points on the embedding,
 the representation is changed accordingly.
 
-See also: [`EmbeddedManifold`](@ref), [`project`](@ref project(M::Manifold,p))
+See also: [`EmbeddedManifold`](@ref), [`project`](@ref project(M::AbstractManifold,p))
 """
-function embed(M::Manifold, p)
+function embed(M::AbstractManifold, p)
     q = allocate_result(M, embed, p)
     embed!(M, q, p)
     return q
 end
 
 """
-    embed!(M::Manifold, q, p)
+    embed!(M::AbstractManifold, q, p)
 
-Embed point `p` from the [`Manifold`](@ref) `M` into an ambient space.
+Embed point `p` from the [`AbstractManifold`](@ref) `M` into an ambient space.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given. Not implementing this function means, there is no proper embedding for your manifold.
 Additionally, `embed` might include changing data representation, if applicable, i.e.
@@ -356,16 +335,16 @@ If you have more than one embedding, see [`EmbeddedManifold`](@ref) for defining
 embedding. If your point `p` is already represented in some embedding,
 see [`AbstractEmbeddedManifold`](@ref) how you can avoid reimplementing code from the embedded manifold
 
-See also: [`EmbeddedManifold`](@ref), [`project!`](@ref project!(M::Manifold, q, p))
+See also: [`EmbeddedManifold`](@ref), [`project!`](@ref project!(M::AbstractManifold, q, p))
 """
-function embed!(M::Manifold, q, p)
+function embed!(M::AbstractManifold, q, p)
     return error(manifold_function_not_implemented_message(M, embed!, q, p))
 end
 
 """
-    embed(M::Manifold, p, X)
+    embed(M::AbstractManifold, p, X)
 
-Embed a tangent vector `X` at a point `p` on the [`Manifold`](@ref) `M` into an ambient space.
+Embed a tangent vector `X` at a point `p` on the [`AbstractManifold`](@ref) `M` into an ambient space.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given. Not implementing this function means, there is no proper embedding for your tangent space(s).
 
@@ -377,9 +356,9 @@ If you have more than one embedding, see [`EmbeddedManifold`](@ref) for defining
 embedding. If your tangent vector `X` is already represented in some embedding,
 see [`AbstractEmbeddedManifold`](@ref) how you can avoid reimplementing code from the embedded manifold
 
-See also: [`EmbeddedManifold`](@ref), [`project`](@ref project(M::Manifold, p, X))
+See also: [`EmbeddedManifold`](@ref), [`project`](@ref project(M::AbstractManifold, p, X))
 """
-function embed(M::Manifold, p, X)
+function embed(M::AbstractManifold, p, X)
     # Note that the order is switched,
     # since the allocation by default takes the type of the first.
     Y = allocate_result(M, embed, X, p)
@@ -388,9 +367,9 @@ function embed(M::Manifold, p, X)
 end
 
 """
-    embed!(M::Manifold, Y, p, X)
+    embed!(M::AbstractManifold, Y, p, X)
 
-Embed a tangent vector `X` at a point `p` on the [`Manifold`](@ref) `M` into the ambient
+Embed a tangent vector `X` at a point `p` on the [`AbstractManifold`](@ref) `M` into the ambient
 space and return the result in `Y`.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given.
@@ -400,228 +379,262 @@ the representation is changed accordingly. This is the case for example for Lie
 when tangent vectors are represented in the Lie algebra. The embedded tangents are then in
 the tangent spaces of the embedded base points.
 
-See also: [`EmbeddedManifold`](@ref), [`project!`](@ref project!(M::Manifold, Y, p, X))
+See also: [`EmbeddedManifold`](@ref), [`project!`](@ref project!(M::AbstractManifold, Y, p, X))
 """
-function embed!(M::Manifold, Y, p, X)
+function embed!(M::AbstractManifold, Y, p, X)
     return error(manifold_function_not_implemented_message(M, embed!, Y, p, X))
 end
 
 """
-    exp(M::Manifold, p, X)
-    exp(M::Manifold, p, X, t::Real = 1)
+    exp(M::AbstractManifold, p, X)
+    exp(M::AbstractManifold, p, X, t::Real = 1)
 
 Compute the exponential map of tangent vector `X`, optionally scaled by `t`,  at point `p`
-from manifold the [`Manifold`](@ref) `M`.
+from manifold the [`AbstractManifold`](@ref) `M`.
 """
-function exp(M::Manifold, p, X)
+function exp(M::AbstractManifold, p, X)
     q = allocate_result(M, exp, p, X)
     exp!(M, q, p, X)
     return q
 end
-exp(M::Manifold, p, X, t::Real) = exp(M, p, t * X)
+exp(M::AbstractManifold, p, X, t::Real) = exp(M, p, t * X)
 
 """
-    exp!(M::Manifold, q, p, X)
-    exp!(M::Manifold, q, p, X, t::Real = 1)
+    exp!(M::AbstractManifold, q, p, X)
+    exp!(M::AbstractManifold, q, p, X, t::Real = 1)
 
 Compute the exponential map of tangent vector `X`, optionally scaled by `t`,  at point `p`
-from manifold the [`Manifold`](@ref) `M`.
+from manifold the [`AbstractManifold`](@ref) `M`.
 The result is saved to `q`.
 """
-function exp!(M::Manifold, q, p, X)
+function exp!(M::AbstractManifold, q, p, X)
     return error(manifold_function_not_implemented_message(M, exp!, q, p, X))
 end
-exp!(M::Manifold, q, p, X, t::Real) = exp!(M, q, p, t * X)
+exp!(M::AbstractManifold, q, p, X, t::Real) = exp!(M, q, p, t * X)
 
 """
-    geodesic(M::Manifold, p, X) -> Function
+    geodesic(M::AbstractManifold, p, X) -> Function
 
-Get the geodesic with initial point `p` and velocity `X` on the [`Manifold`](@ref) `M`.
+Get the geodesic with initial point `p` and velocity `X` on the [`AbstractManifold`](@ref) `M`.
  The geodesic is the curve of constant velocity that is locally distance-minimizing.
  This function returns a function of (time) `t`.
 
-    geodesic(M::Manifold, x, v, t::Real)
-    geodesic(M::Manifold, x, v, T::AbstractVector) -> AbstractVector
+    geodesic(M::AbstractManifold, x, v, t::Real)
+    geodesic(M::AbstractManifold, x, v, T::AbstractVector) -> AbstractVector
 
 Return the point at time `t` or points at times `t` in `T` along the geodesic.
 """
-geodesic(M::Manifold, p, X) = t -> exp(M, p, X, t)
-geodesic(M::Manifold, p, X, t::Real) = exp(M, p, X, t)
-geodesic(M::Manifold, p, X, T::AbstractVector) = map(t -> exp(M, p, X, t), T)
+geodesic(M::AbstractManifold, p, X) = t -> exp(M, p, X, t)
+geodesic(M::AbstractManifold, p, X, t::Real) = exp(M, p, X, t)
+geodesic(M::AbstractManifold, p, X, T::AbstractVector) = map(t -> exp(M, p, X, t), T)
 
-@doc doc"""
-    injectivity_radius(M::Manifold, p)
+@doc raw"""
+    injectivity_radius(M::AbstractManifold, p)
 
-Return the distance $d$ such that [`exp(M, p, X)`](@ref exp(::Manifold, ::Any, ::Any)) is
+Return the distance $d$ such that [`exp(M, p, X)`](@ref exp(::AbstractManifold, ::Any, ::Any)) is
 injective for all tangent vectors shorter than $d$ (i.e. has an inverse).
 
-    injectivity_radius(M::Manifold)
+    injectivity_radius(M::AbstractManifold)
 
 Infimum of the injectivity radius of all manifold points.
 
-    injectivity_radius(M::Manifold[, x], method::AbstractRetractionMethod)
-    injectivity_radius(M::Manifold, x, method::AbstractRetractionMethod)
+    injectivity_radius(M::AbstractManifold[, x], method::AbstractRetractionMethod)
+    injectivity_radius(M::AbstractManifold, x, method::AbstractRetractionMethod)
 
 Distance $d$ such that
-[`retract(M, p, X, method)`](@ref retract(::Manifold, ::Any, ::Any, ::AbstractRetractionMethod))
+[`retract(M, p, X, method)`](@ref retract(::AbstractManifold, ::Any, ::Any, ::AbstractRetractionMethod))
 is injective for all tangent vectors shorter than $d$ (i.e. has an inverse) for point `p`
 if provided or all manifold points otherwise.
 """
-function injectivity_radius(M::Manifold)
+function injectivity_radius(M::AbstractManifold)
     return error(manifold_function_not_implemented_message(M, injectivity_radius))
 end
-injectivity_radius(M::Manifold, p) = injectivity_radius(M)
-function injectivity_radius(M::Manifold, p, method::AbstractRetractionMethod)
+injectivity_radius(M::AbstractManifold, p) = injectivity_radius(M)
+function injectivity_radius(M::AbstractManifold, p, method::AbstractRetractionMethod)
     return injectivity_radius(M, method)
 end
-function injectivity_radius(M::Manifold, method::AbstractRetractionMethod)
+function injectivity_radius(M::AbstractManifold, method::AbstractRetractionMethod)
     return error(manifold_function_not_implemented_message(M, injectivity_radius, method))
 end
-injectivity_radius(M::Manifold, p, ::ExponentialRetraction) = injectivity_radius(M, p)
-injectivity_radius(M::Manifold, ::ExponentialRetraction) = injectivity_radius(M)
+function injectivity_radius(M::AbstractManifold, p, ::ExponentialRetraction)
+    return injectivity_radius(M, p)
+end
+injectivity_radius(M::AbstractManifold, ::ExponentialRetraction) = injectivity_radius(M)
 
 """
-    inner(M::Manifold, p, X, Y)
+    inner(M::AbstractManifold, p, X, Y)
 
 Compute the inner product of tangent vectors `X` and `Y` at point `p` from the
-[`Manifold`](@ref) `M`.
+[`AbstractManifold`](@ref) `M`.
 
 See also: [`MetricManifold`](@ref Main.Manifolds.MetricManifold)
 """
-function inner(M::Manifold, p, X, Y)
+function inner(M::AbstractManifold, p, X, Y)
     return error(manifold_function_not_implemented_message(M, inner, p, X, Y))
 end
 
 """
-    inverse_retract!(M::Manifold, X, p, q[, method::AbstractInverseRetractionMethod])
+    inverse_retract!(M::AbstractManifold, X, p, q[, method::AbstractInverseRetractionMethod])
 
 Compute the inverse retraction, a cheaper, approximate version of the
-[`log`](@ref)arithmic map), of points `p` and `q` on the [`Manifold`](@ref) `M`.
+[`log`](@ref)arithmic map), of points `p` and `q` on the [`AbstractManifold`](@ref) `M`.
 Result is saved to `X`.
 
 Inverse retraction method can be specified by the last argument, defaulting to
 [`LogarithmicInverseRetraction`](@ref). See the documentation of respective manifolds for
 available methods.
 """
-function inverse_retract!(M::Manifold, X, p, q)
+function inverse_retract!(M::AbstractManifold, X, p, q)
     return inverse_retract!(M, X, p, q, LogarithmicInverseRetraction())
 end
-function inverse_retract!(M::Manifold, X, p, q, method::LogarithmicInverseRetraction)
+function inverse_retract!(
+    M::AbstractManifold,
+    X,
+    p,
+    q,
+    method::LogarithmicInverseRetraction,
+)
     return log!(M, X, p, q)
 end
-function inverse_retract!(M::Manifold, X, p, q, method::AbstractInverseRetractionMethod)
+function inverse_retract!(
+    M::AbstractManifold,
+    X,
+    p,
+    q,
+    method::AbstractInverseRetractionMethod,
+)
     return error(
         manifold_function_not_implemented_message(M, inverse_retract!, X, p, q, method),
     )
 end
 
 """
-    inverse_retract(M::Manifold, x, y)
-    inverse_retract(M::Manifold, x, y, method::AbstractInverseRetractionMethod
+    inverse_retract(M::AbstractManifold, x, y)
+    inverse_retract(M::AbstractManifold, x, y, method::AbstractInverseRetractionMethod
 
 Compute the inverse retraction, a cheaper, approximate version of the
-[`log`](@ref)arithmic map), of points `p` and `q` on the [`Manifold`](@ref) `M`.
+[`log`](@ref)arithmic map), of points `p` and `q` on the [`AbstractManifold`](@ref) `M`.
 
 Inverse retraction method can be specified by the last argument, defaulting to
 [`LogarithmicInverseRetraction`](@ref). See the documentation of respective manifolds for
 available methods.
 """
-function inverse_retract(M::Manifold, p, q)
+function inverse_retract(M::AbstractManifold, p, q)
     X = allocate_result(M, inverse_retract, p, q)
     inverse_retract!(M, X, p, q)
     return X
 end
-function inverse_retract(M::Manifold, p, q, method::AbstractInverseRetractionMethod)
+function inverse_retract(M::AbstractManifold, p, q, method::AbstractInverseRetractionMethod)
     X = allocate_result(M, inverse_retract, p, q)
     inverse_retract!(M, X, p, q, method)
     return X
 end
 
 """
-    isapprox(M::Manifold, p, q; kwargs...)
+    isapprox(M::AbstractManifold, p, q; kwargs...)
 
-Check if points `p` and `q` from [`Manifold`](@ref) `M` are approximately equal.
+Check if points `p` and `q` from [`AbstractManifold`](@ref) `M` are approximately equal.
 
 Keyword arguments can be used to specify tolerances.
 """
-isapprox(::Manifold, x, y; kwargs...) = isapprox(x, y; kwargs...)
+isapprox(::AbstractManifold, x, y; kwargs...) = isapprox(x, y; kwargs...)
 
 """
-    isapprox(M::Manifold, p, X, Y; kwargs...)
+    isapprox(M::AbstractManifold, p, X, Y; kwargs...)
 
-Check if vectors `X` and `Y` tangent at `p` from [`Manifold`](@ref) `M` are approximately
+Check if vectors `X` and `Y` tangent at `p` from [`AbstractManifold`](@ref) `M` are approximately
 equal.
 
 Keyword arguments can be used to specify tolerances.
 """
-isapprox(::Manifold, p, X, Y; kwargs...) = isapprox(X, Y; kwargs...)
+isapprox(::AbstractManifold, p, X, Y; kwargs...) = isapprox(X, Y; kwargs...)
 
 
 """
-    is_manifold_point(M::Manifold, p, throw_error = false; kwargs...)
+    is_point(M::AbstractManifold, p, throw_error = false; kwargs...)
 
-Return whether `p` is a valid point on the [`Manifold`](@ref) `M`.
+Return whether `p` is a valid point on the [`AbstractManifold`](@ref) `M`.
 
 If `throw_error` is `false`, the function returns either `true` or `false`. If `throw_error`
 is `true`, the function either returns `true` or throws an error. By default the function
-calls [`check_manifold_point(M, p; kwargs...)`](@ref) and checks whether the returned value
+calls [`check_point(M, p; kwargs...)`](@ref) and checks whether the returned value
 is `nothing` or an error.
 """
-function is_manifold_point(M::Manifold, p, throw_error = false; kwargs...)
-    mpe = check_manifold_point(M, p; kwargs...)
+function is_point(M::AbstractManifold, p, throw_error = false; kwargs...)
+    mpe = check_point(M, p; kwargs...)
     mpe === nothing && return true
     return throw_error ? throw(mpe) : false
 end
 
 """
-    is_tangent_vector(M::Manifold, p, X, throw_error = false; kwargs...)
+    is_vector(M::AbstractManifold, p, X, throw_error = false; check_base_point=true, kwargs...)
 
-Return whether `X` is a valid tangent vector at point `p` on the [`Manifold`](@ref) `M`.
+Return whether `X` is a valid tangent vector at point `p` on the [`AbstractManifold`](@ref) `M`.
 Returns either `true` or `false`.
 
 If `throw_error` is `false`, the function returns either `true` or `false`. If `throw_error`
 is `true`, the function either returns `true` or throws an error. By default the function
-calls [`check_tangent_vector(M, p, X; kwargs...)`](@ref) and checks whether the returned
+calls [`check_vector(M, p, X; kwargs...)`](@ref) and checks whether the returned
 value is `nothing` or an error.
-"""
-function is_tangent_vector(M::Manifold, p, X, throw_error = false; kwargs...)
-    mtve = check_tangent_vector(M, p, X; kwargs...)
+
+If `check_base_point` is true, then the point `p` will be first checked using the
+[`check_point`](@ref) function.
+"""
+function is_vector(
+    M::AbstractManifold,
+    p,
+    X,
+    throw_error = false;
+    check_base_point = true,
+    kwargs...,
+)
+    if check_base_point
+        mpe = check_point(M, p; kwargs...)
+        if mpe !== nothing
+            if throw_error
+                throw(mpe)
+            else
+                return false
+            end
+        end
+    end
+    mtve = check_vector(M, p, X; kwargs...)
     mtve === nothing && return true
     return throw_error ? throw(mtve) : false
 end
 
 """
-    log(M::Manifold, p, q)
+    log(M::AbstractManifold, p, q)
 
-Compute the logarithmic map of point `q` at base point `p` on the [`Manifold`](@ref) `M`.
+Compute the logarithmic map of point `q` at base point `p` on the [`AbstractManifold`](@ref) `M`.
 """
-function log(M::Manifold, p, q)
+function log(M::AbstractManifold, p, q)
     X = allocate_result(M, log, p, q)
     log!(M, X, p, q)
     return X
 end
 
 """
-    log!(M::Manifold, X, p, q)
+    log!(M::AbstractManifold, X, p, q)
 
-Compute the logarithmic map of point `q` at base point `p` on the [`Manifold`](@ref) `M`.
+Compute the logarithmic map of point `q` at base point `p` on the [`AbstractManifold`](@ref) `M`.
 The result is saved to `X`.
 """
-function log!(M::Manifold, X, p, q)
+function log!(M::AbstractManifold, X, p, q)
     return error(manifold_function_not_implemented_message(M, log!, X, p, q))
 end
 
-@doc doc"""
-    manifold_dimension(M::Manifold)
+@doc raw"""
+    manifold_dimension(M::AbstractManifold)
 
 The dimension $n=\dim_{\mathcal M}$ of real space $\mathbb R^n$ to which the neighborhood of
-each point of the [`Manifold`](@ref) `M` is homeomorphic.
+each point of the [`AbstractManifold`](@ref) `M` is homeomorphic.
 """
-function manifold_dimension(M::Manifold)
+function manifold_dimension(M::AbstractManifold)
     return error(manifold_function_not_implemented_message(M, manifold_dimension))
 end
 
-function manifold_function_not_implemented_message(M::Manifold, f, x...)
+function manifold_function_not_implemented_message(M::AbstractManifold, f, x...)
     s = join(map(string, map(typeof, x)), ", ", " and ")
     a = length(x) > 1 ? "arguments" : "argument"
     m = length(x) > 0 ? " for $(a) $(s)." : "."
@@ -629,31 +642,31 @@ function manifold_function_not_implemented_message(M::Manifold, f, x...)
 end
 
 """
-    mid_point(M::Manifold, p1, p2)
+    mid_point(M::AbstractManifold, p1, p2)
 
 Calculate the middle between the two point `p1` and `p2` from manifold `M`.
 By default uses [`log`](@ref), divides the vector by 2 and uses [`exp`](@ref).
 """
-function mid_point(M::Manifold, p1, p2)
+function mid_point(M::AbstractManifold, p1, p2)
     q = allocate(p1)
     return mid_point!(M, q, p1, p2)
 end
 
 """
-    mid_point!(M::Manifold, q, p1, p2)
+    mid_point!(M::AbstractManifold, q, p1, p2)
 
 Calculate the middle between the two point `p1` and `p2` from manifold `M`.
 By default uses [`log`](@ref), divides the vector by 2 and uses [`exp!`](@ref).
 Saves the result in `q`.
 """
-function mid_point!(M::Manifold, q, p1, p2)
+function mid_point!(M::AbstractManifold, q, p1, p2)
     X = log(M, p1, p2)
     return exp!(M, q, p1, X / 2)
 end
 
 @static if VERSION <= v"1.1"
     function mid_point!(
-        M::Manifold,
+        M::AbstractManifold,
         q::AbstractArray{T1,0},
         p1::AbstractArray{T2,0},
         p2::AbstractArray{T3,0},
@@ -664,12 +677,12 @@ end
 end
 
 """
-    norm(M::Manifold, p, X)
+    norm(M::AbstractManifold, p, X)
 
-Compute the norm of tangent vector `X` at point `p` from a [`Manifold`](@ref) `M`.
+Compute the norm of tangent vector `X` at point `p` from a [`AbstractManifold`](@ref) `M`.
 By default this is computed using [`inner`](@ref).
 """
-norm(M::Manifold, p, X) = sqrt(max(real(inner(M, p, X, X)), 0))
+norm(M::AbstractManifold, p, X) = sqrt(max(real(inner(M, p, X, X)), 0))
 
 """
     number_eltype(x)
@@ -686,43 +699,43 @@ function number_eltype(x::Tuple)
 end
 
 """
-    project(M::Manifold, p)
+    project(M::AbstractManifold, p)
 
-Project point `p` from the ambient space of the [`Manifold`](@ref) `M` to `M`.
+Project point `p` from the ambient space of the [`AbstractManifold`](@ref) `M` to `M`.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given. Additionally, the projection includes changing data representation, if applicable,
 i.e. if the points on `M` are not represented in the same array data, the data is changed
 accordingly.
 
-See also: [`EmbeddedManifold`](@ref), [`embed`](@ref embed(M::Manifold, p))
+See also: [`EmbeddedManifold`](@ref), [`embed`](@ref embed(M::AbstractManifold, p))
 """
-function project(M::Manifold, p)
+function project(M::AbstractManifold, p)
     q = allocate_result(M, project, p)
     project!(M, q, p)
     return q
 end
 
 """
-    project!(M::Manifold, q, p)
+    project!(M::AbstractManifold, q, p)
 
-Project point `p` from the ambient space onto the [`Manifold`](@ref) `M`. The result is
+Project point `p` from the ambient space onto the [`AbstractManifold`](@ref) `M`. The result is
 storedin `q`.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given. Additionally, the projection includes changing data representation, if applicable,
 i.e. if the points on `M` are not represented in the same array data, the data is changed
 accordingly.
 
-See also: [`EmbeddedManifold`](@ref), [`embed!`](@ref embed!(M::Manifold, q, p))
+See also: [`EmbeddedManifold`](@ref), [`embed!`](@ref embed!(M::AbstractManifold, q, p))
 """
-function project!(M::Manifold, q, p)
+function project!(M::AbstractManifold, q, p)
     return error(manifold_function_not_implemented_message(M, project!, q, p))
 end
 
 """
-    project(M::Manifold, p, X)
+    project(M::AbstractManifold, p, X)
 
 Project ambient space representation of a vector `X` to a tangent vector at point `p` on
-the [`Manifold`](@ref) `M`.
+the [`AbstractManifold`](@ref) `M`.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given.
 Additionally, `project` includes changing data representation, if applicable, i.e.
@@ -731,9 +744,9 @@ the representation is changed accordingly. This is the case for example for Lie
 when tangent vectors are represented in the Lie algebra. after projection the change to the
 Lie algebra is perfomed, too.
 
-See also: [`EmbeddedManifold`](@ref), [`embed`](@ref embed(M::Manifold, p, X))
+See also: [`EmbeddedManifold`](@ref), [`embed`](@ref embed(M::AbstractManifold, p, X))
 """
-function project(M::Manifold, p, X)
+function project(M::AbstractManifold, p, X)
     # Note that the order is switched,
     # since the allocation by default takes the type of the first.
     Y = allocate_result(M, project, X, p)
@@ -742,10 +755,10 @@ function project(M::Manifold, p, X)
 end
 
 """
-    project!(M::Manifold, Y, p, X)
+    project!(M::AbstractManifold, Y, p, X)
 
 Project ambient space representation of a vector `X` to a tangent vector at point `p` on
-the [`Manifold`](@ref) `M`. The result is saved in vector `Y`.
+the [`AbstractManifold`](@ref) `M`. The result is saved in vector `Y`.
 This method is only available for manifolds where implicitly an embedding or ambient space
 is given.
 Additionally, `project!` includes changing data representation, if applicable, i.e.
@@ -754,77 +767,77 @@ the representation is changed accordingly. This is the case for example for Lie
 when tangent vectors are represented in the Lie algebra. after projection the change to the
 Lie algebra is perfomed, too.
 
-See also: [`EmbeddedManifold`](@ref), [`embed!`](@ref embed!(M::Manifold, Y, p, X))
+See also: [`EmbeddedManifold`](@ref), [`embed!`](@ref embed!(M::AbstractManifold, Y, p, X))
 """
-function project!(M::Manifold, Y, p, X)
+function project!(M::AbstractManifold, Y, p, X)
     return error(manifold_function_not_implemented_message(M, project!, Y, p, X))
 end
 
-@doc doc"""
-    representation_size(M::Manifold)
+@doc raw"""
+    representation_size(M::AbstractManifold)
 
-The size of an array representing a point on [`Manifold`](@ref) `M`.
+The size of an array representing a point on [`AbstractManifold`](@ref) `M`.
 Returns `nothing` by default indicating that points are not represented using an
 `AbstractArray`.
 """
-function representation_size(M::Manifold)
+function representation_size(M::AbstractManifold)
     return nothing
 end
 
 """
-    retract(M::Manifold, p, X)
-    retract(M::Manifold, p, X, t::Real=1)
-    retract(M::Manifold, p, X, method::AbstractRetractionMethod)
-    retract(M::Manifold, p, X, t::Real=1, method::AbstractRetractionMethod)
+    retract(M::AbstractManifold, p, X)
+    retract(M::AbstractManifold, p, X, t::Real=1)
+    retract(M::AbstractManifold, p, X, method::AbstractRetractionMethod)
+    retract(M::AbstractManifold, p, X, t::Real=1, method::AbstractRetractionMethod)
 
 Compute a retraction, a cheaper, approximate version of the [`exp`](@ref)onential map,
-from `p` into direction `X`, scaled by `t`, on the [`Manifold`](@ref) `M`.
+from `p` into direction `X`, scaled by `t`, on the [`AbstractManifold`](@ref) `M`.
 
 Retraction method can be specified by the last argument, defaulting to
 [`ExponentialRetraction`](@ref). See the documentation of respective manifolds for available
 methods.
 """
-function retract(M::Manifold, p, X)
+function retract(M::AbstractManifold, p, X)
     q = allocate_result(M, retract, p, X)
     retract!(M, q, p, X)
     return q
 end
-retract(M::Manifold, p, X, t::Real) = retract(M, p, t * X)
-function retract(M::Manifold, p, X, method::AbstractRetractionMethod)
+retract(M::AbstractManifold, p, X, t::Real) = retract(M, p, t * X)
+function retract(M::AbstractManifold, p, X, method::AbstractRetractionMethod)
     q = allocate_result(M, retract, p, X)
     retract!(M, q, p, X, method)
     return q
 end
-function retract(M::Manifold, p, X, t::Real, method::AbstractRetractionMethod)
+function retract(M::AbstractManifold, p, X, t::Real, method::AbstractRetractionMethod)
     return retract(M, p, t * X, method)
 end
 
 """
-    retract!(M::Manifold, q, p, X)
-    retract!(M::Manifold, q, p, X, t::Real=1)
-    retract!(M::Manifold, q, p, X, method::AbstractRetractionMethod)
-    retract!(M::Manifold, q, p, X, t::Real=1, method::AbstractRetractionMethod)
+    retract!(M::AbstractManifold, q, p, X)
+    retract!(M::AbstractManifold, q, p, X, t::Real=1)
+    retract!(M::AbstractManifold, q, p, X, method::AbstractRetractionMethod)
+    retract!(M::AbstractManifold, q, p, X, t::Real=1, method::AbstractRetractionMethod)
 
 Compute a retraction, a cheaper, approximate version of the [`exp`](@ref)onential map,
-from `p` into direction `X`, scaled by `t`, on the [`Manifold`](@ref) manifold `M`.
+from `p` into direction `X`, scaled by `t`, on the [`AbstractManifold`](@ref) manifold `M`.
 Result is saved to `q`.
 
 Retraction method can be specified by the last argument, defaulting to
 [`ExponentialRetraction`](@ref). See the documentation of respective manifolds for available
 methods.
 """
-retract!(M::Manifold, q, p, X) = retract!(M, q, p, X, ExponentialRetraction())
-retract!(M::Manifold, q, p, X, t::Real) = retract!(M, q, p, t * X)
-retract!(M::Manifold, q, p, X, method::ExponentialRetraction) = exp!(M, q, p, X)
-function retract!(M::Manifold, q, p, X, t::Real, method::AbstractRetractionMethod)
+retract!(M::AbstractManifold, q, p, X) = retract!(M, q, p, X, ExponentialRetraction())
+retract!(M::AbstractManifold, q, p, X, t::Real) = retract!(M, q, p, t * X)
+retract!(M::AbstractManifold, q, p, X, method::ExponentialRetraction) = exp!(M, q, p, X)
+function retract!(M::AbstractManifold, q, p, X, t::Real, method::AbstractRetractionMethod)
     return retract!(M, q, p, t * X, method)
 end
-function retract!(M::Manifold, q, p, X, method::AbstractRetractionMethod)
+function retract!(M::AbstractManifold, q, p, X, method::AbstractRetractionMethod)
     return error(manifold_function_not_implemented_message(M, retract!, q, p, method))
 end
 
-@doc doc"""
-    shortest_geodesic(M::Manifold, p, q) -> Function
+@doc raw"""
+    shortest_geodesic(M::AbstractManifold, p, q) -> Function
 
 Get a [`geodesic`](@ref) $\gamma_{p,q}(t)$ whose length is the shortest path between the
 points `p`and `q`, where $\gamma_{p,q}(0)=p$ and $\gamma_{p,q}(1)=q$. When there are
@@ -832,14 +845,16 @@ multiple shortest geodesics, there is no guarantee which will be returned.
 
 This function returns a function of time, which may be a `Real` or an `AbstractVector`.
 
-    shortest_geodesic(M::Manifold, p, q, t::Real)
-    shortest_geodesic(M::Manifold, p, q, T::AbstractVector) -> AbstractVector
+    shortest_geodesic(M::AbstractManifold, p, q, t::Real)
+    shortest_geodesic(M::AbstractManifold, p, q, T::AbstractVector) -> AbstractVector
 
 Return the point at time `t` or points at times `t` in `T` along the shortest geodesic.
 """
-shortest_geodesic(M::Manifold, p, q) = geodesic(M, p, log(M, p, q))
-shortest_geodesic(M::Manifold, p, q, t::Real) = geodesic(M, p, log(M, p, q), t)
-shortest_geodesic(M::Manifold, p, q, T::AbstractVector) = geodesic(M, p, log(M, p, q), T)
+shortest_geodesic(M::AbstractManifold, p, q) = geodesic(M, p, log(M, p, q))
+shortest_geodesic(M::AbstractManifold, p, q, t::Real) = geodesic(M, p, log(M, p, q), t)
+function shortest_geodesic(M::AbstractManifold, p, q, T::AbstractVector)
+    return geodesic(M, p, log(M, p, q), T)
+end
 
 """
     size_to_tuple(::Type{S}) where S<:Tuple
@@ -848,23 +863,25 @@ Converts a size given by `Tuple{N, M, ...}` into a tuple `(N, M, ...)`.
 """
 Base.@pure size_to_tuple(::Type{S}) where {S<:Tuple} = tuple(S.parameters...)
 
-"""
-    zero_tangent_vector!(M::Manifold, X, p)
+@doc raw"""
+    zero_vector!(M::AbstractManifold, X, p)
 
-Save to `X` a vector such that retracting `X` to the [`Manifold`](@ref) `M` at `p`
-produces `p`.
+Save to `X` the tangent vector from the tangent space ``T_p\mathcal M`` at `p` that
+represents the zero vector, i.e. such that retracting `X` to the [`AbstractManifold`](@ref) `M` at
+`p` produces `p`.
 """
-zero_tangent_vector!(M::Manifold, X, p) = log!(M, X, p, p)
+zero_vector!(M::AbstractManifold, X, p) = log!(M, X, p, p)
 
-"""
-    zero_tangent_vector(M::Manifold, p)
+@doc raw"""
+    zero_vector(M::AbstractManifold, p)
 
-Return the tangent vector from the tangent space at `p` on the [`Manifold`](@ref) `M`, that
-represents the zero vector, i.e. such that a retraction at `p` produces `p`.
+Return the tangent vector from the tangent space ``T_p\mathcal M`` at `p` on the
+[`AbstractManifold`](@ref) `M`, that represents the zero vector, i.e. such that a retraction at
+`p` produces `p`.
 """
-function zero_tangent_vector(M::Manifold, p)
-    X = allocate_result(M, zero_tangent_vector, p)
-    zero_tangent_vector!(M, X, p)
+function zero_vector(M::AbstractManifold, p)
+    X = allocate_result(M, zero_vector, p)
+    zero_vector!(M, X, p)
     return X
 end
 include("errors.jl")
@@ -872,12 +889,13 @@ include("numbers.jl")
 include("vector_transport.jl")
 include("DecoratorManifold.jl")
 include("bases.jl")
+include("vector_spaces.jl")
 include("ValidationManifold.jl")
 include("EmbeddedManifold.jl")
 include("DefaultManifold.jl")
 include("PowerManifold.jl")
 
-export Manifold, MPoint, TVector, CoTVector
+export AbstractManifold, AbstractManifoldPoint, TVector, CoTVector
 export AbstractDecoratorManifold
 export ValidationManifold, ValidationMPoint, ValidationTVector, ValidationCoTVector
 export AbstractEmbeddingType,
@@ -924,8 +942,8 @@ export CompositeManifoldError, ComponentManifoldError
 
 export allocate,
     base_manifold,
-    check_manifold_point,
-    check_tangent_vector,
+    check_point,
+    check_vector,
     check_size,
     distance,
     exp,
@@ -950,8 +968,8 @@ export allocate,
     inverse_retract,
     inverse_retract!,
     isapprox,
-    is_manifold_point,
-    is_tangent_vector,
+    is_point,
+    is_vector,
     isempty,
     length,
     log,
@@ -980,7 +998,7 @@ export allocate,
     vector_transport_to!,
     vee,
     vee!,
-    zero_tangent_vector,
-    zero_tangent_vector!
+    zero_vector,
+    zero_vector!
 
 end # module
diff --git a/src/PowerManifold.jl b/src/PowerManifold.jl
index 02d59b2e..a22525e2 100644
--- a/src/PowerManifold.jl
+++ b/src/PowerManifold.jl
@@ -15,17 +15,20 @@ Each element of such array stores a single point or tangent vector.
 struct NestedPowerRepresentation <: AbstractPowerRepresentation end
 
 @doc raw"""
-    AbstractPowerManifold{𝔽,M,TPR} <: Manifold{𝔽}
+    AbstractPowerManifold{𝔽,M,TPR} <: AbstractManifold{𝔽}
 
-An abstract [`Manifold`](@ref) to represent manifolds that are build as powers
-of another [`Manifold`](@ref) `M` with representation type `TPR`, a subtype of
+An abstract [`AbstractManifold`](@ref) to represent manifolds that are build as powers
+of another [`AbstractManifold`](@ref) `M` with representation type `TPR`, a subtype of
 [`AbstractPowerRepresentation`](@ref).
 """
-abstract type AbstractPowerManifold{𝔽,M<:Manifold{𝔽},TPR<:AbstractPowerRepresentation} <:
-              Manifold{𝔽} end
+abstract type AbstractPowerManifold{
+    𝔽,
+    M<:AbstractManifold{𝔽},
+    TPR<:AbstractPowerRepresentation,
+} <: AbstractManifold{𝔽} end
 
 @doc raw"""
-    PowerManifold{𝔽,TM<:Manifold,TSize<:Tuple,TPR<:AbstractPowerRepresentation} <: AbstractPowerManifold{𝔽,TM}
+    PowerManifold{𝔽,TM<:AbstractManifold,TSize<:Tuple,TPR<:AbstractPowerRepresentation} <: AbstractPowerManifold{𝔽,TM}
 
 The power manifold $\mathcal M^{n_1× n_2 × … × n_d}$ with power geometry
  `TSize` statically defines the number of elements along each axis.
@@ -41,7 +44,7 @@ would not be represented by statically-sized arrays.
 # Constructor
 
     PowerManifold(M::PowerManifold, N_1, N_2, ..., N_d)
-    PowerManifold(M::Manifold, NestedPowerRepresentation(), N_1, N_2, ..., N_d)
+    PowerManifold(M::AbstractManifold, NestedPowerRepresentation(), N_1, N_2, ..., N_d)
     M^(N_1, N_2, ..., N_d)
 
 Generate the power manifold $M^{N_1 × N_2 × … × N_d}$.
@@ -56,13 +59,13 @@ in a nested array representation.
 Since there is no default [`AbstractPowerRepresentation`](@ref) within this interface, the
 `^` operator is only available for `PowerManifold`s and concatenates dimensions.
 """
-struct PowerManifold{𝔽,TM<:Manifold{𝔽},TSize,TPR<:AbstractPowerRepresentation} <:
+struct PowerManifold{𝔽,TM<:AbstractManifold{𝔽},TSize,TPR<:AbstractPowerRepresentation} <:
        AbstractPowerManifold{𝔽,TM,TPR}
     manifold::TM
 end
 
 function PowerManifold(
-    M::Manifold{𝔽},
+    M::AbstractManifold{𝔽},
     ::TPR,
     size::Integer...,
 ) where {𝔽,TPR<:AbstractPowerRepresentation}
@@ -71,21 +74,21 @@ end
 function PowerManifold(
     M::PowerManifold{𝔽,TM,TSize,TPR},
     size::Integer...,
-) where {𝔽,TM<:Manifold{𝔽},TSize,TPR<:AbstractPowerRepresentation}
+) where {𝔽,TM<:AbstractManifold{𝔽},TSize,TPR<:AbstractPowerRepresentation}
     return PowerManifold{𝔽,TM,Tuple{TSize.parameters...,size...},TPR}(M.manifold)
 end
 function PowerManifold(
     M::PowerManifold{𝔽,TM,TSize},
     ::TPR,
     size::Integer...,
-) where {𝔽,TM<:Manifold{𝔽},TSize,TPR<:AbstractPowerRepresentation}
+) where {𝔽,TM<:AbstractManifold{𝔽},TSize,TPR<:AbstractPowerRepresentation}
     return PowerManifold{𝔽,TM,Tuple{TSize.parameters...,size...},TPR}(M.manifold)
 end
 function PowerManifold(
     M::PowerManifold{𝔽,TM,TSize},
     ::NestedPowerRepresentation,
     size::Integer...,
-) where {𝔽,TM<:Manifold{𝔽},TSize}
+) where {𝔽,TM<:AbstractManifold{𝔽},TSize}
     return PowerManifold{
         𝔽,
         PowerManifold{𝔽,TM,TSize},
@@ -160,7 +163,7 @@ struct PowerBasisData{TB<:AbstractArray}
 end
 
 const PowerManifoldNested =
-    AbstractPowerManifold{𝔽,<:Manifold{𝔽},NestedPowerRepresentation} where {𝔽}
+    AbstractPowerManifold{𝔽,<:AbstractManifold{𝔽},NestedPowerRepresentation} where {𝔽}
 
 _access_nested(x, i::Int) = x[i]
 _access_nested(x, i::Tuple) = x[i...]
@@ -168,7 +171,7 @@ _access_nested(x, i::Tuple) = x[i...]
 function Base.:^(
     M::PowerManifold{𝔽,TM,TSize,NestedPowerRepresentation},
     size::Integer...,
-) where {𝔽,TM<:Manifold{𝔽},TSize}
+) where {𝔽,TM<:AbstractManifold{𝔽},TSize}
     return PowerManifold(M, size...)
 end
 
@@ -192,7 +195,7 @@ function allocate_result(
 )
     return invoke(
         allocate_result,
-        Tuple{Manifold,typeof(get_coordinates),Any,Any,typeof(B)},
+        Tuple{AbstractManifold,typeof(get_coordinates),Any,Any,typeof(B)},
         M,
         f,
         p,
@@ -209,7 +212,7 @@ function allocate_result(
 )
     return invoke(
         allocate_result,
-        Tuple{Manifold,typeof(get_coordinates),Any,Any,typeof(B)},
+        Tuple{AbstractManifold,typeof(get_coordinates),Any,Any,typeof(B)},
         M,
         f,
         p,
@@ -226,7 +229,7 @@ end
 
 
 """
-    check_manifold_point(M::AbstractPowerManifold, p; kwargs...)
+    check_point(M::AbstractPowerManifold, p; kwargs...)
 
 Check whether `p` is a valid point on an [`AbstractPowerManifold`](@ref) `M`,
 i.e. each element of `p` has to be a valid point on the base manifold.
@@ -235,10 +238,10 @@ components, for which the tests fail is returned.
 
 The tolerance for the last test can be set using the `kwargs...`.
 """
-function check_manifold_point(M::AbstractPowerManifold, p; kwargs...)
+function check_point(M::AbstractPowerManifold, p; kwargs...)
     rep_size = representation_size(M.manifold)
     e = [
-        (i, check_manifold_point(M.manifold, _read(M, rep_size, p, i); kwargs...)) for
+        (i, check_point(M.manifold, _read(M, rep_size, p, i); kwargs...)) for
         i in get_iterator(M)
     ]
     errors = filter((x) -> !(x[2] === nothing), e)
@@ -249,34 +252,22 @@ function check_manifold_point(M::AbstractPowerManifold, p; kwargs...)
 end
 
 """
-    check_tangent_vector(M::AbstractPowerManifold, p, X; check_base_point = true, kwargs... )
+    check_vector(M::AbstractPowerManifold, p, X; kwargs... )
 
 Check whether `X` is a tangent vector to `p` an the [`AbstractPowerManifold`](@ref)
-`M`, i.e. atfer [`check_manifold_point`](@ref)`(M, p)`, and all projections to
+`M`, i.e. atfer [`check_point`](@ref)`(M, p)`, and all projections to
 base manifolds must be respective tangent vectors.
-The optional parameter `check_base_point` indicates, whether to call [`check_manifold_point`](@ref)  for `p`.
 If `X` is not a tangent vector to `p` on `M` a [`CompositeManifoldError`](@ref) consisting of all error
 messages of the components, for which the tests fail is returned.
 
-
 The tolerance for the last test can be set using the `kwargs...`.
 """
-function check_tangent_vector(
-    M::AbstractPowerManifold,
-    p,
-    X;
-    check_base_point = true,
-    kwargs...,
-)
-    if check_base_point
-        mpe = check_manifold_point(M, p)
-        mpe === nothing || return mpe
-    end
+function check_vector(M::AbstractPowerManifold, p, X; kwargs...)
     rep_size = representation_size(M.manifold)
     e = [
         (
             i,
-            check_tangent_vector(
+            check_vector(
                 M.manifold,
                 _read(M, rep_size, p, i),
                 _read(M, rep_size, X, i);
@@ -292,7 +283,7 @@ function check_tangent_vector(
 end
 
 @doc raw"""
-    copyto!(M::AbstractPowerManifold{𝔽,<:Manifold{𝔽},NestedPowerRepresentation}, q, p)
+    copyto!(M::AbstractPowerManifold{𝔽,<:AbstractManifold{𝔽},NestedPowerRepresentation}, q, p)
 
 Copy the values elementwise, i.e. call `copyto!(M.manifold, b, a)` for all elements `a` and
 `b` of `p` and `q`, respectively.
@@ -306,7 +297,7 @@ function copyto!(M::PowerManifoldNested, q, p)
 end
 
 @doc raw"""
-    copyto!(M::AbstractPowerManifold{𝔽,<:Manifold{𝔽},NestedPowerRepresentation}, Y, p, X)
+    copyto!(M::AbstractPowerManifold{𝔽,<:AbstractManifold{𝔽},NestedPowerRepresentation}, Y, p, X)
 
 Copy the values elementwise, i.e. call `copyto!(M.manifold, B, a, A)` for all elements
 `A`, `a` and `B` of `X`, `p`, and `Y`, respectively.
@@ -461,9 +452,9 @@ function get_coordinates!(
     return Y
 end
 
-get_iterator(M::PowerManifold{𝔽,<:Manifold{𝔽},Tuple{N}}) where {𝔽,N} = Base.OneTo(N)
+get_iterator(M::PowerManifold{𝔽,<:AbstractManifold{𝔽},Tuple{N}}) where {𝔽,N} = Base.OneTo(N)
 @generated function get_iterator(
-    M::PowerManifold{𝔽,<:Manifold{𝔽},SizeTuple},
+    M::PowerManifold{𝔽,<:AbstractManifold{𝔽},SizeTuple},
 ) where {𝔽,SizeTuple}
     size_tuple = size_to_tuple(SizeTuple)
     return Base.product(map(Base.OneTo, size_tuple)...)
@@ -549,7 +540,7 @@ end
 injectivity_radius(M::AbstractPowerManifold) = injectivity_radius(M.manifold)
 eval(
     quote
-        @invoke_maker 1 Manifold injectivity_radius(
+        @invoke_maker 1 AbstractManifold injectivity_radius(
             M::AbstractPowerManifold,
             rm::AbstractRetractionMethod,
         )
@@ -557,7 +548,7 @@ eval(
 )
 eval(
     quote
-        @invoke_maker 1 Manifold injectivity_radius(
+        @invoke_maker 1 AbstractManifold injectivity_radius(
             M::AbstractPowerManifold,
             rm::ExponentialRetraction,
         )
@@ -621,7 +612,7 @@ end
 Compute the inverse retraction from `p` with respect to `q` on an [`AbstractPowerManifold`](@ref) `M`
 using an [`InversePowerRetraction`](@ref), which by default encapsulates a inverse retraction
 of the base manifold. Then this method is performed elementwise, so the encapsulated inverse
-retraction method has to be one that is available on the base [`Manifold`](@ref).
+retraction method has to be one that is available on the base [`AbstractManifold`](@ref).
 """
 inverse_retract(::AbstractPowerManifold, ::Any...)
 
@@ -690,7 +681,7 @@ $\mathcal M$, the manifold is of dimension
 \dim(\mathcal N) = \dim(\mathcal M)\prod_{i=1}^d n_i = n_1n_2\cdot…\cdot n_d \dim(\mathcal M).
 ````
 """
-function manifold_dimension(M::PowerManifold{𝔽,<:Manifold,TSize}) where {𝔽,TSize}
+function manifold_dimension(M::PowerManifold{𝔽,<:AbstractManifold,TSize}) where {𝔽,TSize}
     return manifold_dimension(M.manifold) * prod(size_to_tuple(TSize))
 end
 
@@ -729,7 +720,7 @@ end
 
 return the power of `M`,
 """
-function power_dimensions(::PowerManifold{𝔽,<:Manifold,TSize}) where {𝔽,TSize}
+function power_dimensions(::PowerManifold{𝔽,<:AbstractManifold,TSize}) where {𝔽,TSize}
     return size_to_tuple(TSize)
 end
 
@@ -800,7 +791,7 @@ end
 Compute the retraction from `p` with tangent vector `X` on an [`AbstractPowerManifold`](@ref) `M`
 using a [`PowerRetraction`](@ref), which by default encapsulates a retraction of the
 base manifold. Then this method is performed elementwise, so the encapsulated retraction
-method has to be one that is available on the base [`Manifold`](@ref).
+method has to be one that is available on the base [`AbstractManifold`](@ref).
 """
 retract(::AbstractPowerManifold, ::Any...)
 
@@ -834,7 +825,7 @@ end
     set_component!(M::AbstractPowerManifold, q, p, idx...)
 
 Set the component of a point `q` on an [`AbstractPowerManifold`](@ref) `M` at index `idx`
-to `p`, which itself is a point on the [`Manifold`](@ref) the power manifold is build on.
+to `p`, which itself is a point on the [`AbstractManifold`](@ref) the power manifold is build on.
 """
 function set_component!(M::AbstractPowerManifold, q, p, idx...)
     rep_size = representation_size(M.manifold)
@@ -1006,14 +997,10 @@ end
     return view(x, i...)
 end
 
-function zero_tangent_vector!(M::AbstractPowerManifold, X, p)
+function zero_vector!(M::AbstractPowerManifold, X, p)
     rep_size = representation_size(M.manifold)
     for i in get_iterator(M)
-        zero_tangent_vector!(
-            M.manifold,
-            _write(M, rep_size, X, i),
-            _read(M, rep_size, p, i),
-        )
+        zero_vector!(M.manifold, _write(M, rep_size, X, i), _read(M, rep_size, p, i))
     end
     return X
 end
diff --git a/src/ValidationManifold.jl b/src/ValidationManifold.jl
index 23628e33..87dbeeca 100644
--- a/src/ValidationManifold.jl
+++ b/src/ValidationManifold.jl
@@ -1,67 +1,80 @@
 """
-    ValidationManifold{𝔽,M<:Manifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
+    ValidationManifold{𝔽,M<:AbstractManifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
 
-A manifold to encapsulate manifolds working on array representations of [`MPoint`](@ref)s
+A manifold to encapsulate manifolds working on array representations of [`AbstractManifoldPoint`](@ref)s
 and [`TVector`](@ref)s in a transparent way, such that for these manifolds it's not
 necessary to introduce explicit types for the points and tangent vectors, but they are
 encapsulated/stripped automatically when needed.
 
-This manifold is a decorator for a manifold, i.e. it decorates a [`Manifold`](@ref) `M`
+This manifold is a decorator for a manifold, i.e. it decorates a [`AbstractManifold`](@ref) `M`
 with types points, vectors, and covectors.
 """
-struct ValidationManifold{𝔽,M<:Manifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
+struct ValidationManifold{𝔽,M<:AbstractManifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
     manifold::M
 end
 
 """
-    ValidationMPoint <: MPoint
+    ValidationMPoint <: AbstractManifoldPoint
 
 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 [`ValidationTVector`](@ref)s and [`ValidationCoTVector`](@ref)s.
 """
-struct ValidationMPoint{V<:AbstractArray{<:Number}} <: MPoint
+struct ValidationMPoint{V} <: AbstractManifoldPoint
     value::V
 end
 
 """
-    ValidationTVector <: TVector
+    ValidationFibreVector{TType<:VectorSpaceType} <: AbstractFibreVector{TType}
 
 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 [`ValidationMPoint`](@ref)s and [`ValidationCoTVector`](@ref)s.
+This distinguished the value from [`ValidationMPoint`](@ref)s vectors of other types.
 """
-struct ValidationTVector{V<:AbstractArray{<:Number}} <: TVector
+struct ValidationFibreVector{TType<:VectorSpaceType,V} <: AbstractFibreVector{TType}
     value::V
 end
+function ValidationFibreVector{TType}(value::V) where {TType,V}
+    return ValidationFibreVector{TType,V}(value)
+end
 
 """
-    ValidationCoTVector <: CoTVector
+    ValidationTVector = ValidationFibreVector{TangentSpaceType}
 
-Represent a cotangent vector to a point on an [`ValidationManifold`](@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 [`ValidationMPoint`](@ref)s and [`ValidationTVector`](@ref)s.
+This distinguished the value from [`ValidationMPoint`](@ref)s vectors of other types.
 """
-struct ValidationCoTVector{V<:AbstractArray{<:Number}} <: TVector
-    value::V
-end
+const ValidationTVector = ValidationFibreVector{TangentSpaceType}
+
+"""
+    ValidationCoTVector = ValidationFibreVector{CotangentSpaceType}
 
-(+)(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)
+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 [`ValidationMPoint`](@ref)s vectors of other types.
+"""
+const ValidationCoTVector = ValidationFibreVector{CotangentSpaceType}
 
-(+)(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)
 
+function (+)(X::ValidationFibreVector{TType}, Y::ValidationFibreVector{TType}) where {TType}
+    return ValidationFibreVector{TType}(X.value + Y.value)
+end
+function (-)(X::ValidationFibreVector{TType}, Y::ValidationFibreVector{TType}) where {TType}
+    return ValidationFibreVector{TType}(X.value - Y.value)
+end
+(-)(X::ValidationFibreVector{TType}) where {TType} = ValidationFibreVector{TType}(-X.value)
+function (*)(a::Number, X::ValidationFibreVector{TType}) where {TType}
+    return ValidationFibreVector{TType}(a * X.value)
+end
 
 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))
-function allocate(X::ValidationTVector, ::Type{T}) where {T}
-    return ValidationTVector(allocate(X.value, T))
+function allocate(X::ValidationFibreVector{TType}) where {TType}
+    return ValidationFibreVector{TType}(allocate(X.value))
+end
+function allocate(X::ValidationFibreVector{TType}, ::Type{T}) where {TType,T}
+    return ValidationFibreVector{TType}(allocate(X.value, T))
 end
 
 """
@@ -73,95 +86,90 @@ already an array.
 """
 array_value(p::AbstractArray) = p
 array_value(p::ValidationMPoint) = p.value
-array_value(X::ValidationTVector) = X.value
-array_value(ξ::ValidationCoTVector) = ξ.value
+array_value(X::ValidationFibreVector) = X.value
 
-function check_manifold_point(M::ValidationManifold, p; kwargs...)
-    return check_manifold_point(M.manifold, array_value(p); kwargs...)
+function check_point(M::ValidationManifold, p; kwargs...)
+    return check_point(M.manifold, array_value(p); kwargs...)
 end
-function check_manifold_point(M::ValidationManifold, p::MPoint; kwargs...)
-    return check_manifold_point(M.manifold, array_value(p); kwargs...)
+function check_point(M::ValidationManifold, p::AbstractManifoldPoint; kwargs...)
+    return check_point(M.manifold, array_value(p); kwargs...)
 end
 
-function check_tangent_vector(M::ValidationManifold, p, X; kwargs...)
-    return check_tangent_vector(M.manifold, array_value(p), array_value(X); kwargs...)
+function check_vector(M::ValidationManifold, p, X; kwargs...)
+    return check_vector(M.manifold, array_value(p), array_value(X); kwargs...)
 end
-function check_tangent_vector(M::ValidationManifold, p::MPoint, X::TVector; kwargs...)
-    return check_tangent_vector(M.manifold, array_value(p), array_value(X); kwargs...)
+function check_vector(
+    M::ValidationManifold,
+    p::AbstractManifoldPoint,
+    X::TVector;
+    kwargs...,
+)
+    return check_vector(M.manifold, array_value(p), array_value(X); kwargs...)
 end
 
-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::ValidationManifold{𝔽,M}) where {𝔽,M<:Manifold{𝔽}} = m.manifold
-function convert(::Type{ValidationManifold{𝔽,M}}, m::M) where {𝔽,M<:Manifold{𝔽}}
+convert(::Type{M}, m::ValidationManifold{𝔽,M}) where {𝔽,M<:AbstractManifold{𝔽}} = m.manifold
+function convert(::Type{ValidationManifold{𝔽,M}}, m::M) where {𝔽,M<:AbstractManifold{𝔽}}
     return ValidationManifold(m)
 end
-convert(::Type{V}, p::ValidationMPoint{V}) where {V<:AbstractArray{<:Number}} = p.value
-function convert(::Type{ValidationMPoint{V}}, x::V) where {V<:AbstractArray{<:Number}}
+convert(::Type{V}, p::ValidationMPoint{V}) where {V<:AbstractArray} = p.value
+function convert(::Type{ValidationMPoint{V}}, x::V) where {V<:AbstractArray}
     return ValidationMPoint{V}(x)
 end
-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)
+function convert(
+    ::Type{V},
+    X::ValidationFibreVector{TType,V},
+) where {TType,V<:AbstractArray}
+    return X.value
+end
+function convert(
+    ::Type{ValidationFibreVector{TType,V}},
+    X::V,
+) where {TType,V<:AbstractArray}
+    return ValidationFibreVector{TType,V}(X)
 end
 
 function copyto!(M::ValidationManifold, q::ValidationMPoint, p::ValidationMPoint; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
+    is_point(M, p, true; kwargs...)
     copyto!(M.manifold, q.value, p.value)
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     return q
 end
 function copyto!(
     M::ValidationManifold,
-    Y::ValidationCoTVector,
+    Y::ValidationFibreVector{TType},
     p::ValidationMPoint,
-    X::ValidationCoTVector;
+    X::ValidationFibreVector{TType};
     kwargs...,
-)
-    is_manifold_point(M, p, true; kwargs...)
+) where {TType}
+    is_point(M, p, true; kwargs...)
     copyto!(M.manifold, Y.value, p.value, X.value)
     return p
 end
-function copyto!(
-    M::ValidationManifold,
-    Y::ValidationTVector,
-    p::ValidationMPoint,
-    X::ValidationTVector;
-    kwargs...,
-)
-    is_manifold_point(M, p, true; kwargs...)
-    is_tangent_vector(M, p, X, true; kwargs...)
-    copyto!(M.manifold, Y.value, p.value, X.value)
-    is_tangent_vector(M, p, Y, true; kwargs...)
-    return Y
-end
 
 function distance(M::ValidationManifold, p, q; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, p, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     return distance(M.manifold, array_value(p), array_value(q))
 end
 
 function exp(M::ValidationManifold, p, X; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
-    is_tangent_vector(M, p, X, true; kwargs...)
+    is_point(M, p, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     y = exp(M.manifold, array_value(p), array_value(X))
-    is_manifold_point(M, y, true; kwargs...)
+    is_point(M, y, true; kwargs...)
     return ValidationMPoint(y)
 end
 
 function exp!(M::ValidationManifold, q, p, X; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
-    is_tangent_vector(M, p, X, true; kwargs...)
+    is_point(M, p, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     exp!(M.manifold, array_value(q), array_value(p), array_value(X))
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     return q
 end
 
 function get_basis(M::ValidationManifold, p, B::AbstractBasis; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
+    is_point(M, p, true; kwargs...)
     Ξ = get_basis(M.manifold, array_value(p), B)
     bvectors = get_vectors(M, p, Ξ)
     N = length(bvectors)
@@ -181,7 +189,7 @@ function get_basis(M::ValidationManifold, p, B::AbstractBasis; kwargs...)
             ),
         )
     end
-    map(X -> is_tangent_vector(M, p, X, true; kwargs...), bvectors)
+    map(X -> is_vector(M, p, X, true; kwargs...), bvectors)
     return Ξ
 end
 function get_basis(
@@ -190,7 +198,7 @@ function get_basis(
     B::Union{AbstractOrthogonalBasis,CachedBasis{𝔽,<:AbstractOrthogonalBasis{𝔽}}};
     kwargs...,
 ) where {𝔽}
-    is_manifold_point(M, p, true; kwargs...)
+    is_point(M, p, true; kwargs...)
     Ξ = invoke(get_basis, Tuple{ValidationManifold,Any,AbstractBasis}, M, p, B; kwargs...)
     bvectors = get_vectors(M, p, Ξ)
     N = length(bvectors)
@@ -214,7 +222,7 @@ function get_basis(
     B::Union{AbstractOrthonormalBasis,CachedBasis{𝔽,<:AbstractOrthonormalBasis{𝔽}}};
     kwargs...,
 ) where {𝔽}
-    is_manifold_point(M, p, true; kwargs...)
+    is_point(M, p, true; kwargs...)
     get_basis_invoke_types = Tuple{
         ValidationManifold,
         Any,
@@ -250,8 +258,8 @@ for BT in DISAMBIGUATION_BASIS_TYPES
 end
 
 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...)
+    is_point(M, p, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     return get_coordinates(M.manifold, p, X, B)
 end
 for BT in DISAMBIGUATION_BASIS_TYPES
@@ -269,11 +277,11 @@ for BT in DISAMBIGUATION_BASIS_TYPES
 end
 
 function get_coordinates!(M::ValidationManifold, Y, p, X, B::AbstractBasis; kwargs...)
-    is_tangent_vector(M, p, X, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     get_coordinates!(M.manifold, Y, p, X, B)
     return Y
 end
-for BT in DISAMBIGUATION_BASIS_TYPES
+for BT in [DISAMBIGUATION_BASIS_TYPES..., DISAMBIGUATION_COTANGENT_BASIS_TYPES...]
     eval(
         quote
             @invoke_maker 5 AbstractBasis get_coordinates!(
@@ -289,7 +297,7 @@ for BT in DISAMBIGUATION_BASIS_TYPES
 end
 
 function get_vector(M::ValidationManifold, p, X, B::AbstractBasis; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
+    is_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)
     size(Y) == representation_size(M) || error("Incorrect size of tangent vector Y")
@@ -310,13 +318,13 @@ for BT in DISAMBIGUATION_BASIS_TYPES
 end
 
 function get_vector!(M::ValidationManifold, Y, p, X, B::AbstractBasis; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
+    is_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)
     size(Y) == representation_size(M) || error("Incorrect size of tangent vector Y")
     return Y
 end
-for BT in DISAMBIGUATION_BASIS_TYPES
+for BT in [DISAMBIGUATION_BASIS_TYPES..., DISAMBIGUATION_COTANGENT_BASIS_TYPES...]
     eval(
         quote
             @invoke_maker 5 AbstractBasis get_vector!(
@@ -336,7 +344,7 @@ function injectivity_radius(M::ValidationManifold, method::AbstractRetractionMet
     return injectivity_radius(M.manifold, method)
 end
 function injectivity_radius(M::ValidationManifold, p; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
+    is_point(M, p, true; kwargs...)
     return injectivity_radius(M.manifold, array_value(p))
 end
 function injectivity_radius(
@@ -345,7 +353,7 @@ function injectivity_radius(
     method::AbstractRetractionMethod;
     kwargs...,
 )
-    is_manifold_point(M, p, true; kwargs...)
+    is_point(M, p, true; kwargs...)
     return injectivity_radius(M.manifold, array_value(p), method)
 end
 function injectivity_radius(M::ValidationManifold, method::ExponentialRetraction)
@@ -357,83 +365,81 @@ function injectivity_radius(
     method::ExponentialRetraction;
     kwargs...,
 )
-    is_manifold_point(M, p, true; kwargs...)
+    is_point(M, p, true; kwargs...)
     return injectivity_radius(M.manifold, array_value(p), method)
 end
 
 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...)
+    is_point(M, p, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
+    is_vector(M, p, Y, true; kwargs...)
     return inner(M.manifold, array_value(p), array_value(X), array_value(Y))
 end
 
 function isapprox(M::ValidationManifold, p, q; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, p, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     return isapprox(M.manifold, array_value(p), array_value(q); kwargs...)
 end
 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...)
+    is_point(M, p, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
+    is_vector(M, p, Y, true; kwargs...)
     return isapprox(M.manifold, array_value(p), array_value(X), array_value(Y); kwargs...)
 end
 
 function log(M::ValidationManifold, p, q; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, p, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     X = log(M.manifold, array_value(p), array_value(q))
-    is_tangent_vector(M, p, X, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     return ValidationTVector(X)
 end
 
 function log!(M::ValidationManifold, X, p, q; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, p, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     log!(M.manifold, array_value(X), array_value(p), array_value(q))
-    is_tangent_vector(M, p, X, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     return X
 end
 
 function mid_point(M::ValidationManifold, p1, p2; kwargs...)
-    is_manifold_point(M, p1, true; kwargs...)
-    is_manifold_point(M, p2, true; kwargs...)
+    is_point(M, p1, true; kwargs...)
+    is_point(M, p2, true; kwargs...)
     q = mid_point(M.manifold, array_value(p1), array_value(p2))
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     return q
 end
 
 function mid_point!(M::ValidationManifold, q, p1, p2; kwargs...)
-    is_manifold_point(M, p1, true; kwargs...)
-    is_manifold_point(M, p2, true; kwargs...)
+    is_point(M, p1, true; kwargs...)
+    is_point(M, p2, true; kwargs...)
     mid_point!(M.manifold, array_value(q), array_value(p1), array_value(p2))
-    is_manifold_point(M, q, true; kwargs...)
+    is_point(M, q, true; kwargs...)
     return q
 end
 
 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)
+number_eltype(::Type{ValidationFibreVector{TType,V}}) where {TType,V} = number_eltype(V)
+number_eltype(X::ValidationFibreVector) = number_eltype(X.value)
 
 function project!(M::ValidationManifold, Y, p, X; kwargs...)
-    is_manifold_point(M, p, true; kwargs...)
+    is_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...)
+    is_vector(M, p, Y, true; kwargs...)
     return Y
 end
 
 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))
-function similar(p::ValidationCoTVector, ::Type{T}) where {T}
-    return ValidationCoTVector(similar(p.value, T))
+function similar(X::ValidationFibreVector{TType}) where {TType}
+    return ValidationFibreVector{TType}(similar(X.value))
+end
+function similar(X::ValidationFibreVector{TType}, ::Type{T}) where {TType,T}
+    return ValidationFibreVector{TType}(similar(X.value, T))
 end
-similar(X::ValidationTVector) = ValidationTVector(similar(X.value))
-similar(X::ValidationTVector, ::Type{T}) where {T} = ValidationTVector(similar(X.value, T))
 
 function vector_transport_along!(
     M::ValidationManifold,
@@ -444,7 +450,7 @@ function vector_transport_along!(
     m::AbstractVectorTransportMethod;
     kwargs...,
 )
-    is_tangent_vector(M, p, X, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     vector_transport_along!(
         M.manifold,
         array_value(Y),
@@ -453,7 +459,7 @@ function vector_transport_along!(
         c,
         m,
     )
-    is_tangent_vector(M, c[end], Y, true; kwargs...)
+    is_vector(M, c[end], Y, true; kwargs...)
     return Y
 end
 for VT in VECTOR_TRANSPORT_DISAMBIGUATION
@@ -480,8 +486,8 @@ function vector_transport_to!(
     m::AbstractVectorTransportMethod;
     kwargs...,
 )
-    is_manifold_point(M, q, true; kwargs...)
-    is_tangent_vector(M, p, X, true; kwargs...)
+    is_point(M, q, true; kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     vector_transport_to!(
         M.manifold,
         array_value(Y),
@@ -490,7 +496,7 @@ function vector_transport_to!(
         array_value(q),
         m,
     )
-    is_tangent_vector(M, q, Y, true; kwargs...)
+    is_vector(M, q, Y, true; kwargs...)
     return Y
 end
 
@@ -502,8 +508,8 @@ for T in [
 ]
     @eval begin
         function vector_transport_to!(M::ValidationManifold, Y, p, X, q, m::$T; kwargs...)
-            is_manifold_point(M, q, true; kwargs...)
-            is_tangent_vector(M, p, X, true; kwargs...)
+            is_point(M, q, true; kwargs...)
+            is_vector(M, p, X, true; kwargs...)
             vector_transport_to!(
                 M.manifold,
                 array_value(Y),
@@ -512,22 +518,22 @@ for T in [
                 array_value(q),
                 m,
             )
-            is_tangent_vector(M, q, Y, true; kwargs...)
+            is_vector(M, q, Y, true; kwargs...)
             return Y
         end
     end
 end
 
-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...)
+function zero_vector(M::ValidationManifold, p; kwargs...)
+    is_point(M, p, true; kwargs...)
+    w = zero_vector(M.manifold, array_value(p))
+    is_vector(M, p, w, true; kwargs...)
     return w
 end
 
-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...)
+function zero_vector!(M::ValidationManifold, X, p; kwargs...)
+    is_point(M, p, true; kwargs...)
+    zero_vector!(M.manifold, array_value(X), array_value(p); kwargs...)
+    is_vector(M, p, X, true; kwargs...)
     return X
 end
diff --git a/src/bases.jl b/src/bases.jl
index bb175da2..f2bb6881 100644
--- a/src/bases.jl
+++ b/src/bases.jl
@@ -1,73 +1,167 @@
 """
-    AbstractBasis{𝔽}
+    VectorSpaceType
 
-Abstract type that represents a basis on a manifold or a subset of it.
+Abstract type for tangent spaces, cotangent spaces, their tensor products,
+exterior products, etc.
+
+Every vector space `fiber` is supposed to provide:
+* a method of constructing vectors,
+* basic operations: addition, subtraction, multiplication by a scalar
+  and negation (unary minus),
+* [`zero_vector(fiber, p)`](@ref Main.Manifolds.zero_vector) to construct zero vectors at point `p`,
+* `allocate(X)` and `allocate(X, T)` for vector `X` and type `T`,
+* `copyto!(X, Y)` for vectors `X` and `Y`,
+* `number_eltype(v)` for vector `v`,
+* [`vector_space_dimension`](@ref).
+
+Optionally:
+* inner product via `inner` (used to provide Riemannian metric on vector
+  bundles),
+* [`flat`](@ref Main.Manifolds.flat) and [`sharp`](@ref Main.Manifolds.sharp),
+* `norm` (by default uses `inner`),
+* [`project`](@ref) (for embedded vector spaces),
+* [`representation_size`](@ref) (if support for [`ProductArray`](@ref Main.Manifolds.ProductArray) is desired),
+* broadcasting for basic operations.
+"""
+abstract type VectorSpaceType end
+
+struct TangentSpaceType <: VectorSpaceType end
+
+struct CotangentSpaceType <: VectorSpaceType end
+
+TCoTSpaceType = Union{TangentSpaceType,CotangentSpaceType}
+
+const TangentSpace = TangentSpaceType()
+const CotangentSpace = CotangentSpaceType()
+
+"""
+    AbstractBasis{𝔽,VST<:VectorSpaceType}
+
+Abstract type that represents a basis of vector space of type `VST` on a manifold or
+a subset of it.
 
 The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be used
 for the vectors elements.
+
+# See also
+
+[`VectorSpaceType`](@ref)
 """
-abstract type AbstractBasis{𝔽} end
+abstract type AbstractBasis{𝔽,VST<:VectorSpaceType} end
 
 """
-    DefaultBasis{𝔽}
+    DefaultBasis{𝔽,VST<:VectorSpaceType}
 
-An arbitrary basis on a manifold. This will usually
+An arbitrary basis of vector space of type `VST` on a manifold. This will usually
 be the fastest basis available for a manifold.
 
 The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be used
-for the vectors elements
+for the vectors elements.
+
+# See also
+
+[`VectorSpaceType`](@ref)
 """
-struct DefaultBasis{𝔽} <: AbstractBasis{𝔽} end
-DefaultBasis(𝔽::AbstractNumbers = ℝ) = DefaultBasis{𝔽}()
+struct DefaultBasis{𝔽,VST<:VectorSpaceType} <: AbstractBasis{𝔽,VST}
+    vector_space::VST
+end
+function DefaultBasis(𝔽::AbstractNumbers = ℝ, vs::VectorSpaceType = TangentSpace)
+    return DefaultBasis{𝔽,typeof(vs)}(vs)
+end
+function DefaultBasis{𝔽}(vs::VectorSpaceType = TangentSpace) where {𝔽}
+    return DefaultBasis{𝔽,typeof(vs)}(vs)
+end
+function DefaultBasis{𝔽,TangentSpaceType}() where {𝔽}
+    return DefaultBasis{𝔽,TangentSpaceType}(TangentSpace)
+end
 
 """
-    AbstractOrthogonalBasis{𝔽}
+    AbstractOrthogonalBasis{𝔽,VST<:VectorSpaceType}
 
-Abstract type that represents an orthonormal basis on a manifold or a subset of it.
+Abstract type that represents an orthonormal basis of vector space of type `VST` on a
+manifold or a subset of it.
 
 The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be used
 for the vectors elements.
+
+# See also
+
+[`VectorSpaceType`](@ref)
 """
-abstract type AbstractOrthogonalBasis{𝔽} <: AbstractBasis{𝔽} end
+abstract type AbstractOrthogonalBasis{𝔽,VST<:VectorSpaceType} <: AbstractBasis{𝔽,VST} end
 
 """
-    DefaultOrthogonalBasis{𝔽}
+    DefaultOrthogonalBasis{𝔽,VST<:VectorSpaceType}
 
-An arbitrary orthogonal basis on a manifold. This will usually
+An arbitrary orthogonal basis of vector space of type `VST` on a manifold. This will usually
 be the fastest orthogonal basis available for a manifold.
 
 The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be used
 for the vectors elements.
+
+# See also
+
+[`VectorSpaceType`](@ref)
 """
-struct DefaultOrthogonalBasis{𝔽} <: AbstractOrthogonalBasis{𝔽} end
-DefaultOrthogonalBasis(𝔽::AbstractNumbers = ℝ) = DefaultOrthogonalBasis{𝔽}()
+struct DefaultOrthogonalBasis{𝔽,VST<:VectorSpaceType} <: AbstractOrthogonalBasis{𝔽,VST}
+    vector_space::VST
+end
+function DefaultOrthogonalBasis(𝔽::AbstractNumbers = ℝ, vs::VectorSpaceType = TangentSpace)
+    return DefaultOrthogonalBasis{𝔽,typeof(vs)}(vs)
+end
+function DefaultOrthogonalBasis{𝔽}(vs::VectorSpaceType = TangentSpace) where {𝔽}
+    return DefaultOrthogonalBasis{𝔽,typeof(vs)}(vs)
+end
+function DefaultOrthogonalBasis{𝔽,TangentSpaceType}() where {𝔽}
+    return DefaultOrthogonalBasis{𝔽,TangentSpaceType}(TangentSpace)
+end
 
 
-struct VeeOrthogonalBasis{𝔽} <: AbstractOrthogonalBasis{𝔽} end
+struct VeeOrthogonalBasis{𝔽} <: AbstractOrthogonalBasis{𝔽,TangentSpaceType} end
 VeeOrthogonalBasis(𝔽::AbstractNumbers = ℝ) = VeeOrthogonalBasis{𝔽}()
 
 """
-    AbstractOrthonormalBasis{𝔽}
+    AbstractOrthonormalBasis{𝔽,VST<:VectorSpaceType}
 
-Abstract type that represents an orthonormal basis on a manifold or a subset of it.
+Abstract type that represents an orthonormal basis of vector space of type `VST` on a
+manifold or a subset of it.
 
 The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be used
 for the vectors elements.
+
+# See also
+
+[`VectorSpaceType`](@ref)
 """
-abstract type AbstractOrthonormalBasis{𝔽} <: AbstractOrthogonalBasis{𝔽} end
+abstract type AbstractOrthonormalBasis{𝔽,VST<:VectorSpaceType} <:
+              AbstractOrthogonalBasis{𝔽,VST} end
 
 """
-    DefaultOrthonormalBasis(𝔽::AbstractNumbers = ℝ)
+    DefaultOrthonormalBasis(𝔽::AbstractNumbers = ℝ, vs::VectorSpaceType = TangentSpace)
 
-An arbitrary orthonormal basis on a manifold. This will usually
+An arbitrary orthonormal basis of vector space of type `VST` on a manifold. This will usually
 be the fastest orthonormal basis available for a manifold.
 
 The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be used
 for the vectors elements.
+
+# See also
+
+[`VectorSpaceType`](@ref)
 """
-struct DefaultOrthonormalBasis{𝔽} <: AbstractOrthonormalBasis{𝔽} end
+struct DefaultOrthonormalBasis{𝔽,VST<:VectorSpaceType} <: AbstractOrthonormalBasis{𝔽,VST}
+    vector_space::VST
+end
 
-DefaultOrthonormalBasis(𝔽::AbstractNumbers = ℝ) = DefaultOrthonormalBasis{𝔽}()
+function DefaultOrthonormalBasis(𝔽::AbstractNumbers = ℝ, vs::VectorSpaceType = TangentSpace)
+    return DefaultOrthonormalBasis{𝔽,typeof(vs)}(vs)
+end
+function DefaultOrthonormalBasis{𝔽}(vs::VectorSpaceType = TangentSpace) where {𝔽}
+    return DefaultOrthonormalBasis{𝔽,typeof(vs)}(vs)
+end
+function DefaultOrthonormalBasis{𝔽,TangentSpaceType}() where {𝔽}
+    return DefaultOrthonormalBasis{𝔽,TangentSpaceType}(TangentSpace)
+end
 
 """
     ProjectedOrthonormalBasis(method::Symbol, 𝔽::AbstractNumbers = ℝ)
@@ -86,7 +180,7 @@ Available methods:
     an additional assumption (local metric tensor at a point where the
     basis is calculated has to be diagonal).
 """
-struct ProjectedOrthonormalBasis{Method,𝔽} <: AbstractOrthonormalBasis{𝔽} end
+struct ProjectedOrthonormalBasis{Method,𝔽} <: AbstractOrthonormalBasis{𝔽,TangentSpaceType} end
 
 function ProjectedOrthonormalBasis(method::Symbol, 𝔽::AbstractNumbers = ℝ)
     return ProjectedOrthonormalBasis{method,𝔽}()
@@ -100,11 +194,11 @@ An orthonormal basis obtained from a basis.
 # Constructor
     GramSchmidtOrthonormalBasis(𝔽::AbstractNumbers = ℝ)
 """
-struct GramSchmidtOrthonormalBasis{𝔽} <: AbstractOrthonormalBasis{𝔽} end
+struct GramSchmidtOrthonormalBasis{𝔽} <: AbstractOrthonormalBasis{𝔽,TangentSpaceType} end
 GramSchmidtOrthonormalBasis(𝔽::AbstractNumbers = ℝ) = GramSchmidtOrthonormalBasis{𝔽}()
 
 @doc raw"""
-    DiagonalizingOrthonormalBasis{𝔽,TV} <: AbstractOrthonormalBasis{𝔽}
+    DiagonalizingOrthonormalBasis{𝔽,TV} <: AbstractOrthonormalBasis{𝔽,TangentSpaceType}
 
 An orthonormal basis `Ξ` as a vector of tangent vectors (of length determined by
 [`manifold_dimension`](@ref)) in the tangent space that diagonalizes the curvature
@@ -114,9 +208,10 @@ The type parameter `𝔽` denotes the [`AbstractNumbers`](@ref) that will be use
 for the vectors elements.
 
 # Constructor
+
     DiagonalizingOrthonormalBasis(frame_direction, 𝔽::AbstractNumbers = ℝ)
 """
-struct DiagonalizingOrthonormalBasis{𝔽,TV} <: AbstractOrthonormalBasis{𝔽}
+struct DiagonalizingOrthonormalBasis{𝔽,TV} <: AbstractOrthonormalBasis{𝔽,TangentSpaceType}
     frame_direction::TV
 end
 function DiagonalizingOrthonormalBasis(X, 𝔽::AbstractNumbers = ℝ)
@@ -129,7 +224,7 @@ struct DiagonalizingBasisData{D,V,ET}
 end
 
 const DefaultOrDiagonalizingBasis{𝔽} =
-    Union{DefaultOrthonormalBasis{𝔽},DiagonalizingOrthonormalBasis{𝔽}}
+    Union{DefaultOrthonormalBasis{𝔽,TangentSpaceType},DiagonalizingOrthonormalBasis{𝔽}}
 
 """
     CachedBasis{𝔽,V,<:AbstractBasis{𝔽}} <: AbstractBasis{𝔽}
@@ -142,10 +237,11 @@ are stored in `data`, either explicitly (like in cached variants of
 
     CachedBasis(basis::AbstractBasis, data)
 """
-struct CachedBasis{𝔽,B,V} <: AbstractBasis{𝔽} where {B<:AbstractBasis{𝔽},V}
+struct CachedBasis{𝔽,B,V} <:
+       AbstractBasis{𝔽,TangentSpaceType} where {B<:AbstractBasis{𝔽,TangentSpaceType},V}
     data::V
 end
-function CachedBasis(::B, data::V) where {V,𝔽,B<:AbstractBasis{𝔽}}
+function CachedBasis(::B, data::V) where {V,𝔽,B<:AbstractBasis{𝔽,TangentSpaceType}}
     return CachedBasis{𝔽,B,V}(data)
 end
 function CachedBasis(basis::CachedBasis) # avoid double encapsulation
@@ -164,47 +260,74 @@ end
 function get_coordinates end
 function get_vector end
 
-const all_uncached_bases =
-    Union{AbstractBasis,DefaultBasis,DefaultOrthogonalBasis,DefaultOrthonormalBasis}
+const all_uncached_bases{T} = Union{
+    AbstractBasis{<:Any,T},
+    DefaultBasis{<:Any,T},
+    DefaultOrthogonalBasis{<:Any,T},
+    DefaultOrthonormalBasis{<:Any,T},
+}
 const DISAMBIGUATION_BASIS_TYPES = [
     CachedBasis,
     DefaultBasis,
+    DefaultBasis{<:Any,TangentSpaceType},
     DefaultOrthonormalBasis,
+    DefaultOrthonormalBasis{<:Any,TangentSpaceType},
     DefaultOrthogonalBasis,
+    DefaultOrthogonalBasis{<:Any,TangentSpaceType},
     DiagonalizingOrthonormalBasis,
     ProjectedOrthonormalBasis{:svd,ℝ},
     ProjectedOrthonormalBasis{:gram_schmidt,ℝ},
     VeeOrthogonalBasis,
 ]
+const DISAMBIGUATION_COTANGENT_BASIS_TYPES = [
+    DefaultBasis{<:Any,CotangentSpaceType},
+    DefaultOrthonormalBasis{<:Any,CotangentSpaceType},
+    DefaultOrthogonalBasis{<:Any,CotangentSpaceType},
+]
+
 
-function allocate_result(M::Manifold, f::typeof(get_coordinates), p, X, B::AbstractBasis)
+function allocate_result(
+    M::AbstractManifold,
+    f::typeof(get_coordinates),
+    p,
+    X,
+    B::AbstractBasis,
+)
     T = allocate_result_type(M, f, (p, X))
     return allocate(p, T, number_of_coordinates(M, B))
 end
 
-function allocate_result(M::Manifold, f::typeof(get_coordinates), p, X, B::CachedBasis)
+function allocate_result(
+    M::AbstractManifold,
+    f::typeof(get_coordinates),
+    p,
+    X,
+    B::CachedBasis,
+)
     T = allocate_result_type(M, f, (p, X))
     return allocate(p, T, number_of_coordinates(M, B))
 end
 
 @inline function allocate_result_type(
-    M::Manifold,
+    M::AbstractManifold,
     f::Union{typeof(get_coordinates),typeof(get_vector)},
     args::Tuple,
 )
     apf = allocation_promotion_function(M, f, args)
-    return apf(invoke(allocate_result_type, Tuple{Manifold,Any,typeof(args)}, M, f, args))
+    return apf(
+        invoke(allocate_result_type, Tuple{AbstractManifold,Any,typeof(args)}, M, f, args),
+    )
 end
 
 """
-    allocation_promotion_function(M::Manifold, f, args::Tuple)
+    allocation_promotion_function(M::AbstractManifold, f, args::Tuple)
 
 Determine the function that must be used to ensure that the allocated representation is of
 the right type. This is needed for [`get_vector`](@ref) when a point on a complex manifold
 is represented by a real-valued vectors with a real-coefficient basis, so that
 a complex-valued vector representation is allocated.
 """
-allocation_promotion_function(M::Manifold, f, args::Tuple) = identity
+allocation_promotion_function(M::AbstractManifold, f, args::Tuple) = identity
 
 function combine_allocation_promotion_functions(f::T, ::T) where {T}
     return f
@@ -216,6 +339,37 @@ function combine_allocation_promotion_functions(::typeof(identity), ::typeof(com
     return complex
 end
 
+@doc raw"""
+    dual_basis(M::AbstractManifold, p, B::AbstractBasis) 
+
+Get the dual basis to `B`, a basis of a vector space at point `p` from manifold `M`.
+
+The dual to the $i$th vector $v_i$ from basis `B` is a vector $v^i$ from the dual space
+such that $v^i(v_j) = δ^i_j$, where $δ^i_j$ is the Kronecker delta symbol:
+````math
+δ^i_j = \begin{cases}
+1 & \text{ if } i=j, \\
+0 & \text{ otherwise.}
+\end{cases}
+````
+"""
+dual_basis(M::AbstractManifold, p, B::AbstractBasis)
+
+function dual_basis(
+    ::AbstractManifold,
+    p,
+    ::DefaultOrthonormalBasis{𝔽,TangentSpaceType},
+) where {𝔽}
+    return DefaultOrthonormalBasis{𝔽}(CotangentSpace)
+end
+function dual_basis(
+    ::AbstractManifold,
+    p,
+    ::DefaultOrthonormalBasis{𝔽,CotangentSpaceType},
+) where {𝔽}
+    return DefaultOrthonormalBasis{𝔽}(TangentSpace)
+end
+
 function _euclidean_basis_vector(p, i)
     X = zero(p)
     X[i] = 1
@@ -223,7 +377,7 @@ function _euclidean_basis_vector(p, i)
 end
 
 """
-    get_basis(M::Manifold, p, B::AbstractBasis) -> CachedBasis
+    get_basis(M::AbstractManifold, p, B::AbstractBasis) -> CachedBasis
 
 Compute the basis vectors of the tangent space at a point on manifold `M`
 represented by `p`.
@@ -234,31 +388,31 @@ the function [`get_vectors`](@ref) needs to be used to retrieve the basis vector
 
 See also: [`get_coordinates`](@ref), [`get_vector`](@ref)
 """
-function get_basis(M::Manifold, p, B::AbstractBasis)
-    return error(
-        "get_basis not implemented for manifold of type $(typeof(M)) a point of type $(typeof(p)) and basis of type $(typeof(B)).",
-    )
-end
+get_basis(M::AbstractManifold, p, B::AbstractBasis)
 @decorator_transparent_signature get_basis(
     M::AbstractDecoratorManifold,
     p,
     B::AbstractBasis,
 )
-function decorator_transparent_dispatch(::typeof(get_basis), ::Manifold, args...)
+function decorator_transparent_dispatch(::typeof(get_basis), ::AbstractManifold, args...)
     return Val(:parent)
 end
 
-function get_basis(M::Manifold, p, B::DefaultOrthonormalBasis)
+function get_basis(
+    M::AbstractManifold,
+    p,
+    B::DefaultOrthonormalBasis{<:Any,TangentSpaceType},
+)
     dim = manifold_dimension(M)
     return CachedBasis(
         B,
         [get_vector(M, p, [ifelse(i == j, 1, 0) for j in 1:dim], B) for i in 1:dim],
     )
 end
-function get_basis(::Manifold, ::Any, B::CachedBasis)
+function get_basis(::AbstractManifold, ::Any, B::CachedBasis)
     return B
 end
-function get_basis(M::Manifold, p, B::ProjectedOrthonormalBasis{:svd,ℝ})
+function get_basis(M::AbstractManifold, p, B::ProjectedOrthonormalBasis{:svd,ℝ})
     S = representation_size(M)
     PS = prod(S)
     dim = manifold_dimension(M)
@@ -282,7 +436,7 @@ function get_basis(M::Manifold, p, B::ProjectedOrthonormalBasis{:svd,ℝ})
     return CachedBasis(B, vecs)
 end
 function get_basis(
-    M::Manifold,
+    M::AbstractManifold,
     p,
     B::ProjectedOrthonormalBasis{:gram_schmidt,ℝ};
     warn_linearly_dependent = false,
@@ -313,8 +467,8 @@ for BT in DISAMBIGUATION_BASIS_TYPES
 end
 
 @doc raw"""
-    get_coordinates(M::Manifold, p, X, B::AbstractBasis)
-    get_coordinates(M::Manifold, p, X, B::CachedBasis)
+    get_coordinates(M::AbstractManifold, p, X, B::AbstractBasis)
+    get_coordinates(M::AbstractManifold, p, X, B::CachedBasis)
 
 Compute a one-dimensional vector of coefficients of the tangent vector `X`
 at point denoted by `p` on manifold `M` in basis `B`.
@@ -329,7 +483,7 @@ requires either a dual basis or the cached basis to be selfdual, for example ort
 
 See also: [`get_vector`](@ref), [`get_basis`](@ref)
 """
-function get_coordinates(M::Manifold, p, X, B::AbstractBasis)
+function get_coordinates(M::AbstractManifold, p, X, B::AbstractBasis)
     Y = allocate_result(M, get_coordinates, p, X, B)
     return get_coordinates!(M, Y, p, X, B)
 end
@@ -339,11 +493,15 @@ end
     X,
     B::AbstractBasis,
 )
-function decorator_transparent_dispatch(::typeof(get_coordinates), ::Manifold, args...)
+function decorator_transparent_dispatch(
+    ::typeof(get_coordinates),
+    ::AbstractManifold,
+    args...,
+)
     return Val(:parent)
 end
 
-function get_coordinates!(M::Manifold, Y, p, X, B::AbstractBasis)
+function get_coordinates!(M::AbstractManifold, Y, p, X, B::AbstractBasis)
     return error(
         "get_coordinates! not implemented for manifold of type $(typeof(M)) coordinates of type $(typeof(Y)), a point of type $(typeof(p)), tangent vector of type $(typeof(X)) and basis of type $(typeof(B)).",
     )
@@ -355,7 +513,7 @@ end
     X,
     B::AbstractBasis,
 )
-for BT in DISAMBIGUATION_BASIS_TYPES
+for BT in [DISAMBIGUATION_BASIS_TYPES..., DISAMBIGUATION_COTANGENT_BASIS_TYPES...]
     eval(
         quote
             @decorator_transparent_signature get_coordinates!(
@@ -368,24 +526,28 @@ for BT in DISAMBIGUATION_BASIS_TYPES
         end,
     )
 end
-function decorator_transparent_dispatch(::typeof(get_coordinates!), ::Manifold, args...)
+function decorator_transparent_dispatch(
+    ::typeof(get_coordinates!),
+    ::AbstractManifold,
+    args...,
+)
     return Val(:transparent)
 end
 
-function get_coordinates!(M::Manifold, Y, p, X, B::VeeOrthogonalBasis)
+function get_coordinates!(M::AbstractManifold, Y, p, X, B::VeeOrthogonalBasis)
     return get_coordinates!(M, Y, p, X, DefaultOrthogonalBasis(number_system(B)))
 end
-function get_coordinates!(M::Manifold, Y, p, X, B::DefaultBasis)
+function get_coordinates!(M::AbstractManifold, Y, p, X, B::DefaultBasis)
     return get_coordinates!(M, Y, p, X, DefaultOrthogonalBasis(number_system(B)))
 end
-function get_coordinates!(M::Manifold, Y, p, X, B::DefaultOrthogonalBasis)
+function get_coordinates!(M::AbstractManifold, 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)
+function get_coordinates!(M::AbstractManifold, Y, p, X, B::CachedBasis)
     return _get_coordinates!(M, number_system(M), Y, p, X, B, number_system(B))
 end
 function _get_coordinates!(
-    M::Manifold,
+    M::AbstractManifold,
     ::ComplexNumbers,
     Y,
     p,
@@ -396,13 +558,21 @@ function _get_coordinates!(
     map!(vb -> conj(inner(M, p, X, vb)), Y, get_vectors(M, p, B))
     return Y
 end
-function _get_coordinates!(M::Manifold, a::𝔽, Y, p, X, C::CachedBasis, b::𝔽) where {𝔽}
+function _get_coordinates!(
+    M::AbstractManifold,
+    a::𝔽,
+    Y,
+    p,
+    X,
+    C::CachedBasis,
+    b::𝔽,
+) where {𝔽}
     map!(vb -> real(inner(M, p, X, vb)), Y, get_vectors(M, p, C))
     return Y
 end
 
 """
-    get_vector(M::Manifold, p, X, B::AbstractBasis)
+    get_vector(M::AbstractManifold, p, X, B::AbstractBasis)
 
 Convert a one-dimensional vector of coefficients in a basis `B` of
 the tangent space at `p` on manifold `M` to a tangent vector `X` at `p`.
@@ -416,7 +586,7 @@ requires either a dual basis or the cached basis to be selfdual, for example ort
 
 See also: [`get_coordinates`](@ref), [`get_basis`](@ref)
 """
-function get_vector(M::Manifold, p, X, B::AbstractBasis)
+function get_vector(M::AbstractManifold, p, X, B::AbstractBasis)
     Y = allocate_result(M, get_vector, p, X)
     return get_vector!(M, Y, p, X, B)
 end
@@ -426,11 +596,11 @@ end
     X,
     B::AbstractBasis,
 )
-function decorator_transparent_dispatch(::typeof(get_vector), ::Manifold, args...)
+function decorator_transparent_dispatch(::typeof(get_vector), ::AbstractManifold, args...)
     return Val(:parent)
 end
 
-function get_vector!(M::Manifold, Y, p, X, B::AbstractBasis)
+function get_vector!(M::AbstractManifold, Y, p, X, B::AbstractBasis)
     return error(
         "get_vector! not implemented for manifold of type $(typeof(M)) vector of type $(typeof(Y)), a point of type $(typeof(p)), coordinates of type $(typeof(X)) and basis of type $(typeof(B)).",
     )
@@ -442,7 +612,7 @@ end
     X,
     B::AbstractBasis,
 )
-for BT in DISAMBIGUATION_BASIS_TYPES
+for BT in [DISAMBIGUATION_BASIS_TYPES..., DISAMBIGUATION_COTANGENT_BASIS_TYPES...]
     eval(
         quote
             @decorator_transparent_signature get_vector!(
@@ -455,22 +625,22 @@ for BT in DISAMBIGUATION_BASIS_TYPES
         end,
     )
 end
-function decorator_transparent_dispatch(::typeof(get_vector!), ::Manifold, args...)
+function decorator_transparent_dispatch(::typeof(get_vector!), ::AbstractManifold, args...)
     return Val(:transparent)
 end
 
 _get_vector_cache_broadcast(::Any) = Val(true)
 
-function get_vector!(M::Manifold, Y, p, X, B::VeeOrthogonalBasis)
+function get_vector!(M::AbstractManifold, Y, p, X, B::VeeOrthogonalBasis)
     return get_vector!(M, Y, p, X, DefaultOrthogonalBasis(number_system(B)))
 end
-function get_vector!(M::Manifold, Y, p, X, B::DefaultBasis)
+function get_vector!(M::AbstractManifold, Y, p, X, B::DefaultBasis)
     return get_vector!(M, Y, p, X, DefaultOrthogonalBasis(number_system(B)))
 end
-function get_vector!(M::Manifold, Y, p, X, B::DefaultOrthogonalBasis)
+function get_vector!(M::AbstractManifold, Y, p, X, B::DefaultOrthogonalBasis)
     return get_vector!(M, Y, p, X, DefaultOrthonormalBasis(number_system(B)))
 end
-function get_vector!(M::Manifold, Y, p, X, B::CachedBasis)
+function get_vector!(M::AbstractManifold, Y, p, X, B::CachedBasis)
     # quite convoluted but:
     #  1) preserves the correct `eltype`
     #  2) guarantees a reasonable array type `Y`
@@ -494,16 +664,16 @@ function get_vector!(M::Manifold, Y, p, X, B::CachedBasis)
 end
 
 """
-    get_vectors(M::Manifold, p, B::AbstractBasis)
+    get_vectors(M::AbstractManifold, p, B::AbstractBasis)
 
 Get the basis vectors of basis `B` of the tangent space at point `p`.
 """
-function get_vectors(M::Manifold, p, B::AbstractBasis)
+function get_vectors(M::AbstractManifold, p, B::AbstractBasis)
     return error(
         "get_vectors not implemented for manifold of type $(typeof(M)) a point of type $(typeof(p)) and basis of type $(typeof(B)).",
     )
 end
-function get_vectors(::Manifold, ::Any, B::CachedBasis)
+function get_vectors(::AbstractManifold, ::Any, B::CachedBasis)
     return _get_vectors(B)
 end
 #internal for directly cached basis i.e. those that are just arrays – used in show
@@ -514,10 +684,10 @@ end
 
 
 @doc raw"""
-    gram_schmidt(M::Manifold{𝔽}, p, B::AbstractBasis{𝔽}) where {𝔽}
-    gram_schmidt(M::Manifold, p, V::AbstractVector)
+    gram_schmidt(M::AbstractManifold{𝔽}, p, B::AbstractBasis{𝔽}) where {𝔽}
+    gram_schmidt(M::AbstractManifold, p, V::AbstractVector)
 
-Compute an ONB in the tangent space at `p` on the [`Manifold`](@ref} `M` from either an
+Compute an ONB in the tangent space at `p` on the [`AbstractManifold`](@ref} `M` from either an
 [`AbstractBasis`](@ref) basis ´B´ or a set of (at most) [`manifold_dimension`](@ref)`(M)`
 many vectors.
 Note that this method requires the manifold and basis to work on the same
@@ -540,7 +710,7 @@ When a set of vectors is orthonormalized a set of vectors is returned.
 When an [`AbstractBasis`](@ref) is orthonormalized, a [`CachedBasis`](@ref) is returned.
 """
 function gram_schmidt(
-    M::Manifold{𝔽},
+    M::AbstractManifold{𝔽},
     p,
     B::AbstractBasis{𝔽};
     warn_linearly_dependent = false,
@@ -558,7 +728,7 @@ function gram_schmidt(
     return CachedBasis(GramSchmidtOrthonormalBasis(𝔽), V)
 end
 function gram_schmidt(
-    M::Manifold,
+    M::AbstractManifold,
     p,
     V::AbstractVector;
     warn_linearly_dependent = false,
@@ -601,7 +771,7 @@ function gram_schmidt(
 end
 
 @doc raw"""
-    hat(M::Manifold, p, Xⁱ)
+    hat(M::AbstractManifold, p, Xⁱ)
 
 Given a basis $e_i$ on the tangent space at a point `p` and tangent
 component vector $X^i$, compute the equivalent vector representation
@@ -615,20 +785,20 @@ For array manifolds, this converts a vector representation of the tangent
 vector to an array representation. The [`vee`](@ref) map is the `hat` map's
 inverse.
 """
-hat(M::Manifold, p, X) = get_vector(M, p, X, VeeOrthogonalBasis())
-hat!(M::Manifold, Y, p, X) = get_vector!(M, Y, p, X, VeeOrthogonalBasis())
+hat(M::AbstractManifold, p, X) = get_vector(M, p, X, VeeOrthogonalBasis())
+hat!(M::AbstractManifold, Y, p, X) = get_vector!(M, Y, p, X, VeeOrthogonalBasis())
 
 """
-    number_of_coordinates(M::Manifold, B::AbstractBasis)
+    number_of_coordinates(M::AbstractManifold, B::AbstractBasis)
 
 Compute the number of coordinates in basis `B` of manifold `M`.
 This also corresponds to the number of vectors represented by `B`,
 or stored within `B` in case of a [`CachedBasis`](@ref).
 """
-function number_of_coordinates(M::Manifold{𝔽}, B::AbstractBasis{𝔾}) where {𝔽,𝔾}
+function number_of_coordinates(M::AbstractManifold{𝔽}, B::AbstractBasis{𝔾}) where {𝔽,𝔾}
     return div(manifold_dimension(M), real_dimension(𝔽)) * real_dimension(𝔾)
 end
-function number_of_coordinates(M::Manifold{𝔽}, B::AbstractBasis{𝔽}) where {𝔽}
+function number_of_coordinates(M::AbstractManifold{𝔽}, B::AbstractBasis{𝔽}) where {𝔽}
     return manifold_dimension(M)
 end
 
@@ -723,7 +893,7 @@ function show(
 end
 
 @doc raw"""
-    vee(M::Manifold, p, X)
+    vee(M::AbstractManifold, p, X)
 
 Given a basis $e_i$ on the tangent space at a point `p` and tangent
 vector `X`, compute the vector components $X^i$, such that $X = X^i e_i$, where
@@ -737,8 +907,8 @@ For array manifolds, this converts an array representation of the tangent
 vector to a vector representation. The [`hat`](@ref) map is the `vee` map's
 inverse.
 """
-vee(M::Manifold, p, X) = get_coordinates(M, p, X, VeeOrthogonalBasis())
-vee!(M::Manifold, Y, p, X) = get_coordinates!(M, Y, p, X, VeeOrthogonalBasis())
+vee(M::AbstractManifold, p, X) = get_coordinates(M, p, X, VeeOrthogonalBasis())
+vee!(M::AbstractManifold, Y, p, X) = get_coordinates!(M, Y, p, X, VeeOrthogonalBasis())
 
 macro invoke_maker(argnum, type, sig)
     parts = ManifoldsBase._split_signature(sig)
diff --git a/src/numbers.jl b/src/numbers.jl
index 3e8c14d0..93eb2a65 100644
--- a/src/numbers.jl
+++ b/src/numbers.jl
@@ -77,8 +77,8 @@ real_dimension(::ComplexNumbers) = 2
 real_dimension(::QuaternionNumbers) = 4
 
 @doc raw"""
-    number_system(M::Manifold{𝔽})
+    number_system(M::AbstractManifold{𝔽})
 
 Return the number system the manifold `M` is based on, i.e. the parameter `𝔽`.
 """
-number_system(M::Manifold{𝔽}) where {𝔽} = 𝔽
+number_system(M::AbstractManifold{𝔽}) where {𝔽} = 𝔽
diff --git a/src/vector_spaces.jl b/src/vector_spaces.jl
new file mode 100644
index 00000000..98652312
--- /dev/null
+++ b/src/vector_spaces.jl
@@ -0,0 +1,93 @@
+
+"""
+    FVector(type::VectorSpaceType, data, basis::AbstractBasis)
+
+Decorator indicating that the vector `data` contains coordinates of a vector from a fiber
+of a vector bundle of type `type`. `basis` is an object describing the basis of that space
+in which the coordinates are given.
+"""
+struct FVector{TType<:VectorSpaceType,TData,TBasis<:AbstractBasis}
+    type::TType
+    data::TData
+    basis::TBasis
+end
+
+const TFVector = FVector{TangentSpaceType}
+const CoTFVector = FVector{CotangentSpaceType}
+
+function TFVector(data, basis::AbstractBasis)
+    return TFVector{typeof(data),typeof(basis)}(TangentSpace, data, basis)
+end
+function CoTFVector(data, basis::AbstractBasis)
+    return CoTFVector{typeof(data),typeof(basis)}(CotangentSpace, data, basis)
+end
+
+
+"""
+    AbstractFibreVector{TType<:VectorSpaceType}
+
+Type for a vector from a vector space (fibre of a vector bundle) of type `TType` of a manifold.
+While a [`AbstractManifold`](@ref) does not necessarily require this type, for example when it is
+implemented for `Vector`s or `Matrix` type elements, this type can be used for more
+complicated representations, semantic verification, or even dispatch for different
+representations of tangent vectors and their types on a manifold.
+"""
+abstract type AbstractFibreVector{TType<:VectorSpaceType} end
+
+"""
+    TVector = AbstractFibreVector{TangentSpaceType}
+
+Type for a tangent vector of a manifold. While a [`AbstractManifold`](@ref) does not necessarily
+require this type, for example when it is implemented for `Vector`s or `Matrix` type
+elements, this type can be used for more complicated representations, semantic verification,
+or even dispatch for different representations of tangent vectors and their types on a
+manifold.
+"""
+const TVector = AbstractFibreVector{TangentSpaceType}
+
+"""
+    CoTVector = AbstractFibreVector{CotangentSpaceType}
+
+Type for a cotangent vector of a manifold. While a [`AbstractManifold`](@ref) does not necessarily
+require this type, for example when it is implemented for `Vector`s or `Matrix` type
+elements, this type can be used for more complicated representations, semantic verification,
+or even dispatch for different representations of cotangent vectors and their types on a
+manifold.
+"""
+const CoTVector = AbstractFibreVector{CotangentSpaceType}
+
+Base.:+(X::FVector, Y::FVector) = FVector(X.type, X.data + Y.data, X.basis)
+
+Base.:-(X::FVector, Y::FVector) = FVector(X.type, X.data - Y.data, X.basis)
+Base.:-(X::FVector) = FVector(X.type, -X.data, X.basis)
+
+Base.:*(a::Number, X::FVector) = FVector(X.type, a * X.data, X.basis)
+
+allocate(x::FVector) = FVector(x.type, allocate(x.data), x.basis)
+allocate(x::FVector, ::Type{T}) where {T} = FVector(x.type, allocate(x.data, T), x.basis)
+
+function Base.copyto!(X::FVector, Y::FVector)
+    copyto!(X.data, Y.data)
+    return X
+end
+
+function number_eltype(
+    ::Type{FVector{TType,TData,TBasis}},
+) where {TType<:VectorSpaceType,TData,TBasis}
+    return number_eltype(TData)
+end
+number_eltype(v::FVector) = number_eltype(v.data)
+
+Base.show(io::IO, ::TangentSpaceType) = print(io, "TangentSpace")
+Base.show(io::IO, ::CotangentSpaceType) = print(io, "CotangentSpace")
+
+"""
+    vector_space_dimension(M::AbstractManifold, V::VectorSpaceType)
+
+Dimension of the vector space of type `V` on manifold `M`.
+"""
+vector_space_dimension(::AbstractManifold, ::VectorSpaceType)
+
+function vector_space_dimension(M::AbstractManifold, ::TCoTSpaceType)
+    return manifold_dimension(M)
+end
diff --git a/src/vector_transport.jl b/src/vector_transport.jl
index a6be8403..763cd302 100644
--- a/src/vector_transport.jl
+++ b/src/vector_transport.jl
@@ -73,7 +73,7 @@ Specify to use parallel transport as vector transport method within
 [`vector_transport_along`](@ref).
 
 Note that since it is technically the [`DifferentiatedRetractionVectorTransport`](@ref) of
-the [`exp`](@ref exp(M::Manifold, p, X)) (cf. [`ExponentialRetraction`](@ref)), we define
+the [`exp`](@ref exp(M::AbstractManifold, p, X)) (cf. [`ExponentialRetraction`](@ref)), we define
 `ParallelTransport` as an alias.
 """
 const ParallelTransport = DifferentiatedRetractionVectorTransport{ExponentialRetraction}
@@ -402,35 +402,41 @@ function show(io::IO, m::ScaledVectorTransport)
 end
 
 """
-    vector_transport_along(M::Manifold, p, X, c)
-    vector_transport_along(M::Manifold, p, X, c, method::AbstractVectorTransportMethod)
+    vector_transport_along(M::AbstractManifold, p, X, c)
+    vector_transport_along(M::AbstractManifold, p, X, c, method::AbstractVectorTransportMethod)
 
-Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
+Transport a vector `X` from the tangent space at a point `p` on the [`AbstractManifold`](@ref) `M`
 along the curve represented by `c` using the `method`, which defaults to
 [`ParallelTransport`](@ref).
 """
-function vector_transport_along(M::Manifold, p, X, c)
+function vector_transport_along(M::AbstractManifold, p, X, c)
     return vector_transport_along(M, p, X, c, ParallelTransport())
 end
-function vector_transport_along(M::Manifold, p, X, c, m::AbstractVectorTransportMethod)
+function vector_transport_along(
+    M::AbstractManifold,
+    p,
+    X,
+    c,
+    m::AbstractVectorTransportMethod,
+)
     Y = allocate_result(M, vector_transport_along, X, p)
     vector_transport_along!(M, Y, p, X, c, m)
     return Y
 end
 
 """
-    vector_transport_along!(M::Manifold, Y, p, X, c)
-    vector_transport_along!(M::Manifold, Y, p, X, c, method::AbstractVectorTransportMethod)
+    vector_transport_along!(M::AbstractManifold, Y, p, X, c)
+    vector_transport_along!(M::AbstractManifold, Y, p, X, c, method::AbstractVectorTransportMethod)
 
-Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
+Transport a vector `X` from the tangent space at a point `p` on the [`AbstractManifold`](@ref) `M`
 along the curve represented by `c` using the `method`, which defaults to
 [`ParallelTransport`](@ref). The result is saved to `Y`.
 """
-function vector_transport_along!(M::Manifold, Y, p, X, c)
+function vector_transport_along!(M::AbstractManifold, Y, p, X, c)
     return vector_transport_along!(M, Y, p, X, c, ParallelTransport())
 end
 function vector_transport_along!(
-    M::Manifold,
+    M::AbstractManifold,
     Y,
     p,
     X,
@@ -452,7 +458,7 @@ function vector_transport_along!(
 end
 @doc raw"""
     vector_transport_along!(
-        M::Manifold,
+        M::AbstractManifold,
         Y,
         p,
         X,
@@ -464,7 +470,7 @@ Compute the vector transport along a discretized curve `c` using an
 [`AbstractVectorTransportMethod`](@ref) `method` succesively along the sampled curve.
 """
 function vector_transport_along!(
-    M::Manifold,
+    M::AbstractManifold,
     Y,
     p,
     X,
@@ -488,7 +494,7 @@ function vector_transport_along!(
 end
 @doc raw"""
     function vector_transport_along!(
-        M::Manifold,
+        M::AbstractManifold,
         Y,
         p,
         X,
@@ -502,7 +508,7 @@ This method is avoiding additional allocations as well as inner exp/log by perfo
 ladder steps on the manifold and only computing one tangent vector in the end.
 """
 function vector_transport_along!(
-    M::Manifold,
+    M::AbstractManifold,
     Y,
     p,
     X,
@@ -551,7 +557,7 @@ function vector_transport_along!(
 end
 @doc raw"""
     vector_transport_along!(
-        M::Manifold,
+        M::AbstractManifold,
         Y,
         p,
         X,
@@ -565,7 +571,7 @@ This method is avoiding additional allocations as well as inner exp/log by perfo
 ladder steps on the manifold and only computing one tangent vector in the end.
 """
 function vector_transport_along!(
-    M::Manifold,
+    M::AbstractManifold,
     Y,
     p,
     X,
@@ -614,19 +620,19 @@ end
 
 
 """
-    vector_transport_direction(M::Manifold, p, X, d)
-    vector_transport_direction(M::Manifold, p, X, d, method::AbstractVectorTransportMethod)
+    vector_transport_direction(M::AbstractManifold, p, X, d)
+    vector_transport_direction(M::AbstractManifold, p, X, d, method::AbstractVectorTransportMethod)
 
-Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
+Transport a vector `X` from the tangent space at a point `p` on the [`AbstractManifold`](@ref) `M`
 in the direction indicated by the tangent vector `d` at `p`. By default, [`exp`](@ref) and
 [`vector_transport_to!`](@ref) are used with the `method`, which defaults
 to [`ParallelTransport`](@ref).
 """
-function vector_transport_direction(M::Manifold, p, X, d)
+function vector_transport_direction(M::AbstractManifold, p, X, d)
     return vector_transport_direction(M, p, X, d, ParallelTransport())
 end
 function vector_transport_direction(
-    M::Manifold,
+    M::AbstractManifold,
     p,
     X,
     d,
@@ -638,19 +644,19 @@ function vector_transport_direction(
 end
 
 """
-    vector_transport_direction!(M::Manifold, Y, p, X, d)
-    vector_transport_direction!(M::Manifold, Y, p, X, d, method::AbstractVectorTransportMethod)
+    vector_transport_direction!(M::AbstractManifold, Y, p, X, d)
+    vector_transport_direction!(M::AbstractManifold, Y, p, X, d, method::AbstractVectorTransportMethod)
 
-Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
+Transport a vector `X` from the tangent space at a point `p` on the [`AbstractManifold`](@ref) `M`
 in the direction indicated by the tangent vector `d` at `p`. By default, [`exp`](@ref) and
 [`vector_transport_to!`](@ref) are used with the `method`, which defaults
 to [`ParallelTransport`](@ref). The result is saved to `Y`.
 """
-function vector_transport_direction!(M::Manifold, Y, p, X, d)
+function vector_transport_direction!(M::AbstractManifold, Y, p, X, d)
     return vector_transport_direction!(M, Y, p, X, d, ParallelTransport())
 end
 function vector_transport_direction!(
-    M::Manifold,
+    M::AbstractManifold,
     Y,
     p,
     X,
@@ -662,53 +668,59 @@ function vector_transport_direction!(
 end
 
 """
-    vector_transport_to(M::Manifold, p, X, q)
-    vector_transport_to(M::Manifold, p, X, q, method::AbstractVectorTransportMethod)
+    vector_transport_to(M::AbstractManifold, p, X, q)
+    vector_transport_to(M::AbstractManifold, p, X, q, method::AbstractVectorTransportMethod)
 
-Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
+Transport a vector `X` from the tangent space at a point `p` on the [`AbstractManifold`](@ref) `M`
 along the [`shortest_geodesic`](@ref) to the tangent space at another point `q`.
 By default, the [`AbstractVectorTransportMethod`](@ref) `method` is
 [`ParallelTransport`](@ref).
 """
-function vector_transport_to(M::Manifold, p, X, q)
+function vector_transport_to(M::AbstractManifold, p, X, q)
     return vector_transport_to(M, p, X, q, ParallelTransport())
 end
-function vector_transport_to(M::Manifold, p, X, q, method::AbstractVectorTransportMethod)
+function vector_transport_to(
+    M::AbstractManifold,
+    p,
+    X,
+    q,
+    method::AbstractVectorTransportMethod,
+)
     Y = allocate_result(M, vector_transport_to, X, p, q)
     vector_transport_to!(M, Y, p, X, q, method)
     return Y
 end
 
 """
-    vector_transport_to!(M::Manifold, Y, p, X, q)
-    vector_transport_to!(M::Manifold, Y, p, X, q, method::AbstractVectorTransportMethod)
+    vector_transport_to!(M::AbstractManifold, Y, p, X, q)
+    vector_transport_to!(M::AbstractManifold, Y, p, X, q, method::AbstractVectorTransportMethod)
 
-Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
+Transport a vector `X` from the tangent space at a point `p` on the [`AbstractManifold`](@ref) `M`
 along the [`shortest_geodesic`](@ref) to the tangent space at another point `q`.
 By default, the [`AbstractVectorTransportMethod`](@ref) `method` is
 [`ParallelTransport`](@ref). The result is saved to `Y`.
 """
-function vector_transport_to!(M::Manifold, Y, p, X, q)
+function vector_transport_to!(M::AbstractManifold, Y, p, X, q)
     return vector_transport_to!(M, Y, p, X, q, ParallelTransport())
 end
 """
-    vector_transport_to!(M::Manifold, Y, p, X, q, method::ProjectionTransport)
+    vector_transport_to!(M::AbstractManifold, Y, p, X, q, method::ProjectionTransport)
 
-Transport a vector `X` from the tangent space at `p` on the [`Manifold`](@ref) `M` by
+Transport a vector `X` from the tangent space at `p` on the [`AbstractManifold`](@ref) `M` by
 interpreting it as an element of the embedding and then projecting it onto the tangent space
 at `q`. This function needs to be separately implemented for each manifold because
-projection [`project`](@ref project(M::Manifold, p, X)) may also change vector
+projection [`project`](@ref project(M::AbstractManifold, p, X)) may also change vector
 representation (if it's different than in the embedding) and it is assumed that the vector
 `X` already has the correct representation for `M`.
 """
-vector_transport_to!(M::Manifold, Y, p, X, q, m::ProjectionTransport)
+vector_transport_to!(M::AbstractManifold, Y, p, X, q, m::ProjectionTransport)
 
 @doc raw"""
-    vector_transport_to!(M::Manifold, Y, p, X, q, method::PoleLadderTransport)
+    vector_transport_to!(M::AbstractManifold, Y, p, X, q, method::PoleLadderTransport)
 
 Perform a vector transport by using [`PoleLadderTransport`](@ref).
 """
-function vector_transport_to!(M::Manifold, Y, p, X, q, m::PoleLadderTransport)
+function vector_transport_to!(M::AbstractManifold, Y, p, X, q, m::PoleLadderTransport)
     inverse_retract!(
         M,
         Y,
@@ -728,7 +740,7 @@ function vector_transport_to!(M::Manifold, Y, p, X, q, m::PoleLadderTransport)
 end
 
 function vector_transport_to!(
-    M::Manifold,
+    M::AbstractManifold,
     Y,
     p,
     X,
@@ -741,11 +753,11 @@ function vector_transport_to!(
 end
 
 @doc raw"""
-    vector_transport_to!(M::Manifold, Y, p, X, q, method::SchildsLadderTransport)
+    vector_transport_to!(M::AbstractManifold, Y, p, X, q, method::SchildsLadderTransport)
 
 Perform a vector transport by using [`SchildsLadderTransport`](@ref).
 """
-function vector_transport_to!(M::Manifold, Y, p, X, q, m::SchildsLadderTransport)
+function vector_transport_to!(M::AbstractManifold, Y, p, X, q, m::SchildsLadderTransport)
     return inverse_retract!(
         M,
         Y,
@@ -764,7 +776,7 @@ end
 
 
 function vector_transport_to!(
-    M::Manifold,
+    M::AbstractManifold,
     Y,
     p,
     X,


Test patch:
diff --git a/test/allocation.jl b/test/allocation.jl
index 02f8ba8f..b1becefc 100644
--- a/test/allocation.jl
+++ b/test/allocation.jl
@@ -3,7 +3,7 @@ using Test
 using ManifoldsBase:
     combine_allocation_promotion_functions, allocation_promotion_function, ℝ
 
-struct AllocManifold{𝔽} <: Manifold{𝔽} end
+struct AllocManifold{𝔽} <: AbstractManifold{𝔽} end
 AllocManifold() = AllocManifold{ℝ}()
 
 function ManifoldsBase.exp!(::AllocManifold, v, x, y)
diff --git a/test/bases.jl b/test/bases.jl
index f0204a7d..c444cf80 100644
--- a/test/bases.jl
+++ b/test/bases.jl
@@ -1,11 +1,14 @@
 using LinearAlgebra
 using ManifoldsBase
 using ManifoldsBase: DefaultManifold, ℝ, ℂ
+using ManifoldsBase: CotangentSpace, CotangentSpaceType, TangentSpace, TangentSpaceType
+using ManifoldsBase: FVector, CoTFVector, TFVector
 using Test
 import Base: +, -, *, copyto!, isapprox
 import ManifoldsBase: allocate
 
-struct ProjManifold <: Manifold{ℝ} end
+
+struct ProjManifold <: AbstractManifold{ℝ} end
 
 ManifoldsBase.inner(::ProjManifold, x, w, v) = dot(w, v)
 ManifoldsBase.project!(::ProjManifold, w, x, v) = (w .= v .- dot(x, v) .* x)
@@ -44,7 +47,7 @@ ManifoldsBase.get_vector(::ProjManifold, x, v, ::DefaultOrthonormalBasis) = reve
     ) === Val(:transparent)
 end
 
-struct ProjectionTestManifold <: Manifold{ℝ} end
+struct ProjectionTestManifold <: AbstractManifold{ℝ} end
 
 ManifoldsBase.inner(::ProjectionTestManifold, ::Any, X, Y) = dot(X, Y)
 function ManifoldsBase.project!(::ProjectionTestManifold, Y, p, X)
@@ -110,8 +113,8 @@ ManifoldsBase.manifold_dimension(::ProjectionTestManifold) = 100
     end
 end
 
-struct NonManifold <: Manifold{ℝ} end
-struct NonBasis <: ManifoldsBase.AbstractBasis{ℝ} end
+struct NonManifold <: AbstractManifold{ℝ} end
+struct NonBasis <: ManifoldsBase.AbstractBasis{ℝ,TangentSpaceType} end
 
 struct NonBroadcastBasisThing{T}
     v::T
@@ -157,9 +160,9 @@ function ManifoldsBase.exp!(
 end
 
 function ManifoldsBase.get_basis(
-    M::DefaultManifold,
+    ::DefaultManifold,
     p::NonBroadcastBasisThing,
-    B::DefaultOrthonormalBasis,
+    B::DefaultOrthonormalBasis{ℝ,TangentSpaceType},
 )
     return CachedBasis(
         B,
@@ -170,9 +173,9 @@ function ManifoldsBase.get_basis(
     )
 end
 function ManifoldsBase.get_basis(
-    M::DefaultManifold,
+    ::DefaultManifold,
     p::NonBroadcastBasisThing,
-    B::DefaultOrthogonalBasis,
+    B::DefaultOrthogonalBasis{ℝ,TangentSpaceType},
 )
     return CachedBasis(
         B,
@@ -183,9 +186,9 @@ function ManifoldsBase.get_basis(
     )
 end
 function ManifoldsBase.get_basis(
-    M::DefaultManifold,
+    ::DefaultManifold,
     p::NonBroadcastBasisThing,
-    B::DefaultBasis,
+    B::DefaultBasis{ℝ,TangentSpaceType},
 )
     return CachedBasis(
         B,
@@ -199,9 +202,9 @@ end
 function ManifoldsBase.get_coordinates!(
     M::DefaultManifold,
     Y,
-    p::NonBroadcastBasisThing,
+    ::NonBroadcastBasisThing,
     X::NonBroadcastBasisThing,
-    B::DefaultOrthonormalBasis,
+    ::DefaultOrthonormalBasis{ℝ,TangentSpaceType},
 )
     copyto!(Y, reshape(X.v, manifold_dimension(M)))
     return Y
@@ -210,9 +213,9 @@ end
 function ManifoldsBase.get_vector!(
     M::DefaultManifold,
     Y::NonBroadcastBasisThing,
-    p::NonBroadcastBasisThing,
+    ::NonBroadcastBasisThing,
     X,
-    B::DefaultOrthonormalBasis,
+    ::DefaultOrthonormalBasis{ℝ,TangentSpaceType},
 )
     copyto!(Y.v, reshape(X, representation_size(M)))
     return Y
@@ -220,11 +223,11 @@ end
 
 function ManifoldsBase.inner(
     ::DefaultManifold,
-    x::NonBroadcastBasisThing,
-    v::NonBroadcastBasisThing,
-    w::NonBroadcastBasisThing,
+    ::NonBroadcastBasisThing,
+    X::NonBroadcastBasisThing,
+    Y::NonBroadcastBasisThing,
 )
-    return dot(v.v, w.v)
+    return dot(X.v, Y.v)
 end
 
 ManifoldsBase._get_vector_cache_broadcast(::NonBroadcastBasisThing) = Val(false)
@@ -238,7 +241,7 @@ DiagonalizingBasisProxy() = DiagonalizingOrthonormalBasis([1.0, 0.0, 0.0])
         onb = DefaultOrthonormalBasis()
 
         @test_throws ErrorException get_basis(m, [0], onb)
-        @test_throws ErrorException get_basis(m, [0], NonBasis())
+        @test_throws MethodError get_basis(m, [0], NonBasis())
         @test_throws ErrorException get_coordinates(m, [0], [0], onb)
         @test_throws ErrorException get_coordinates!(m, [0], [0], [0], onb)
         @test_throws ErrorException get_vector(m, [0], [0], onb)
@@ -248,6 +251,18 @@ DiagonalizingBasisProxy() = DiagonalizingOrthonormalBasis([1.0, 0.0, 0.0])
 
     M = DefaultManifold(3)
 
+    @testset "Constructors" begin
+        @test DefaultBasis{ℂ,TangentSpaceType}() === DefaultBasis(ℂ)
+        @test DefaultOrthogonalBasis{ℂ,TangentSpaceType}() === DefaultOrthogonalBasis(ℂ)
+        @test DefaultOrthonormalBasis{ℂ,TangentSpaceType}() === DefaultOrthonormalBasis(ℂ)
+
+        @test DefaultBasis{ℂ}(CotangentSpace) === DefaultBasis(ℂ, CotangentSpace)
+        @test DefaultOrthogonalBasis{ℂ}(CotangentSpace) ===
+              DefaultOrthogonalBasis(ℂ, CotangentSpace)
+        @test DefaultOrthonormalBasis{ℂ}(CotangentSpace) ===
+              DefaultOrthonormalBasis(ℂ, CotangentSpace)
+    end
+
     _pts = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
     @testset "basis representation" for BT in (
             DefaultBasis,
@@ -273,11 +288,15 @@ 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{ℝ,TangentSpaceType},Vector{Vector{Float64}}})
             else
                 @test isa(
                     b,
-                    CachedBasis{ℝ,BT{ℝ},Vector{NonBroadcastBasisThing{Vector{Float64}}}},
+                    CachedBasis{
+                        ℝ,
+                        BT{ℝ,TangentSpaceType},
+                        Vector{NonBroadcastBasisThing{Vector{Float64}}},
+                    },
                 )
             end
         end
@@ -348,12 +367,13 @@ end
     @test sprint(show, ProjectedOrthonormalBasis(:gram_schmidt, ℂ)) ==
           "ProjectedOrthonormalBasis(:gram_schmidt, ℂ)"
 
-    @test sprint(show, "text/plain", DiagonalizingOrthonormalBasis(Float64[1, 2, 3])) == """
-                                                                               DiagonalizingOrthonormalBasis(ℝ) with eigenvalue 0 in direction:
-                                                                               3-element $(sprint(show, Vector{Float64})):
-                                                                                 1.0
-                                                                                 2.0
-                                                                                 3.0"""
+    diag_onb = DiagonalizingOrthonormalBasis(Float64[1, 2, 3])
+    @test sprint(show, "text/plain", diag_onb) == """
+    DiagonalizingOrthonormalBasis(ℝ) with eigenvalue 0 in direction:
+    3-element $(sprint(show, Vector{Float64})):
+      1.0
+      2.0
+      3.0"""
 
     M = DefaultManifold(2, 3)
     x = collect(reshape(1.0:6.0, (2, 3)))
@@ -444,3 +464,63 @@ end
      1-element $(sprint(show, Vector{Float64})):
       1.0"""
 end
+
+@testset "Bases of cotangent spaces" begin
+    b1 = DefaultOrthonormalBasis(ℝ, CotangentSpace)
+    @test b1.vector_space == CotangentSpace
+
+    b2 = DefaultOrthogonalBasis(ℝ, CotangentSpace)
+    @test b2.vector_space == CotangentSpace
+
+    b3 = DefaultBasis(ℝ, CotangentSpace)
+    @test b3.vector_space == CotangentSpace
+
+    M = DefaultManifold(2; field = ℂ)
+    p = [1.0, 2.0im]
+    b1_d = ManifoldsBase.dual_basis(M, p, b1)
+    @test b1_d isa DefaultOrthonormalBasis
+    @test b1_d.vector_space == TangentSpace
+
+    b1_d_d = ManifoldsBase.dual_basis(M, p, b1_d)
+    @test b1_d_d isa DefaultOrthonormalBasis
+    @test b1_d_d.vector_space == CotangentSpace
+end
+
+@testset "FVector" begin
+    @test sprint(show, TangentSpace) == "TangentSpace"
+    @test sprint(show, CotangentSpace) == "CotangentSpace"
+    tvs = ([1.0, 0.0, 0.0], [0.0, 1.0, 0.0])
+    fv_tvs = map(v -> TFVector(v, DefaultOrthonormalBasis()), tvs)
+    fv1 = fv_tvs[1]
+    tv1s = allocate(fv_tvs[1])
+    @test isa(tv1s, FVector)
+    @test tv1s.type == TangentSpace
+    @test size(tv1s.data) == size(tvs[1])
+    @test number_eltype(tv1s) == number_eltype(tvs[1])
+    @test number_eltype(tv1s) == number_eltype(typeof(tv1s))
+    @test isa(fv1 + fv1, FVector)
+    @test (fv1 + fv1).type == TangentSpace
+    @test isa(fv1 - fv1, FVector)
+    @test (fv1 - fv1).type == TangentSpace
+    @test isa(-fv1, FVector)
+    @test (-fv1).type == TangentSpace
+    @test isa(2 * fv1, FVector)
+    @test (2 * fv1).type == TangentSpace
+    tv1s_32 = allocate(fv_tvs[1], Float32)
+    @test isa(tv1s, FVector)
+    @test eltype(tv1s_32.data) === Float32
+    copyto!(tv1s, fv_tvs[2])
+    @test isapprox(tv1s.data, fv_tvs[2].data)
+
+    cofv1 = CoTFVector(tvs[1], DefaultOrthonormalBasis(ℝ, CotangentSpace))
+    @test cofv1 isa CoTFVector
+end
+
+@testset "vector_space_dimension" begin
+    M = ManifoldsBase.DefaultManifold(3)
+    MC = ManifoldsBase.DefaultManifold(3; field = ℂ)
+    @test ManifoldsBase.vector_space_dimension(M, TangentSpace) == 3
+    @test ManifoldsBase.vector_space_dimension(M, CotangentSpace) == 3
+    @test ManifoldsBase.vector_space_dimension(MC, TangentSpace) == 6
+    @test ManifoldsBase.vector_space_dimension(MC, CotangentSpace) == 6
+end
diff --git a/test/complex_manifold.jl b/test/complex_manifold.jl
index df849472..18d4bf30 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} <: AbstractManifold{ℂ} 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 6d91f34c..e98cffd7 100644
--- a/test/decorator_manifold.jl
+++ b/test/decorator_manifold.jl
@@ -7,35 +7,35 @@ using ManifoldsBase:
     is_decorator_transparent
 import ManifoldsBase: decorator_transparent_dispatch
 
-struct TestDecorator{M<:Manifold{ℝ}} <: AbstractDecoratorManifold{ℝ}
+struct TestDecorator{M<:AbstractManifold{ℝ}} <: AbstractDecoratorManifold{ℝ}
     manifold::M
 end
 
 abstract type AbstractTestDecorator <: AbstractDecoratorManifold{ℝ} end
 
-struct TestDecorator2{M<:Manifold{ℝ}} <: AbstractTestDecorator
+struct TestDecorator2{M<:AbstractManifold{ℝ}} <: AbstractTestDecorator
     manifold::M
 end
 
-struct TestDecorator3{M<:Manifold{ℝ}} <: AbstractTestDecorator
+struct TestDecorator3{M<:AbstractManifold{ℝ}} <: AbstractTestDecorator
     manifold::M
 end
 
 abstract type AbstractParentDecorator <: AbstractDecoratorManifold{ℝ} end
 
-struct ChildDecorator{M<:Manifold{ℝ}} <: AbstractParentDecorator
+struct ChildDecorator{M<:AbstractManifold{ℝ}} <: AbstractParentDecorator
     manifold::M
 end
 
-struct DefaultDecorator{M<:Manifold{ℝ}} <: AbstractDecoratorManifold{ℝ}
+struct DefaultDecorator{M<:AbstractManifold{ℝ}} <: AbstractDecoratorManifold{ℝ}
     manifold::M
 end
 ManifoldsBase.default_decorator_dispatch(::DefaultDecorator) = Val(true)
 
-test1(M::Manifold, p; a = 0) = 101 + a
-test2(M::Manifold, p; a = 0) = 102 + a
-test3(M::Manifold, p; a = 0) = 103 + a
-function test4(M::Manifold, p; a = 0)
+test1(M::AbstractManifold, p; a = 0) = 101 + a
+test2(M::AbstractManifold, p; a = 0) = 102 + a
+test3(M::AbstractManifold, p; a = 0) = 103 + a
+function test4(M::AbstractManifold, p; a = 0)
     return error(ManifoldsBase.manifold_function_not_implemented_message(M, test4, p))
 end
 
@@ -70,7 +70,7 @@ end
     return 17
 end
 
-test8(M::Manifold, p; a = 0) = 8 + a
+test8(M::AbstractManifold, p; a = 0) = 8 + a
 
 @decorator_transparent_function :parent function test9(
     M::AbstractDecoratorManifold,
diff --git a/test/default_manifold.jl b/test/default_manifold.jl
index 4edd7f47..7c1b7af5 100644
--- a/test/default_manifold.jl
+++ b/test/default_manifold.jl
@@ -69,46 +69,41 @@ Base.size(x::MatrixVectorTransport) = (size(x.m, 2),)
             tv1 = log(M, pts[1], pts[2])
 
             for pt in pts
-                @test is_manifold_point(M, pt)
+                @test is_point(M, pt)
             end
-            @test is_tangent_vector(M, pts[1], tv1; atol = eps(eltype(pts[1])))
+            @test is_vector(M, pts[1], tv1; atol = eps(eltype(pts[1])))
 
             tv2 = log(M, pts[2], pts[1])
             @test isapprox(M, pts[2], exp(M, pts[1], tv1))
             @test isapprox(M, pts[1], exp(M, pts[1], tv1, 0))
             @test isapprox(M, pts[2], exp(M, pts[1], tv1, 1))
             @test isapprox(M, pts[1], exp(M, pts[2], tv2))
-            @test is_manifold_point(M, retract(M, pts[1], tv1))
+            @test is_point(M, retract(M, pts[1], tv1))
             @test isapprox(M, pts[1], retract(M, pts[1], tv1, 0))
 
-            @test is_manifold_point(M, retract(M, pts[1], tv1, rm))
+            @test is_point(M, retract(M, pts[1], tv1, rm))
             @test isapprox(M, pts[1], retract(M, pts[1], tv1, 0, rm))
 
             new_pt = exp(M, pts[1], tv1)
             retract!(M, new_pt, pts[1], tv1)
-            @test is_manifold_point(M, new_pt)
+            @test is_point(M, new_pt)
             for x in pts
+                @test isapprox(M, zero_vector(M, x), log(M, x, x); atol = eps(eltype(x)))
                 @test isapprox(
                     M,
-                    zero_tangent_vector(M, x),
-                    log(M, x, x);
-                    atol = eps(eltype(x)),
-                )
-                @test isapprox(
-                    M,
-                    zero_tangent_vector(M, x),
+                    zero_vector(M, x),
                     inverse_retract(M, x, x);
                     atol = eps(eltype(x)),
                 )
                 @test isapprox(
                     M,
-                    zero_tangent_vector(M, x),
+                    zero_vector(M, x),
                     inverse_retract(M, x, x, irm);
                     atol = eps(eltype(x)),
                 )
             end
-            zero_tangent_vector!(M, tv1, pts[1])
-            @test isapprox(M, pts[1], tv1, zero_tangent_vector(M, pts[1]))
+            zero_vector!(M, tv1, pts[1])
+            @test isapprox(M, pts[1], tv1, zero_vector(M, pts[1]))
             log!(M, tv1, pts[1], pts[2])
             @test norm(M, pts[1], tv1) ≈ sqrt(inner(M, pts[1], tv1, tv1))
 
@@ -152,7 +147,7 @@ Base.size(x::MatrixVectorTransport) = (size(x.m, 2),)
                     M,
                     pts[1],
                     0 * tv1,
-                    zero_tangent_vector(M, pts[1]);
+                    zero_vector(M, pts[1]);
                     atol = eps(eltype(pts[1])),
                 )
                 @test isapprox(M, pts[1], 2 * tv1, tv1 + tv1)
@@ -217,8 +212,8 @@ Base.size(x::MatrixVectorTransport) = (size(x.m, 2),)
                 v1t2 = zero(v1t1)
                 vector_transport_to!(M, v1t2, pts[1], v1, v2, ProjectionTransport())
                 v1t3 = vector_transport_direction(M, pts[1], v1, v2)
-                @test is_tangent_vector(M, pts[3], v1t1)
-                @test is_tangent_vector(M, pts[3], v1t3)
+                @test is_vector(M, pts[3], v1t1)
+                @test is_vector(M, pts[3], v1t3)
                 @test isapprox(M, pts[3], v1t1, v1t3)
                 # along a `Vector` of points
                 c = [pts[1]]
diff --git a/test/domain_errors.jl b/test/domain_errors.jl
index df835715..ae6602b7 100644
--- a/test/domain_errors.jl
+++ b/test/domain_errors.jl
@@ -1,16 +1,16 @@
 using ManifoldsBase
 using Test
 
-struct ErrorTestManifold <: Manifold{ℝ} end
+struct ErrorTestManifold <: AbstractManifold{ℝ} end
 
-function ManifoldsBase.check_manifold_point(::ErrorTestManifold, x)
+function ManifoldsBase.check_point(::ErrorTestManifold, x)
     if any(u -> u < 0, x)
         return DomainError(x, "<0")
     end
     return nothing
 end
-function ManifoldsBase.check_tangent_vector(M::ErrorTestManifold, x, v)
-    mpe = check_manifold_point(M, x)
+function ManifoldsBase.check_vector(M::ErrorTestManifold, x, v)
+    mpe = check_point(M, x)
     mpe === nothing || return mpe
     if any(u -> u < 0, v)
         return DomainError(v, "<0")
@@ -20,15 +20,15 @@ end
 
 @testset "Domain errors" begin
     M = ErrorTestManifold()
-    @test isa(check_manifold_point(M, [-1, 1]), DomainError)
-    @test check_manifold_point(M, [1, 1]) === nothing
-    @test !is_manifold_point(M, [-1, 1])
-    @test is_manifold_point(M, [1, 1])
-    @test_throws DomainError is_manifold_point(M, [-1, 1], true)
+    @test isa(check_point(M, [-1, 1]), DomainError)
+    @test check_point(M, [1, 1]) === nothing
+    @test !is_point(M, [-1, 1])
+    @test is_point(M, [1, 1])
+    @test_throws DomainError is_point(M, [-1, 1], true)
 
-    @test isa(check_tangent_vector(M, [1, 1], [-1, 1]), DomainError)
-    @test check_tangent_vector(M, [1, 1], [1, 1]) === nothing
-    @test !is_tangent_vector(M, [1, 1], [-1, 1])
-    @test is_tangent_vector(M, [1, 1], [1, 1])
-    @test_throws DomainError is_tangent_vector(M, [1, 1], [-1, 1], true)
+    @test isa(check_vector(M, [1, 1], [-1, 1]), DomainError)
+    @test check_vector(M, [1, 1], [1, 1]) === nothing
+    @test !is_vector(M, [1, 1], [-1, 1])
+    @test is_vector(M, [1, 1], [1, 1])
+    @test_throws DomainError is_vector(M, [1, 1], [-1, 1], true)
 end
diff --git a/test/embedded_manifold.jl b/test/embedded_manifold.jl
index 19d338de..4121a5d7 100644
--- a/test/embedded_manifold.jl
+++ b/test/embedded_manifold.jl
@@ -114,12 +114,12 @@ struct NotImplementedEmbeddedManifold3 <: AbstractEmbeddedManifold{ℝ,DefaultEm
         @test ManifoldsBase.default_embedding_dispatch(M) === Val(false)
         @test get_embedding(M) == ManifoldsBase.DefaultManifold(1, 3)
         # Check fallbacks to check embed->check_manifoldpoint Defaults
-        @test_throws DomainError is_manifold_point(M, [1, 0, 0], true)
-        @test_throws DomainError is_manifold_point(M, [1 0], true)
-        @test is_manifold_point(M, [1 0 0], true)
-        @test_throws DomainError is_tangent_vector(M, [1 0 0], [1], true)
-        @test_throws DomainError is_tangent_vector(M, [1 0 0], [0 0 0 0], true)
-        @test is_tangent_vector(M, [1 0 0], [1 0 1], true)
+        @test_throws DomainError is_point(M, [1, 0, 0], true)
+        @test_throws DomainError is_point(M, [1 0], true)
+        @test is_point(M, [1 0 0], true)
+        @test_throws DomainError is_vector(M, [1 0 0], [1], true)
+        @test_throws DomainError is_vector(M, [1 0 0], [0 0 0 0], true)
+        @test is_vector(M, [1 0 0], [1 0 1], true)
         p = [1.0 1.0 0.0]
         q = [1.0 0.0 0.0]
         X = q - p
@@ -172,8 +172,8 @@ struct NotImplementedEmbeddedManifold3 <: AbstractEmbeddedManifold{ℝ,DefaultEm
             M = NotImplementedEmbeddedManifold()
             A = zeros(2)
             # without any extra tests just the embedding is asked
-            @test check_manifold_point(M, [1, 2]) === nothing
-            @test check_tangent_vector(M, [1, 2], [3, 4]) === nothing
+            @test check_point(M, [1, 2]) === nothing
+            @test check_vector(M, [1, 2], [3, 4]) === nothing
             @test norm(M, [1, 2], [2, 3]) ≈ sqrt(13)
             @test distance(M, [1, 2], [3, 4]) ≈ sqrt(8)
             @test inner(M, [1, 2], [2, 3], [2, 3]) ≈ 13
@@ -267,7 +267,7 @@ struct NotImplementedEmbeddedManifold3 <: AbstractEmbeddedManifold{ℝ,DefaultEm
         for f in [mid_point, mid_point!]
             @test ManifoldsBase.decorator_transparent_dispatch(f, AM) === Val(:parent)
         end
-        for f in [check_manifold_point, check_tangent_vector, exp!, inner, embed!]
+        for f in [check_point, check_vector, exp!, inner, embed!]
             @test ManifoldsBase.decorator_transparent_dispatch(f, AM) ===
                   Val(:intransparent)
         end
diff --git a/test/empty_manifold.jl b/test/empty_manifold.jl
index 2cc8bd19..02855a06 100644
--- a/test/empty_manifold.jl
+++ b/test/empty_manifold.jl
@@ -2,14 +2,14 @@ using ManifoldsBase
 
 using Test
 import Base: *
-struct NonManifold <: Manifold{ManifoldsBase.ℝ} end
-struct NonMPoint <: MPoint end
+struct NonManifold <: AbstractManifold{ManifoldsBase.ℝ} end
+struct NonMPoint <: AbstractManifoldPoint end
 struct NonTVector <: TVector end
 struct NonCoTVector <: CoTVector end
 struct NotImplementedRetraction <: AbstractRetractionMethod end
 struct NotImplementedInverseRetraction <: AbstractInverseRetractionMethod end
 *(t::Float64, X::NonTVector) = X
-@testset "Manifold with empty implementation" begin
+@testset "AbstractManifold with empty implementation" begin
     M = NonManifold()
     p = NonMPoint()
     v = NonTVector()
@@ -133,18 +133,18 @@ struct NotImplementedInverseRetraction <: AbstractInverseRetractionMethod end
     @test_throws ErrorException injectivity_radius(M, [0])
     @test_throws ErrorException injectivity_radius(M, [0], exp_retr)
 
-    @test_throws ErrorException zero_tangent_vector!(M, [0], [0])
-    @test_throws ErrorException zero_tangent_vector(M, [0])
+    @test_throws ErrorException zero_vector!(M, [0], [0])
+    @test_throws ErrorException zero_vector(M, [0])
 
-    @test check_manifold_point(M, [0]) === nothing
-    @test check_manifold_point(M, p) === nothing
-    @test is_manifold_point(M, [0])
-    @test check_manifold_point(M, [0]) === nothing
+    @test check_point(M, [0]) === nothing
+    @test check_point(M, p) === nothing
+    @test is_point(M, [0])
+    @test check_point(M, [0]) === nothing
 
-    @test check_tangent_vector(M, [0], [0]) === nothing
-    @test check_tangent_vector(M, p, v) === nothing
-    @test is_tangent_vector(M, [0], [0])
-    @test check_tangent_vector(M, [0], [0]) === nothing
+    @test check_vector(M, [0], [0]) === nothing
+    @test check_vector(M, p, v) === nothing
+    @test is_vector(M, [0], [0])
+    @test check_vector(M, [0], [0]) === nothing
 
     @test_throws ErrorException hat!(M, [0], [0], [0])
     @test_throws ErrorException vee!(M, [0], [0], [0])
diff --git a/test/power.jl b/test/power.jl
index beb64173..3d72c96c 100644
--- a/test/power.jl
+++ b/test/power.jl
@@ -4,7 +4,7 @@ using ManifoldsBase: AbstractNumbers, ℝ, ℂ
 
 struct DummyPowerRepresentation <: AbstractPowerRepresentation end
 
-@testset "Power Manifold" begin
+@testset "Power AbstractManifold" begin
     M = ManifoldsBase.DefaultManifold(3)
     N = PowerManifold(M, NestedPowerRepresentation(), 2)
     p = [zeros(3), ones(3)]
@@ -31,23 +31,23 @@ struct DummyPowerRepresentation <: AbstractPowerRepresentation end
     @testset "point/tangent checks" begin
         pE1 = [zeros(3), ones(2)] # one component wrong
         pE2 = [zeros(2), ones(2)] # both wrong
-        @test is_manifold_point(N, p)
-        @test is_manifold_point(N, p, true)
-        @test !is_manifold_point(N, pE1)
-        @test !is_manifold_point(N, pE2)
-        @test_throws ComponentManifoldError is_manifold_point(N, pE1, true)
-        @test_throws CompositeManifoldError is_manifold_point(N, pE2, true)
+        @test is_point(N, p)
+        @test is_point(N, p, true)
+        @test !is_point(N, pE1)
+        @test !is_point(N, pE2)
+        @test_throws ComponentManifoldError is_point(N, pE1, true)
+        @test_throws CompositeManifoldError is_point(N, pE2, true)
         # tangent - test base
-        @test is_tangent_vector(N, p, p)
-        @test is_tangent_vector(N, p, p, true)
-        @test !is_tangent_vector(N, pE1, p)
-        @test !is_tangent_vector(N, pE2, p)
+        @test is_vector(N, p, p)
+        @test is_vector(N, p, p, true)
+        @test !is_vector(N, pE1, p)
+        @test !is_vector(N, pE2, p)
         # tangents - with proper base
-        @test is_tangent_vector(N, p, p, true)
-        @test !is_tangent_vector(N, p, pE1)
-        @test !is_tangent_vector(N, p, pE2)
-        @test_throws ComponentManifoldError is_tangent_vector(N, p, pE1, true)
-        @test_throws CompositeManifoldError is_tangent_vector(N, p, pE2, true)
+        @test is_vector(N, p, p, true)
+        @test !is_vector(N, p, pE1)
+        @test !is_vector(N, p, pE2)
+        @test_throws ComponentManifoldError is_vector(N, p, pE1, true)
+        @test_throws CompositeManifoldError is_vector(N, p, pE2, true)
     end
     @testset "specific functions" begin
         @test distance(N, p, q) == sqrt(sum(distance.(Ref(M), p, q) .^ 2))
@@ -111,7 +111,7 @@ struct DummyPowerRepresentation <: AbstractPowerRepresentation end
         @test B.data.bases[1].data == get_basis(M, p[1], DefaultBasis()).data
         @test B.data.bases[2].data == get_basis(M, p[2], DefaultBasis()).data
         @test get_vector(N, p, v, B) == q
-        @test zero_tangent_vector(N, p) == [zeros(3), zeros(3)]
+        @test zero_vector(N, p) == [zeros(3), zeros(3)]
         B2 = DiagonalizingOrthonormalBasis([ones(3), ones(3)])
         B3 = get_basis(N, p, B2)
         @test sprint(show, "text/plain", B) == """$(DefaultBasis()) for a power manifold
@@ -127,6 +127,6 @@ struct DummyPowerRepresentation <: AbstractPowerRepresentation end
         p = [1.0, 2.0, 3.0]
 
         @test p[N, 1] == 1.0
-        @test zero_tangent_vector(N, p) == zero(p)
+        @test zero_vector(N, p) == zero(p)
     end
 end
diff --git a/test/runtests.jl b/test/runtests.jl
index d48cc2c6..d71d5555 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -5,8 +5,11 @@ using ManifoldsBase
     if VERSION >= v"1.1"
         num_ambiguities = length(Test.detect_ambiguities(ManifoldsBase))
         #num_ambiguities > 0 && @warn "The number of ambiguities in ManifoldsBase is $(num_ambiguities)."
-        if VERSION >= v"1.6"
-            @test num_ambiguities <= 1
+        if VERSION >= v"1.6-DEV"
+            # At the time of writing there seem to be two ambiguities regarding `getindex`,
+            # one with a method from SparseArrays and one from VSCode's JSON processing
+            # that's automatically loaded when running code in VSCode.
+            @test num_ambiguities <= 2
         else
             @test num_ambiguities == 0
         end
diff --git a/test/validation_manifold.jl b/test/validation_manifold.jl
index f978f0e5..d74d7c02 100644
--- a/test/validation_manifold.jl
+++ b/test/validation_manifold.jl
@@ -75,7 +75,7 @@ end
             @test isapprox(A, 2 * a, T(2 .* v))
         end
     end
-    @testset "Manifold functions" begin
+    @testset "AbstractManifold functions" begin
         @test manifold_dimension(A) == manifold_dimension(M)
         @test isapprox(y2.value, y)
         @test distance(A, x, y) == distance(M, x, y)
@@ -97,7 +97,7 @@ end
         @test mp == 0.5 * (x .+ y)
         @test isapprox(A, x, v2s, v2)
         @test isapprox(A, exp(A, x, v), y2)
-        @test isapprox(A, zero_tangent_vector(A, x), zero_tangent_vector(M, x))
+        @test isapprox(A, zero_vector(A, x), zero_vector(M, x))
         vector_transport_to!(A, v2s, x2, v2, y2)
         @test isapprox(A, x2, v2, v2s)
         vector_transport_to!(A, v2s, x2, v2, y2, ManifoldsBase.SchildsLadderTransport())
@@ -106,8 +106,8 @@ end
         @test isapprox(A, x2, v2, v2s)
         vector_transport_to!(A, v2s, x2, v2, y2, ManifoldsBase.ProjectionTransport())
         @test isapprox(A, x2, v2, v2s)
-        zero_tangent_vector!(A, v2s, x)
-        @test isapprox(A, x, v2s, zero_tangent_vector(M, x))
+        zero_vector!(A, v2s, x)
+        @test isapprox(A, x, v2s, zero_vector(M, x))
         c = [x2]
         v3 = similar(v2)
         @test isapprox(
diff --git a/test/vector_transport_along.jl b/test/vector_transport_along.jl
index 0d709014..70e5e33e 100644
--- a/test/vector_transport_along.jl
+++ b/test/vector_transport_along.jl
@@ -5,7 +5,7 @@
 using ManifoldsBase, Test
 
 
-struct NonDefaultEuclidean <: Manifold{ManifoldsBase.ℝ} end
+struct NonDefaultEuclidean <: AbstractManifold{ManifoldsBase.ℝ} end
 ManifoldsBase.log!(::NonDefaultEuclidean, v, x, y) = (v .= y .- x)
 ManifoldsBase.exp!(::NonDefaultEuclidean, y, x, v) = (y .= x .+ v)
 function ManifoldsBase.vector_transport_to!(