Repository: hyrodium/BasicBSpline.jl (julia)

Issue:
`⊊(::BSplineSpace, ::BSplineSpace)` is not supported
```julia
julia> using BasicBSpline

julia> P = BSplineSpace{1}(KnotVector(1:8))
BSplineSpace{1, Float64}(KnotVector([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]))

julia> P
BSplineSpace{1, Float64}(KnotVector([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]))

julia> P ⊆ P
true

julia> P ⊊ P
ERROR: MethodError: no method matching length(::BSplineSpace{1, Float64})
Closest candidates are:
  length(::Union{Base.KeySet, Base.ValueIterator}) at ~/julia/julia-1.7.1/share/julia/base/abstractdict.jl:58
  length(::Union{ArrayInterface.BidiagonalIndex, ArrayInterface.TridiagonalIndex, ArrayInterface.BandedBlockBandedMatrixIndex, ArrayInterface.BandedMatrixIndex, ArrayInterface.BlockBandedMatrixIndex}) at ~/.julia/packages/ArrayInterface/TCj9U/src/array_index.jl:209
  length(::Union{LinearAlgebra.Adjoint{T, <:Union{StaticArrays.StaticVector{<:Any, T}, StaticArrays.StaticMatrix{<:Any, <:Any, T}}}, LinearAlgebra.Diagonal{T, <:StaticArrays.StaticVector{<:Any, T}}, LinearAlgebra.Hermitian{T, <:StaticArrays.StaticMatrix{<:Any, <:Any, T}}, LinearAlgebra.LowerTriangular{T, <:StaticArrays.StaticMatrix{<:Any, <:Any, T}}, LinearAlgebra.Symmetric{T, <:StaticArrays.StaticMatrix{<:Any, <:Any, T}}, LinearAlgebra.Transpose{T, <:Union{StaticArrays.StaticVector{<:Any, T}, StaticArrays.StaticMatrix{<:Any, <:Any, T}}}, LinearAlgebra.UnitLowerTriangular{T, <:StaticArrays.StaticMatrix{<:Any, <:Any, T}}, LinearAlgebra.UnitUpperTriangular{T, <:StaticArrays.StaticMatrix{<:Any, <:Any, T}}, LinearAlgebra.UpperTriangular{T, <:StaticArrays.StaticMatrix{<:Any, <:Any, T}}, StaticArrays.StaticVector{<:Any, T}, StaticArrays.StaticMatrix{<:Any, <:Any, T}, StaticArrays.StaticArray{<:Tuple, T}} where T) at ~/.julia/dev/StaticArrays/src/abstractarray.jl:1
```

Pull request description:
This PR fixes #175.

Note that we are missing \sqsupsetneq.

Patch:
diff --git a/src/BasicBSpline.jl b/src/BasicBSpline.jl
index b9bb6713f..2954fa0a6 100644
--- a/src/BasicBSpline.jl
+++ b/src/BasicBSpline.jl
@@ -18,7 +18,7 @@ export bsplinebasis′₊₀, bsplinebasis′₋₀, bsplinebasis′
 export bsplinebasisall, intervalindex
 
 # B-spline space
-export dim, exactdim, ⊑, ⊒, ⋢, ⋣, ≃
+export dim, exactdim, ⊑, ⊒, ⋢, ⋣, ⋤, ≃
 export domain, changebasis
 export bsplinesupport, bsplinesupport_R, bsplinesupport_I
 export expandspace, expandspace_R, expandspace_I
diff --git a/src/_BSplineSpace.jl b/src/_BSplineSpace.jl
index d33e987b5..1c412f6b8 100644
--- a/src/_BSplineSpace.jl
+++ b/src/_BSplineSpace.jl
@@ -117,6 +117,11 @@ const ⊑ = issqsubset
 
 ≃(P1::AbstractBSplineSpace, P2::AbstractBSplineSpace) = (P1 ⊑ P2) & (P2 ⊑ P1)
 
+Base.:⊊(A::AbstractFunctionSpace, B::AbstractFunctionSpace) = (A ≠ B) & (A ⊆ B)
+Base.:⊋(A::AbstractFunctionSpace, B::AbstractFunctionSpace) = (A ≠ B) & (A ⊇ B)
+⋤(A::AbstractFunctionSpace, B::AbstractFunctionSpace) = (A ≠ B) & (A ⊑ B)
+# \sqsupsetneq seems missing
+
 function isdegenerate_R(P::AbstractBSplineSpace{p}, i::Integer) where p
     k = knotvector(P)
     return k[i] == k[i+p+1]
diff --git a/src/_KnotVector.jl b/src/_KnotVector.jl
index 8923a8166..6a0ac3a1b 100644
--- a/src/_KnotVector.jl
+++ b/src/_KnotVector.jl
@@ -229,6 +229,9 @@ function Base.issubset(k::KnotVector, k′::KnotVector)
     return true
 end
 
+Base.:⊊(A::AbstractKnotVector, B::AbstractKnotVector) = (A ≠ B) & (A ⊆ B)
+Base.:⊋(A::AbstractKnotVector, B::AbstractKnotVector) = (A ≠ B) & (A ⊇ B)
+
 @doc raw"""
 For given knot vector ``k``, the following function ``\mathfrak{n}_k:\mathbb{R}\to\mathbb{Z}`` represents the number of knots that duplicate the knot vector ``k``.
 


Test patch:
diff --git a/test/test_BSplineSpace.jl b/test/test_BSplineSpace.jl
index 7962e520b..e2f56aa8d 100644
--- a/test/test_BSplineSpace.jl
+++ b/test/test_BSplineSpace.jl
@@ -74,10 +74,26 @@
         P1 = BSplineSpace{1}(KnotVector([1, 3, 5, 8]))
         P2 = BSplineSpace{1}(KnotVector([1, 3, 5, 6, 8, 9]))
         P3 = BSplineSpace{2}(KnotVector([1, 1, 3, 3, 5, 5, 8, 8]))
+
+        @test P1 ⊆ P1
+        @test P2 ⊆ P2
+        @test P3 ⊆ P3
+
         @test P1 ⊆ P2
         @test P1 ⋢ P2
         @test P1 ⊆ P3
         @test P2 ⊈ P3
+
+        @test !(P1 ⊊ P1)
+        @test !(P2 ⊊ P2)
+        @test !(P3 ⊊ P3)
+        @test P1 ⊊ P2
+        @test P1 ⊊ P3
+        @test !(P1 ⊋ P1)
+        @test !(P2 ⊋ P2)
+        @test !(P3 ⊋ P3)
+        @test P2 ⊋ P1
+        @test P3 ⊋ P1
     end
 
     @testset "equality" begin
@@ -162,6 +178,8 @@
         @test P6 ≃ P7
         @test P6 ⊈ P7
         @test P7 ⊈ P6
+        @test P6 ⋤ P7
+        @test P7 ⋤ P6
         @test domain(P6) == domain(P7)
     end
 end
diff --git a/test/test_KnotVector.jl b/test/test_KnotVector.jl
index 906b385ff..8b3b4837c 100644
--- a/test/test_KnotVector.jl
+++ b/test/test_KnotVector.jl
@@ -77,6 +77,13 @@
         @test KnotVector([1,2,2,3])   ⊈ KnotVector([1,2,3,5])
         @test KnotVector([1,2,2,3,5]) ⊇ KnotVector([1,2,2,3])
         @test KnotVector([1,2,3,5])   ⊉ KnotVector([1,2,2,3])
+
+        @test !(KnotVector([1,2,3,4]) ⊊ KnotVector([1,2,3]))
+        @test !(KnotVector([1,2,3]) ⊊ KnotVector([1,2,3]))
+        @test KnotVector([1,2,3]) ⊊ KnotVector([1,2,3,4])
+        @test !(KnotVector([1,2,3]) ⊋ KnotVector([1,2,3,4]))
+        @test !(KnotVector([1,2,3]) ⊋ KnotVector([1,2,3]))
+        @test KnotVector([1,2,3,4]) ⊋ KnotVector([1,2,3])
     end
 
     @testset "string" begin