diff --git a/Project.toml b/Project.toml index 29a48b30..82847f93 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ManifoldsBase" uuid = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb" authors = ["Seth Axen ", "Mateusz Baran ", "Ronny Bergmann ", "Antoine Levitt "] -version = "0.12.1" +version = "0.12.2" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl index b9c352dc..920a4f8b 100644 --- a/src/ManifoldsBase.jl +++ b/src/ManifoldsBase.jl @@ -5,6 +5,7 @@ import Base: exp, log, convert, + copy, copyto!, angle, eltype, @@ -81,7 +82,7 @@ end Return type of element of the array that will represent the result of function `f` and the [`AbstractManifold`](@ref) `M` on given arguments `args` (passed as a tuple). """ -function allocate_result_type(M::AbstractManifold, f, args::NTuple{N,Any}) where {N} +function allocate_result_type(::AbstractManifold, f, args::NTuple{N,Any}) where {N} return typeof(mapreduce(eti -> one(number_eltype(eti)), +, args)) end @@ -175,6 +176,33 @@ function check_size(M::AbstractManifold, p, X) end end +@doc raw""" + copy(M, p) + +Copy the value(s) from the point `p` on the [`AbstractManifold`](@ref) `M` into a new point. +See [`allocate_result`](@ref) for the allocation of new point memory and [`copyto!`](@ref) for the copying. +""" +function copy(M::AbstractManifold, p) + q = allocate_result(M, copy, p) + copyto!(M, q, p) + return q +end + +@doc raw""" + copy(M, p, X) + +Copy the value(s) from the tangent vector `X` at a point `p` on the +[`AbstractManifold`](@ref) `M` into a new tangent vector. +See [`allocate_result`](@ref) for the allocation of new point memory and [`copyto!`](@ref) for the copying. +""" +function copy(M::AbstractManifold, p, X) + # the order of args switched, since the allocation by default takes the type of the first. + Y = allocate_result(M, copy, X, p) + copyto!(M, Y, p, X) + return Y +end + + @doc raw""" copyto!(M::AbstractManifold, q, p) @@ -272,8 +300,7 @@ see [`AbstractEmbeddedManifold`](@ref) how you can avoid reimplementing code fro See also: [`EmbeddedManifold`](@ref), [`project`](@ref project(M::AbstractManifold, 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. + # the order of args switched, since the allocation by default takes the type of the first. Y = allocate_result(M, embed, X, p) embed!(M, Y, p, X) return Y @@ -596,6 +623,8 @@ export allocate, check_point, check_vector, check_size, + copy, + copyto!, distance, exp, exp!, diff --git a/test/default_manifold.jl b/test/default_manifold.jl index f4cdf8fd..09d8bf54 100644 --- a/test/default_manifold.jl +++ b/test/default_manifold.jl @@ -306,4 +306,20 @@ Base.size(x::MatrixVectorTransport) = (size(x.m, 2),) a = NLsolveInverseRetraction(ExponentialRetraction()) @test a.retraction isa ExponentialRetraction end + + @testset "copy of points and vectors" begin + M = DefaultManifold(2) + p = [2.0, 3.0] + q = similar(p) + copyto!(M, q, p) + @test p == q + r = copy(M, p) + @test r == p + X = [4.0, 5.0] + Y = similar(X) + copyto!(M, Y, p, X) + @test Y == X + Z = copy(M, p, X) + @test Z == X + end end