diff --git a/NEWS.md b/NEWS.md index 1a614167..b457a004 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,11 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.15.10] 15/05/2024 +## [0.15.10] 19/05/2024 ### Added * Functions `fill(p, N)` and `fill!(P, p, N)` to fill values into a point on a power manifold `N`. +* introduce a `base_point(TpM)` to access the base point of a tangent space +* introduce `TpM[i]` to access tangent spaces of factors from an `AbstractPowerManifold` or a `ProductManifold`. + ## [0.15.9] 02/05/2024 diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl index 3c946558..43b30f4a 100644 --- a/src/ManifoldsBase.jl +++ b/src/ManifoldsBase.jl @@ -1221,6 +1221,7 @@ export ×, allocate, angle, base_manifold, + base_point, change_basis, change_basis!, change_metric, diff --git a/src/PowerManifold.jl b/src/PowerManifold.jl index e75266a6..c188c713 100644 --- a/src/PowerManifold.jl +++ b/src/PowerManifold.jl @@ -820,6 +820,21 @@ Base.@propagate_inbounds function Base.getindex( return get_component(M, p, I...) end +""" + getindex(M::TangentSpace{𝔽, AbstractPowerManifold}, i...) + TpM[i...] + +Access the `i`th manifold component from an [`AbstractPowerManifold`](@ref)s' tangent space `TpM`. +""" +function Base.getindex( + TpM::TangentSpace{𝔽,<:AbstractPowerManifold}, + I::Union{Integer,Colon,AbstractVector}..., +) where {𝔽} + M = base_manifold(TpM) + p = base_point(TpM) + return TangentSpace(M.manifold, p[M, I...]) +end + @doc raw""" injectivity_radius(M::AbstractPowerManifold[, p]) diff --git a/src/ProductManifold.jl b/src/ProductManifold.jl index f5b4b80c..3a4d42bd 100644 --- a/src/ProductManifold.jl +++ b/src/ProductManifold.jl @@ -28,6 +28,17 @@ access the `i`th manifold component from the [`ProductManifold`](@ref) `M`. """ @inline Base.getindex(M::ProductManifold, i::Integer) = M.manifolds[i] +""" + getindex(M::TangentSpace{𝔽,<:ProductManifold}, i::Integer) + TpM[i] + +Access the `i`th manifold component from a [`ProductManifold`](@ref)s' tangent space `TpM`. +""" +function Base.getindex(TpM::TangentSpace{𝔽,<:ProductManifold}, i::Integer) where {𝔽} + M = base_manifold(TpM) + return TangentSpace(M[i], base_point(TpM)[M, i]) +end + ProductManifold() = throw(MethodError("No method matching ProductManifold().")) const PRODUCT_BASIS_LIST = [ diff --git a/src/TangentSpace.jl b/src/TangentSpace.jl index 8ba795ef..91a7a88e 100644 --- a/src/TangentSpace.jl +++ b/src/TangentSpace.jl @@ -40,6 +40,13 @@ function allocate_result(M::TangentSpace, ::typeof(rand)) return zero_vector(M.manifold, M.point) end +@doc raw""" + base_point(TpM::TangentSpace) + +Return the base point of the [`TangentSpace`](@ref). +""" +base_point(TpM::TangentSpace) = TpM.point + # forward both point checks to tangent vector checks function check_point(TpM::TangentSpace, p; kwargs...) return check_vector(TpM.manifold, TpM.point, p; kwargs...) diff --git a/test/power.jl b/test/power.jl index 513b113f..390efa72 100644 --- a/test/power.jl +++ b/test/power.jl @@ -2,11 +2,11 @@ using Test using ManifoldsBase using ManifoldsBase: AbstractNumbers, - DefaultManifold, ℝ, ℂ, NestedReplacingPowerRepresentation, - VectorSpaceType + VectorSpaceType, + DefaultManifold using StaticArrays using LinearAlgebra using Random @@ -411,6 +411,16 @@ end @test zero_vector(N, p) == 0 .* p end + @testset "TangentSpace" begin + M = ManifoldsBase.DefaultManifold(3) + N = PowerManifold(M, NestedPowerRepresentation(), 2) + p = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]] + TpN = TangentSpace(N, p) + Tp1M = TpN[1] + @test base_point(Tp1M) === p[N, 1] + @test base_manifold(Tp1M) === M + end + @testset "fill" begin M = ManifoldsBase.DefaultManifold(3) N = PowerManifold(M, NestedPowerRepresentation(), 2) diff --git a/test/product_manifold.jl b/test/product_manifold.jl index fb516c8d..67c84266 100644 --- a/test/product_manifold.jl +++ b/test/product_manifold.jl @@ -1,6 +1,6 @@ using Test using ManifoldsBase -using ManifoldsBase: submanifold_component, submanifold_components +using ManifoldsBase: DefaultManifold, submanifold_component, submanifold_components using ManifoldsBase: AbstractNumbers, ℝ, ℂ, NestedReplacingPowerRepresentation, ProductBasisData using LinearAlgebra @@ -606,4 +606,10 @@ using ManifoldsBaseTestUtils @test ts1 × ts1 == ProductVectorTransport(tr1, tr2, tr1, tr2) end + @testset "TangentSpace" begin + TpM = TangentSpace(M, p1) + Tp1M1 = TpM[1] + @test base_point(Tp1M1) === p1[M, 1] + @test base_manifold(Tp1M1) === M[1] + end end