diff --git a/src/_BSplineManifold.jl b/src/_BSplineManifold.jl index f11ac185b..67ead06af 100644 --- a/src/_BSplineManifold.jl +++ b/src/_BSplineManifold.jl @@ -57,6 +57,14 @@ Base.:(==)(M1::AbstractManifold, M2::AbstractManifold) = (bsplinespaces(M1)==bsp bsplinespaces(M::BSplineManifold) = M.bsplinespaces controlpoints(M::BSplineManifold) = M.controlpoints +function Base.hash(M::BSplineManifold{0}, h::UInt) + hash(BSplineManifold{0}, hash(controlpoints(M), h)) +end + +function Base.hash(M::BSplineManifold, h::UInt) + hash(xor(hash.(bsplinespaces(M), h)...), hash(controlpoints(M), h)) +end + @doc raw""" unbounded_mapping(M::BSplineManifold{Dim}, t::Vararg{Real,Dim}) diff --git a/src/_BSplineSpace.jl b/src/_BSplineSpace.jl index 08aff29f9..4491834b0 100644 --- a/src/_BSplineSpace.jl +++ b/src/_BSplineSpace.jl @@ -511,3 +511,8 @@ end function expandspace(P::BSplineSpace{p,T}, k₊::AbstractKnotVector=EmptyKnotVector{T}()) where {p,T} expandspace_I(P,k₊) end + +function Base.hash(P::BSplineSpace{p}, h::UInt) where p + k = knotvector(P) + hash(BSplineSpace{p}, hash(_vec(k), h)) +end diff --git a/src/_DerivativeSpace.jl b/src/_DerivativeSpace.jl index 42b9cd868..313ecbd6c 100644 --- a/src/_DerivativeSpace.jl +++ b/src/_DerivativeSpace.jl @@ -116,3 +116,9 @@ function Base.issubset(P::BSplineSpace, dP′::BSplineDerivativeSpace) end # TODO: Add issqsubset + +function Base.hash(dP::BSplineDerivativeSpace{r,<:BSplineSpace{p}}, h::UInt) where {r,p} + P = bsplinespace(dP) + k = knotvector(P) + hash(BSplineDerivativeSpace{r,<:BSplineSpace{p}}, hash(_vec(k), h)) +end diff --git a/src/_KnotVector.jl b/src/_KnotVector.jl index 50baa2d71..15adea605 100644 --- a/src/_KnotVector.jl +++ b/src/_KnotVector.jl @@ -459,3 +459,7 @@ KnotVector([6]) macro knotvector_str(s) return sum(KnotVector(findall(==('0'+i), s))*i for i in 1:9) end + +function Base.hash(k::AbstractKnotVector, h::UInt) + hash(AbstractKnotVector, hash(_vec(k), h)) +end diff --git a/src/_RationalBSplineManifold.jl b/src/_RationalBSplineManifold.jl index f930737d6..ef3ab8c5f 100644 --- a/src/_RationalBSplineManifold.jl +++ b/src/_RationalBSplineManifold.jl @@ -51,6 +51,14 @@ RationalBSplineManifold(a::Array{C,Dim},w::Array{T,Dim},Ps::Vararg{BSplineSpace, Base.:(==)(M1::RationalBSplineManifold, M2::RationalBSplineManifold) = (bsplinespaces(M1)==bsplinespaces(M2)) & (controlpoints(M1)==controlpoints(M2)) & (weights(M1)==weights(M2)) +function Base.hash(M::RationalBSplineManifold{0}, h::UInt) + hash(RationalBSplineManifold{0}, hash(weights(M), hash(controlpoints(M), h))) +end + +function Base.hash(M::RationalBSplineManifold, h::UInt) + hash(xor(hash.(bsplinespaces(M), h)...), hash(weights(M), hash(controlpoints(M), h))) +end + controlpoints(M::RationalBSplineManifold) = M.controlpoints weights(M::RationalBSplineManifold) = M.weights bsplinespaces(M::RationalBSplineManifold) = M.bsplinespaces diff --git a/test/test_BSplineManifold.jl b/test/test_BSplineManifold.jl index 078a99d7a..c6e19a332 100644 --- a/test/test_BSplineManifold.jl +++ b/test/test_BSplineManifold.jl @@ -18,6 +18,37 @@ return a′ end + @testset "constructor" begin + k1 = KnotVector([0,0,1,1]) + k2 = UniformKnotVector(1:8) + k3 = KnotVector(rand(8)) + _k1 = KnotVector([0,0,1,1]) + _k2 = KnotVector(1:8) + _k3 = copy(k3) + P1 = BSplineSpace{1}(k1) + P2 = BSplineSpace{3}(k2) + P3 = BSplineSpace{2}(k3) + _P1 = BSplineSpace{1}(_k1) + _P2 = BSplineSpace{3}(_k2) + _P3 = BSplineSpace{2}(_k3) + + # 0-dim + a = fill(1.2) + @test BSplineManifold(a) == BSplineManifold(a) + @test BSplineManifold(a) == BSplineManifold(copy(a)) + @test hash(BSplineManifold(a)) == hash(BSplineManifold(a)) + @test hash(BSplineManifold(a)) == hash(BSplineManifold(copy(a))) + + # 4-dim + a = rand(dim(P1), dim(P2), dim(P3), dim(P3)) + @test BSplineManifold(a, P1, P2, P3, P3) == BSplineManifold(a, P1, P2, P3, P3) + @test hash(BSplineManifold(a, P1, P2, P3, P3)) == hash(BSplineManifold(a, P1, P2, P3, P3)) + @test BSplineManifold(a, P1, P2, P3, P3) == BSplineManifold(a, _P1, _P2, _P3, _P3) + @test hash(BSplineManifold(a, P1, P2, P3, P3)) == hash(BSplineManifold(a, _P1, _P2, _P3, _P3)) + @test BSplineManifold(a, P1, P2, P3, P3) == BSplineManifold(copy(a), _P1, _P2, _P3, _P3) + @test hash(BSplineManifold(a, P1, P2, P3, P3)) == hash(BSplineManifold(copy(a), _P1, _P2, _P3, _P3)) + end + @testset "1dim" begin @testset "BSplineManifold-1dim" begin P1 = BSplineSpace{1}(KnotVector([0, 0, 1, 1])) diff --git a/test/test_BSplineSpace.jl b/test/test_BSplineSpace.jl index aec0451c6..b8eadb4ca 100644 --- a/test/test_BSplineSpace.jl +++ b/test/test_BSplineSpace.jl @@ -123,12 +123,15 @@ @test P1 ⊆ P2 @test P2 ⊆ P1 @test P1 == P2 + @test hash(P1) == hash(P2) @test P3 ⊆ P4 @test P4 ⊆ P3 @test P3 == P4 + @test hash(P3) == hash(P4) @test P1 != P3 + @test hash(P1) != hash(P3) end @testset "expandspace" begin diff --git a/test/test_Derivative.jl b/test/test_Derivative.jl index b0f036f65..685810e52 100644 --- a/test/test_Derivative.jl +++ b/test/test_Derivative.jl @@ -16,6 +16,7 @@ dP7 = BSplineDerivativeSpace{2,typeof(P3)}(dP6) @test dP1 == dP2 == dP3 != dP4 @test dP1 !== dP2 + @test hash(dP1) == hash(dP2) == hash(dP3) != hash(dP4) @test_throws MethodError BSplineDerivativeSpace{1,typeof(P2)}(dP1) @test_throws MethodError BSplineDerivativeSpace(dP1) @test_throws MethodError BSplineDerivativeSpace{}(dP1) @@ -25,6 +26,7 @@ @test dP1 isa BSplineDerivativeSpace{1,<:BSplineSpace{p,T,KnotVector{T}} where {p,T}} @test dP2 isa BSplineDerivativeSpace{1,<:UniformBSplineSpace{p,T} where {p,T}} @test dP4 == dP5 == dP6 == dP7 + @test hash(dP4) == hash(dP5) == hash(dP6) == hash(dP7) @test dP2 == convert(BSplineDerivativeSpace,dP2) @test dP2 == convert(BSplineDerivativeSpace{1},dP2) diff --git a/test/test_KnotVector.jl b/test/test_KnotVector.jl index 18aadec29..1488744c1 100644 --- a/test/test_KnotVector.jl +++ b/test/test_KnotVector.jl @@ -13,6 +13,14 @@ @test k1 != k2 @test k1.vector !== copy(k1).vector + @test hash(k1) == hash(KnotVector(1:3)::KnotVector{Int}) + @test hash(k1) == hash(KnotVector([1,3,2])::KnotVector{Int64}) + @test hash(k1) == hash(KnotVector([1,2,3])::KnotVector{Int64}) + @test hash(k1) == hash(KnotVector([1,3,2])::KnotVector{Int64}) + @test hash(k1) == hash(KnotVector([1.,3,2])::KnotVector{Float64}) + @test hash(k1) == hash(KnotVector{Int}([1,3,2])::KnotVector{Int}) + @test hash(k1) != hash(k2) + @test KnotVector{Int}([1,2]) isa KnotVector{Int} @test KnotVector{Int}([1,2]) isa KnotVector{Int} @test KnotVector{Int}([1,2.]) isa KnotVector{Int} @@ -59,7 +67,12 @@ @test KnotVector(Float64[]) == EmptyKnotVector() @test KnotVector(Float64[]) |> isempty @test KnotVector(Float64[]) |> iszero - # @test KnotVector() this shold be return error + + @test hash(KnotVector(Float64[])) == hash(zero(KnotVector)) + @test hash(KnotVector(Float64[])) == hash(0*k1) == hash(k1*0) == hash(zero(k1)) + @test hash(KnotVector(Float64[])) == hash(EmptyKnotVector()) + + @test_throws MethodError KnotVector() @test EmptyKnotVector() |> isempty @test EmptyKnotVector() |> iszero @test EmptyKnotVector() == KnotVector(Float64[]) diff --git a/test/test_RationalBSplineManifold.jl b/test/test_RationalBSplineManifold.jl index 40c601709..e3bbe0d95 100644 --- a/test/test_RationalBSplineManifold.jl +++ b/test/test_RationalBSplineManifold.jl @@ -1,4 +1,37 @@ @testset "RationalBSplineManifold" begin + @testset "constructor" begin + k1 = KnotVector([0,0,1,1]) + k2 = UniformKnotVector(1:8) + k3 = KnotVector(rand(8)) + _k1 = KnotVector([0,0,1,1]) + _k2 = KnotVector(1:8) + _k3 = copy(k3) + P1 = BSplineSpace{1}(k1) + P2 = BSplineSpace{3}(k2) + P3 = BSplineSpace{2}(k3) + _P1 = BSplineSpace{1}(_k1) + _P2 = BSplineSpace{3}(_k2) + _P3 = BSplineSpace{2}(_k3) + + # 0-dim + a = fill(1.2) + w = fill(4.2) + @test RationalBSplineManifold(a, w) == RationalBSplineManifold(a, w) + @test RationalBSplineManifold(a, w) == RationalBSplineManifold(copy(a), copy(w)) + @test hash(RationalBSplineManifold(a, w)) == hash(RationalBSplineManifold(a, w)) + @test hash(RationalBSplineManifold(a, w)) == hash(RationalBSplineManifold(copy(a), copy(w))) + + # 4-dim + a = rand(dim(P1), dim(P2), dim(P3), dim(P3)) + w = rand(dim(P1), dim(P2), dim(P3), dim(P3)) + @test RationalBSplineManifold(a, w, P1, P2, P3, P3) == RationalBSplineManifold(a, w, P1, P2, P3, P3) + @test hash(RationalBSplineManifold(a, w, P1, P2, P3, P3)) == hash(RationalBSplineManifold(a, w, P1, P2, P3, P3)) + @test RationalBSplineManifold(a, w, P1, P2, P3, P3) == RationalBSplineManifold(a, w, _P1, _P2, _P3, _P3) + @test hash(RationalBSplineManifold(a, w, P1, P2, P3, P3)) == hash(RationalBSplineManifold(a, w, _P1, _P2, _P3, _P3)) + @test RationalBSplineManifold(a, w, P1, P2, P3, P3) == RationalBSplineManifold(copy(a), copy(w), _P1, _P2, _P3, _P3) + @test hash(RationalBSplineManifold(a, w, P1, P2, P3, P3)) == hash(RationalBSplineManifold(copy(a), copy(w), _P1, _P2, _P3, _P3)) + end + @testset "1dim-arc" begin a = [SVector(1,0), SVector(1,1), SVector(0,1), SVector(-1,1), SVector(-1,0)] w = [1, 1/√2, 1, 1/√2, 1] diff --git a/test/test_UniformBSplineSpace.jl b/test/test_UniformBSplineSpace.jl index df7deff02..b9800a784 100644 --- a/test/test_UniformBSplineSpace.jl +++ b/test/test_UniformBSplineSpace.jl @@ -21,7 +21,7 @@ @test exactdim_R(P2) == exactdim_R(P2′) == 0 @test isnondegenerate(P2) == false @test isdegenerate(P2) == true - @test P2 == P2′ + @test P2 === P2′ k3 = UniformKnotVector(1.0:0.5:12.0) P3 = BSplineSpace{2}(k3) @@ -79,6 +79,9 @@ @test P1 == P2 == P3 == P4 @test P1 != P5 @test P1 != P6 + @test hash(P1) == hash(P2) == hash(P3) == hash(P4) + @test hash(P1) != hash(P5) + @test hash(P1) != hash(P6) end @testset "subset but not sqsubset" begin diff --git a/test/test_UniformKnotVector.jl b/test/test_UniformKnotVector.jl index b9a9478d5..aad198e66 100644 --- a/test/test_UniformKnotVector.jl +++ b/test/test_UniformKnotVector.jl @@ -16,6 +16,14 @@ @test k2 != 1:3 @test k1.vector === copy(k1).vector @test k1 === copy(k1) + + @test hash(k1) == hash(k1) + @test hash(k1) == hash(k2) + @test hash(k2) != hash(k3) + @test hash(k4) != hash(k3) + @test hash(k4) != hash(k2) + @test hash(k2) == hash(KnotVector(1:3)) + @test hash(k2) != hash(1:3) end @testset "constructor, conversion" begin