Skip to content

Commit

Permalink
Add copyto tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
kellertuer committed Oct 15, 2024
1 parent 2065185 commit a27ab64
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 30 deletions.
67 changes: 41 additions & 26 deletions src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,27 @@ function conjugate!(G::LieGroup, k, g, h)
end

ManifoldsBase.copyto!(G::LieGroup, h, g) = ManifoldsBase.copyto!(G.manifold, h, g)
function ManifoldsBase.copyto!(G::LieGroup{𝔽,O}, h, g::Identity{O}) where {𝔽,O}
return ManifoldsBase.copyto!(G.manifold, h, identity_element(g))
function ManifoldsBase.copyto!(
G::LieGroup{𝔽,O}, h, g::Identity{O}
) where {𝔽,O<:AbstractGroupOperation}
return ManifoldsBase.copyto!(G.manifold, h, identity_element(G))
end
function ManifoldsBase.copyto!(G::LieGroup{𝔽,O}, h::Identity{O}, g::Identity{O}) where {𝔽,O}
return ManifoldsBase.copyto!(G.manifold, h, identity_element(g))
function ManifoldsBase.copyto!(
::LieGroup{𝔽,O}, h::Identity{O}, ::Identity{O}
) where {𝔽,O<:AbstractGroupOperation}
return h
end
function ManifoldsBase.copyto!(
G::LieGroup{𝔽,O}, h::Identity{O}, g
) where {𝔽,O<:AbstractGroupOperation}
(is_identity(G, g)) && return h
throw(
DomainError(
g,
"copyto! into the identity element of $G ($h) is not defined for a non-identity element g ($g)",
),
)
end

_doc_diff_conjugate = """
diff_conjugate(G::LieGroup, g, h, X)
diff_conjugate!(G::LieGroup, Y, g, h, X)
Expand Down Expand Up @@ -397,6 +411,28 @@ function ManifoldsBase.exp!(G::LieGroup, h, e::Identity, X, t::Number=1)
),
)
end

_doc_identity_element = """
identity_element(G::LieGroup)
identity_element!(G::LieGroup, g)
Return a point representation of the [`Identity`](@ref) on the [`LieGroup`](@ref) `G`.
By default this representation is the default array or number representation.
It should return the corresponding default representation of ``e`` as a point on `G` if
points are not represented by arrays.
This can be performed in-place of `g`.
"""
# `function identity_element end`
@doc "$(_doc_identity_element)"
function identity_element(G::LieGroup)
g = ManifoldsBase.allocate_result(G, identity_element)
return identity_element!(G, g)
end

function identity_element! end
@doc "$(_doc_identity_element)"
identity_element!(G::LieGroup, g)

_doc_inv_left_compose = """
inv_left_compose(G::LieGroup, g, h)
inv_left_compose!(G::LieGroup, k, g, h)
Expand Down Expand Up @@ -441,27 +477,6 @@ function inv_right_compose!(::LieGroup, k, h, g)
return k

Check warning on line 477 in src/interface.jl

View check run for this annotation

Codecov / codecov/patch

src/interface.jl#L474-L477

Added lines #L474 - L477 were not covered by tests
end

_doc_identity_element = """
identity_element(G::LieGroup)
identity_element!(G::LieGroup, g)
Return a point representation of the [`Identity`](@ref) on the [`LieGroup`](@ref) `G`.
By default this representation is the default array or number representation.
It should return the corresponding default representation of ``e`` as a point on `G` if
points are not represented by arrays.
This can be performed in-place of `g`.
"""
# `function identity_element end`
@doc "$(_doc_identity_element)"
function identity_element(G::LieGroup)
g = ManifoldsBase.allocate_result(G, identity_element)
return identity_element!(G, g)
end

function identity_element! end
@doc "$(_doc_identity_element)"
identity_element!(G::LieGroup, g)

_doc_inv = """
inv(G::LieGroup, g)
inv!(G::LieGroup, h, g)
Expand Down
47 changes: 44 additions & 3 deletions test/LieGroupsTestSuite.jl/LieGroupsTestSuite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ end
Test functionality of `conjugate`.
# Keyword arguments
* `expected_value=missing` the result of the conjugate can also be provided directly,
* `expected_value=missing`: the result of the conjugate can also be provided directly,
then neither `compose` nor `inv` are not required.
"""
function test_conjugate(G::LieGroup, g, h; expected_value=missing)
Expand All @@ -96,6 +96,33 @@ function test_conjugate(G::LieGroup, g, h; expected_value=missing)
return nothing
end

"""
test_copyto(G, g)
Test that `copyto!` works also when copying over an `Identity`.
The point `g` can be any point _but_ the `identity_element`.
"""
function test_copyto(G, g)
@testset "copyto!" begin
k = copy(G, g)
e = Identity(G)
copyto!(G, k, e)
@test is_identity(G, k)
# Test that copying back also works
copyto!(G, k, g)
@test isapprox(G, k, g)
# copy into identity only works if provided the identity
@test copyto!(G, e, Identity(G)) == e
# but then also always returns e
copyto!(G, k, e)
@test copyto!(G, e, k) == e
# and fails if the point to copy in is not (numerically) e
@test_throws DomainError copyto!(G, e, g)
return nothing
end
end

"""
test_exp_log(G, g, h, X)
Expand Down Expand Up @@ -194,7 +221,7 @@ Possible properties are
* `:Functions` is a vector of all defined functions for `G`
Note that if `f` is in `:Functions`, and `f!` makes sense, for example for `compose`,
it is assumed that both are defined.
* `:points` is a vector of at least three points on `G`
* `:points` is a vector of at least three points on `G`, the first is not allowed to be the identity numerically
* `:vectors` is a vector of at least 3 elements from the Lie algebra `𝔤` og `G`
* `:name` is a name of the test. If not provided, defaults to `"\$G"`
Expand All @@ -214,14 +241,25 @@ function test_LieGroup(G::LieGroup, properties::Dict, expectations::Dict=Dict())
test_name = get(properties, :Name, "$G")
@testset "$(test_name)" begin
# Call function tests based on their presence in alphabetical order
#
#
# --- C
if (compose in functions)
ti = all(in.([inv, is_identity], Ref(functions)))
test_compose(G, points[1], points[2]; test_inverse=ti)
end
if (conjugate in functions)
# since there is a default, also providing compose&inv suffices
if (conjugate in functions) || (all(in.([compose, inv], Ref(functions))))
v = get(expectations, :conjugate, missing)
test_conjugate(G, points[1], points[2]; expected_value=v)
end
# Either `copyto` or the default with `identity_element`` available
if any(in.([copyto!, identity_element], Ref(functions)))
test_copyto(G, points[1])
end
#
#
# --- E
if any(in.([exp, log], Ref(functions)))
test_exp_log(
G,
Expand All @@ -232,6 +270,9 @@ function test_LieGroup(G::LieGroup, properties::Dict, expectations::Dict=Dict())
test_log=(log in functions),
)
end
#
#
# --- S
if (any(in.([show, repr], Ref(functions)))) && haskey(expectations, :repr)
test_show(G, expectations[:repr])
end
Expand Down
3 changes: 2 additions & 1 deletion test/groups/test_translation_group.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ begin
:Name => "The Translation group",
:Points => [g1, g2, g3],
:Vectors => [X1, X2, X3],
:Functions => [compose, conjugate, exp, inv, log, show, is_identity],
:Functions =>
[compose, conjugate, exp, identity_element, inv, is_identity, log, show],
)
expectations = Dict(:repr => "TranslationGroup(3; field=ℝ)")
test_LieGroup(G, properties, expectations)
Expand Down

0 comments on commit a27ab64

Please sign in to comment.