Skip to content

Commit ee1354c

Browse files
authored
Merge pull request #33 from JuliaManifolds/patches-for-0.8.0
Patches for 0.8.0
2 parents 039807b + 3784062 commit ee1354c

10 files changed

+134
-51
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ManifoldsBase"
22
uuid = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb"
33
authors = ["Seth Axen <[email protected]>", "Mateusz Baran <[email protected]>", "Ronny Bergmann <[email protected]>", "Antoine Levitt <[email protected]>"]
4-
version = "0.8.0"
4+
version = "0.8.1"
55

66
[deps]
77
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

src/EmbeddedManifold.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A type used to specify properties of an [`AbstractEmbeddedManifold`](@ref).
66
abstract type AbstractEmbeddingType end
77

88
"""
9-
AbstractEmbeddedManifold{T<:AbstractEmbeddingType,𝔽} <: AbstractDecoratorManifold{𝔽}
9+
AbstractEmbeddedManifold{𝔽,T<:AbstractEmbeddingType,𝔽} <: AbstractDecoratorManifold{𝔽}
1010
1111
An abstract type for embedded manifolds, which acts as an [`AbstractDecoratorManifold`](@ref).
1212
The functions of the manifold that is embedded can hence be just passed on to the embedding.
@@ -20,7 +20,7 @@ abstract type AbstractEmbeddedManifold{𝔽,T<:AbstractEmbeddingType} <:
2020
AbstractDecoratorManifold{𝔽} end
2121

2222
"""
23-
DefaultEmbeddingType <: AbstractEmbeddingType
23+
DefaultEmbeddingType <: AbstractEmbeddingType
2424
2525
A type of default embedding that does not have any special properties.
2626
"""

src/ManifoldsBase.jl

+23-18
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,9 @@ shortest_geodesic(M::Manifold, p, q, T::AbstractVector) = geodesic(M, p, log(M,
737737
vector_transport_along(M::Manifold, p, X, c)
738738
vector_transport_along(M::Manifold, p, X, c, method::AbstractVectorTransportMethod)
739739
740-
Transport a vector `X` from a point `p` along the curve `c` such that `c(0)` is equal to `p`
741-
to the point `c(1)` using the `method`, which defaults to [`ParallelTransport`](@ref).
740+
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
741+
along the curve `c` such that `c(0)` is equal to `p` to the point `c(1)` using the `method`,
742+
which defaults to [`ParallelTransport`](@ref).
742743
"""
743744
function vector_transport_along(M::Manifold, p, X, c)
744745
return vector_transport_along(M, p, X, c, ParallelTransport())
@@ -753,9 +754,9 @@ end
753754
vector_transport_along!(M::Manifold, Y, p, X, c)
754755
vector_transport_along!(M::Manifold, Y, p, X, c, method::AbstractVectorTransportMethod)
755756
756-
Transport a vector `X` from a point `p` along the curve `c` such that `c(0)` is equal to `p`
757-
to the point `c(1)` using the `method`, which defaults to [`ParallelTransport`](@ref).
758-
The result is saved to `Y`.
757+
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
758+
along the curve `c` such that `c(0)` is equal to `p` to the point `c(1)` using the `method`,
759+
which defaults to [`ParallelTransport`](@ref). The result is saved to `Y`.
759760
"""
760761
function vector_transport_along!(M::Manifold, Y, p, X, c)
761762
return vector_transport_along!(M, Y, p, X, c, ParallelTransport())
@@ -785,9 +786,10 @@ end
785786
vector_transport_direction(M::Manifold, p, X, d)
786787
vector_transport_direction(M::Manifold, p, X, d, method::AbstractVectorTransportMethod)
787788
788-
Transport a vector `X` from a point `p` in the direction indicated by the tangent vector `d`
789-
at point `p`. By default, [`exp`](@ref) and [`vector_transport_to!`](@ref) are used with
790-
the `method`, which defaults to [`ParallelTransport`](@ref).
789+
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
790+
in the direction indicated by the tangent vector `d` at `p`. By default, [`exp`](@ref) and
791+
[`vector_transport_to!`](@ref) are used with the `method`, which defaults
792+
to [`ParallelTransport`](@ref).
791793
"""
792794
function vector_transport_direction(M::Manifold, p, X, d)
793795
return vector_transport_direction(M, p, X, d, ParallelTransport())
@@ -808,10 +810,10 @@ end
808810
vector_transport_direction!(M::Manifold, Y, p, X, d)
809811
vector_transport_direction!(M::Manifold, Y, p, X, d, method::AbstractVectorTransportMethod)
810812
811-
Transport a vector `X` from a point `p` in the direction indicated by the tangent vector `d`
812-
at point `p`. The result is saved to `Y`. By default, [`exp`](@ref) and
813-
[`vector_transport_to!`](@ref) are used with the `method`, which defaults to
814-
[`ParallelTransport`](@ref).
813+
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
814+
in the direction indicated by the tangent vector `d` at `p`. By default, [`exp`](@ref) and
815+
[`vector_transport_to!`](@ref) are used with the `method`, which defaults
816+
to [`ParallelTransport`](@ref). The result is saved to `Y`.
815817
"""
816818
function vector_transport_direction!(M::Manifold, Y, p, X, d)
817819
return vector_transport_direction!(M, Y, p, X, d, ParallelTransport())
@@ -832,7 +834,8 @@ end
832834
vector_transport_to(M::Manifold, p, X, q)
833835
vector_transport_to(M::Manifold, p, X, q, method::AbstractVectorTransportMethod)
834836
835-
Compute the vector transport of vector `X` at point `p` to point `q`.
837+
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
838+
along the [`shortest_geodesic`](@ref) to the tangent space at another point `q`.
836839
By default, the [`AbstractVectorTransportMethod`](@ref) `method` is
837840
[`ParallelTransport`](@ref).
838841
"""
@@ -849,19 +852,20 @@ end
849852
vector_transport_to!(M::Manifold, Y, p, X, q)
850853
vector_transport_to!(M::Manifold, Y, p, X, q, method::AbstractVectorTransportMethod)
851854
852-
Compute the vector transport of vector `X` at point `p` to point `q`.
853-
The result is saved to `Y`. By default, the [`AbstractVectorTransportMethod`](@ref) `method`
854-
is [`ParallelTransport`](@ref).
855+
Transport a vector `X` from the tangent space at a point `p` on the [`Manifold`](@ref) `M`
856+
along the [`shortest_geodesic`](@ref) to the tangent space at another point `q`.
857+
By default, the [`AbstractVectorTransportMethod`](@ref) `method` is
858+
[`ParallelTransport`](@ref). The result is saved to `Y`.
855859
"""
856860
function vector_transport_to!(M::Manifold, Y, p, q, X)
857861
return vector_transport_to!(M, Y, p, q, X, ParallelTransport())
858862
end
859863
"""
860864
vector_transport_to!(M::Manifold, Y, p, X, q, method::ProjectionTransport)
861865
862-
Transport a vector `X` from the tangent space at `p` on a [`Manifold`](@ref) `M` by
866+
Transport a vector `X` from the tangent space at `p` on the [`Manifold`](@ref) `M` by
863867
interpreting it as an element of the embedding and then projecting it onto the tangent space
864-
at `q`. This method requires [`project`](@ref).
868+
at `q`. This method requires [`project`](@ref project(M::Manifold, p, X)).
865869
"""
866870
function vector_transport_to!(M::Manifold, Y, p, X, q, ::ProjectionTransport)
867871
return project!(M, Y, q, X)
@@ -977,6 +981,7 @@ export allocate,
977981
manifold_dimension,
978982
norm,
979983
number_eltype,
984+
number_of_coordinates,
980985
number_system,
981986
project,
982987
project!,

src/ValidationManifold.jl

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
"""
2-
ValidationManifold{M<:Manifold} <: Manifold
2+
ValidationManifold{𝔽,M<:Manifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
33
4-
A manifold to encapsulate manifolds working on array representations of `MPoints` and
5-
`TVectors` in a transparent way, such that for these manifolds it's not necessary to
6-
introduce explicit types for the points and tangent vectors, but they are
4+
A manifold to encapsulate manifolds working on array representations of [`MPoint`](@ref)s
5+
and [`TVector`](@ref)s in a transparent way, such that for these manifolds it's not
6+
necessary to introduce explicit types for the points and tangent vectors, but they are
77
encapsulated/stripped automatically when needed.
88
9-
This manifold is a decorator for a manifold, i.e. it decorates a manifold `M` with types
10-
points, vectors, and covectors.
9+
This manifold is a decorator for a manifold, i.e. it decorates a [`Manifold`](@ref) `M`
10+
with types points, vectors, and covectors.
1111
"""
1212
struct ValidationManifold{𝔽,M<:Manifold{𝔽}} <: AbstractDecoratorManifold{𝔽}
1313
manifold::M
@@ -183,7 +183,8 @@ function get_basis(
183183
kwargs...,
184184
) where {𝔽}
185185
is_manifold_point(M, p, true; kwargs...)
186-
Ξ = invoke(get_basis, Tuple{ValidationManifold,Any,AbstractOrthogonalBasis}, M, p, B; kwargs...)
186+
get_basis_invoke_types = Tuple{ValidationManifold,Any,Union{AbstractOrthogonalBasis,CachedBasis{𝔽,<:AbstractOrthogonalBasis{𝔽}}} where {𝔽}}
187+
Ξ = invoke(get_basis, get_basis_invoke_types, M, p, B; kwargs...)
187188
bvectors = get_vectors(M, p, Ξ)
188189
N = length(bvectors)
189190
for i = 1:N

src/bases.jl

+41-12
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ struct DiagonalizingBasisData{D,V,ET}
117117
vectors::V
118118
end
119119

120-
const DefaultOrDiagonalizingBasis =
121-
Union{DefaultOrthonormalBasis,DiagonalizingOrthonormalBasis}
120+
const DefaultOrDiagonalizingBasis{𝔽} =
121+
Union{DefaultOrthonormalBasis{𝔽},DiagonalizingOrthonormalBasis{𝔽}}
122122

123123
"""
124124
CachedBasis{𝔽,V,<:AbstractBasis{𝔽}} <: AbstractBasis{𝔽}
@@ -156,10 +156,6 @@ function get_vector end
156156
const all_uncached_bases = Union{AbstractBasis, DefaultBasis, DefaultOrthogonalBasis, DefaultOrthonormalBasis}
157157
const DISAMBIGUATION_BASIS_TYPES = [
158158
CachedBasis,
159-
CachedBasis{ℝ,<:AbstractBasis{ℝ}},
160-
CachedBasis{ℂ,<:AbstractBasis{ℂ}},
161-
CachedBasis{ℝ,<:AbstractOrthogonalBasis{ℝ}},
162-
CachedBasis{ℝ,<:AbstractOrthonormalBasis{ℝ}},
163159
DefaultBasis,
164160
DefaultOrthonormalBasis,
165161
DefaultOrthogonalBasis,
@@ -169,14 +165,20 @@ const DISAMBIGUATION_BASIS_TYPES = [
169165
VeeOrthogonalBasis,
170166
]
171167

172-
function allocate_result(M::Manifold, f::typeof(get_coordinates), p, X, B)
168+
function allocate_result(
169+
M::Manifold,
170+
f::typeof(get_coordinates),
171+
p,
172+
X,
173+
B::AbstractBasis,
174+
)
173175
T = allocate_result_type(M, f, (p, X))
174-
return allocate(p, T, manifold_dimension(M))
176+
return allocate(p, T, number_of_coordinates(M, B))
175177
end
176178

177179
function allocate_result(M::Manifold, f::typeof(get_coordinates), p, X, B::CachedBasis)
178180
T = allocate_result_type(M, f, (p, X))
179-
return allocate(p, T, length(get_vectors(M, p, B)))
181+
return allocate(p, T, number_of_coordinates(M, B))
180182
end
181183

182184
@inline function allocate_result_type(
@@ -229,6 +231,10 @@ See also: [`get_coordinates`](@ref), [`get_vector`](@ref)
229231
function get_basis(M::Manifold, p, B::AbstractBasis)
230232
error("get_basis not implemented for manifold of type $(typeof(M)) a point of type $(typeof(p)) and basis of type $(typeof(B)).")
231233
end
234+
@decorator_transparent_signature get_basis(M::AbstractDecoratorManifold, p, B::AbstractBasis)
235+
function decorator_transparent_dispatch(::typeof(get_basis), ::Manifold, args...)
236+
return Val(:parent)
237+
end
232238

233239
function get_basis(M::Manifold, p, B::DefaultOrthonormalBasis)
234240
dim = manifold_dimension(M)
@@ -305,6 +311,11 @@ function get_basis(
305311
error("get_basis with bases $(typeof(B)) only found $(K) orthonormal basis vectors, but manifold dimension is $(dim).")
306312
end
307313
end
314+
for BT in DISAMBIGUATION_BASIS_TYPES
315+
eval(quote
316+
@decorator_transparent_signature get_basis(M::AbstractDecoratorManifold, p, B::$BT)
317+
end)
318+
end
308319

309320
"""
310321
get_coordinates(M::Manifold, p, X, B::AbstractBasis)
@@ -354,11 +365,14 @@ end
354365
function get_coordinates!(M::Manifold, Y, p, X, B::DefaultOrthogonalBasis)
355366
return get_coordinates!(M, Y, p, X, DefaultOrthonormalBasis(number_system(B)))
356367
end
357-
function get_coordinates!(M::Manifold{𝔾}, Y, p, X, C::CachedBasis{𝔽,B,V}) where {B,V,𝔾,𝔽}
358-
map!(vb -> conj(inner(M, p, X, vb)), Y, get_vectors(M, p, C))
368+
function get_coordinates!(M::Manifold, Y, p, X, B::CachedBasis)
369+
_get_coordinates!(M, number_system(M), Y, p, X, B, number_system(B))
370+
end
371+
function _get_coordinates!(M::Manifold, ::ComplexNumbers, Y, p, X, B::CachedBasis,::RealNumbers)
372+
map!(vb -> conj(inner(M, p, X, vb)), Y, get_vectors(M, p, B))
359373
return Y
360374
end
361-
function get_coordinates!(M::Manifold{𝔽}, Y, p, X, C::CachedBasis{𝔽,B,V}) where {B,V,𝔽}
375+
function _get_coordinates!(M::Manifold, a::𝔽, Y, p, X, C::CachedBasis, b::𝔽) where {𝔽}
362376
map!(vb -> real(inner(M, p, X, vb)), Y, get_vectors(M, p, C))
363377
return Y
364378
end
@@ -417,6 +431,7 @@ function get_vector!(M::Manifold, Y, p, X, B::CachedBasis)
417431
# 2) guarantees a reasonable array type `Y`
418432
# (for example scalar * `SizedValidation` is an `SArray`)
419433
bvectors = get_vectors(M, p, B)
434+
#print("hi.\nB:$(B)\n& X:$(X)\n\nyields\n $(bvectors).")
420435
if _get_vector_cache_broadcast(bvectors[1]) === Val(false)
421436
Xt = X[1] * bvectors[1]
422437
copyto!(Y, Xt)
@@ -471,6 +486,20 @@ inverse.
471486
hat(M::Manifold, p, X) = get_vector(M, p, X, VeeOrthogonalBasis())
472487
hat!(M::Manifold, Y, p, X) = get_vector!(M, Y, p, X, VeeOrthogonalBasis())
473488

489+
"""
490+
number_of_coordinates(M::Manifold, B::AbstractBasis)
491+
492+
Compute the number of coordinates in basis `B` of manifold `M`.
493+
This also corresponds to the number of vectors represented by `B`,
494+
or stored within `B` in case of a [`CachedBasis`](@ref).
495+
"""
496+
function number_of_coordinates(M::Manifold{𝔽}, B::AbstractBasis{𝔾}) where {𝔽,𝔾}
497+
return div(manifold_dimension(M), real_dimension(𝔽)) * real_dimension(𝔾)
498+
end
499+
function number_of_coordinates(M::Manifold{𝔽}, B::AbstractBasis{𝔽}) where {𝔽}
500+
return manifold_dimension(M)
501+
end
502+
474503
"""
475504
number_system(::AbstractBasis)
476505

src/numbers.jl

+24-1
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,23 @@ the fields [`RealNumbers`](@ref) (`ℝ` for short) and [`ComplexNumbers`](@ref)
99
abstract type AbstractNumbers end
1010

1111
"""
12+
RealNumbers <: AbstractNumbers
1213
ℝ = RealNumbers()
1314
1415
The field of real numbers.
1516
"""
1617
struct RealNumbers <: AbstractNumbers end
1718

1819
"""
20+
ComplexNumbers <: AbstractNumbers
1921
ℂ = ComplexNumbers()
2022
2123
The field of complex numbers.
2224
"""
2325
struct ComplexNumbers <: AbstractNumbers end
2426

2527
"""
28+
QuaternionNumbers <: AbstractNumbers
2629
ℍ = QuaternionNumbers()
2730
2831
The division algebra of quaternions.
@@ -33,14 +36,34 @@ const ℝ = RealNumbers()
3336
const= ComplexNumbers()
3437
const= QuaternionNumbers()
3538

39+
"""
40+
_unify_number_systems(𝔽s::AbstractNumbers...)
41+
42+
Compute a number system that includes all given number systems (as sub-systems) and is
43+
closed under addition and multiplication.
44+
"""
45+
function _unify_number_systems(a::AbstractNumbers, rest::AbstractNumbers...)
46+
return _unify_number_systems(a, _unify_number_systems(rest...))
47+
end
48+
_unify_number_systems(𝔽::AbstractNumbers) = 𝔽
49+
_unify_number_systems(r::RealNumbers, ::RealNumbers) = r
50+
_unify_number_systems(::RealNumbers, c::ComplexNumbers) = c
51+
_unify_number_systems(::RealNumbers, q::QuaternionNumbers) = q
52+
_unify_number_systems(c::ComplexNumbers, ::RealNumbers) = c
53+
_unify_number_systems(c::ComplexNumbers, ::ComplexNumbers) = c
54+
_unify_number_systems(::ComplexNumbers, q::QuaternionNumbers) = q
55+
_unify_number_systems(q::QuaternionNumbers, ::RealNumbers) = q
56+
_unify_number_systems(q::QuaternionNumbers, ::ComplexNumbers) = q
57+
_unify_number_systems(q::QuaternionNumbers, ::QuaternionNumbers) = q
58+
3659
Base.show(io::IO, ::RealNumbers) = print(io, "")
3760
Base.show(io::IO, ::ComplexNumbers) = print(io, "")
3861
Base.show(io::IO, ::QuaternionNumbers) = print(io, "")
3962

4063
@doc raw"""
4164
real_dimension(𝔽::AbstractNumbers)
4265
43-
Return the real dimension $\dim_ℝ 𝔽$ of the [`AbstractNumbers`] system `𝔽`.
66+
Return the real dimension $\dim_ℝ 𝔽$ of the [`AbstractNumbers`](@ref) system `𝔽`.
4467
The real dimension is the dimension of a real vector space with which a number in `𝔽` can be
4568
identified.
4669
For example, [`ComplexNumbers`](@ref) have a real dimension of 2, and

test/bases.jl

+13-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ ManifoldsBase.manifold_dimension(::ProjManifold) = 5
1313
ManifoldsBase.get_vector(::ProjManifold, x, v, ::DefaultOrthonormalBasis) = reverse(v)
1414

1515
@testset "Dispatch" begin
16+
@test ManifoldsBase.decorator_transparent_dispatch(
17+
get_basis,
18+
DefaultManifold(3),
19+
[0.0, 0.0, 0.0],
20+
DefaultBasis(),
21+
) === Val(:parent)
1622
@test ManifoldsBase.decorator_transparent_dispatch(
1723
get_coordinates,
1824
DefaultManifold(3),
@@ -200,6 +206,7 @@ DiagonalizingBasisProxy() = DiagonalizingOrthonormalBasis([1.0, 0.0, 0.0])
200206
continue
201207
end
202208
v1 = log(M, pts[1], pts[2])
209+
@test ManifoldsBase.number_of_coordinates(M, BT()) == 3
203210

204211
if BT != DiagonalizingBasisProxy
205212
vb = get_coordinates(M, pts[1], v1, BT())
@@ -259,15 +266,17 @@ end
259266
X = [1.2, 2.2im, 2.3im]
260267
b = [Matrix{Float64}(I,3,3)[:,i] for i=1:3]
261268
Bℝ = CachedBasis(DefaultOrthonormalBasis{ℝ}(),b)
262-
aℝ = get_coordinates(M,p,X,Bℝ)
263-
Yℝ = get_vector(M,p,aℝ,Bℝ)
269+
aℝ = get_coordinates(M, p, X, Bℝ)
270+
Yℝ = get_vector(M, p, aℝ, Bℝ)
264271
@test Yℝ X
272+
@test ManifoldsBase.number_of_coordinates(M, Bℝ) == 3
265273

266274
bℂ = [b...,(b.*1im)...]
267275
Bℂ = CachedBasis(DefaultOrthonormalBasis{ℂ}(), bℂ)
268-
aℂ = get_coordinates(M,p,X,Bℂ)
269-
Yℂ = get_vector(M,p,aℂ,Bℂ)
276+
aℂ = get_coordinates(M, p, X, Bℂ)
277+
Yℂ = get_vector(M, p, aℂ, Bℂ)
270278
@test Yℂ X
279+
@test ManifoldsBase.number_of_coordinates(M, Bℂ) == 6
271280
end
272281

273282
@testset "Basis show methods" begin

0 commit comments

Comments
 (0)