Repository: hyrodium/BasicBSpline.jl (julia)

Issue:
Add string macro to define `KnotVector{Int}`
The following macro is not useful for most people but is useful for debugging and writing tests.
```julia
julia> using BasicBSpline

julia> macro knotvector_str(s)
           return sum(KnotVector(findall(==('0'+i), s))*i for i in 1:9)
       end
@knotvector_str (macro with 1 method)

julia> knotvector"1111"
KnotVector([1, 2, 3, 4])

julia> k1 = knotvector" 1 2  4 5"
KnotVector([2, 4, 4, 7, 7, 7, 7, 9, 9, 9, 9, 9])

julia> k2 = knotvector" 1 21 5 5"
KnotVector([2, 4, 4, 5, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9])

julia> k3 = knotvector" 1 21 5 3"
KnotVector([2, 4, 4, 5, 7, 7, 7, 7, 7, 9, 9, 9])

julia> k1 ⊆ k2
true

julia> k1 ⊆ k3
false

```

Pull request description:
This PR fixes https://github.com/hyrodium/BasicBSpline.jl/issues/315.

Patch:
diff --git a/src/BasicBSpline.jl b/src/BasicBSpline.jl
index 3f81f3aee..142ba8078 100644
--- a/src/BasicBSpline.jl
+++ b/src/BasicBSpline.jl
@@ -37,6 +37,9 @@ export bsplinespace
 # Useful functions
 export refinement
 
+# Macros
+export @knotvector_str
+
 include("_util.jl")
 include("_KnotVector.jl")
 include("_BSplineSpace.jl")
diff --git a/src/_KnotVector.jl b/src/_KnotVector.jl
index b64227f33..352168bb0 100644
--- a/src/_KnotVector.jl
+++ b/src/_KnotVector.jl
@@ -398,3 +398,27 @@ function countknots(k::AbstractKnotVector, t::Real)
     # for large case, this is faster
     return length(searchsorted(_vec(k), t, lt=<))
 end
+
+"""
+    @knotvector_str -> KnotVector
+
+Construct a knotvector by specifying the numbers of duplicates of knots.
+
+# Examples
+```jldoctest
+julia> knotvector"11111"
+KnotVector([1, 2, 3, 4, 5])
+
+julia> knotvector"123"
+KnotVector([1, 2, 2, 3, 3, 3])
+
+julia> knotvector" 2 2 2"
+KnotVector([2, 2, 4, 4, 6, 6])
+
+julia> knotvector"     1"
+KnotVector([6])
+```
+"""
+macro knotvector_str(s)
+    return sum(KnotVector(findall(==('0'+i), s))*i for i in 1:9)
+end


Test patch:
diff --git a/test/test_BSplineSpace.jl b/test/test_BSplineSpace.jl
index 43569d70d..6774bef80 100644
--- a/test/test_BSplineSpace.jl
+++ b/test/test_BSplineSpace.jl
@@ -171,9 +171,21 @@
         @test (P5 ⊑ P4) == (_P5 ⊑ _P4)
     end
 
+    @testset "subset and sqsubset" begin
+        P6 = BSplineSpace{2}(knotvector"1111 111")
+        P7 = BSplineSpace{2}(knotvector"11121111")
+        @test P6 ⊆ P6
+        @test P6 ⊆ P7
+        @test P7 ⊆ P7
+        @test P6 ⊑ P6
+        @test P6 ⊑ P7
+        @test P7 ⊑ P7
+        @test domain(P6) == domain(P7)
+    end
+
     @testset "subset but not sqsubset" begin
-        P6 = BSplineSpace{2}(KnotVector(1:8))
-        P7 = BSplineSpace{2}(KnotVector(1:10))
+        P6 = BSplineSpace{2}(knotvector"11111111")
+        P7 = BSplineSpace{2}(knotvector"1111111111")
         @test P6 ⊆ P6
         @test P7 ⊆ P7
         @test P6 ⊆ P7
@@ -187,8 +199,8 @@
     end
 
     @testset "sqsubset but not subset" begin
-        P6 = BSplineSpace{2}(KnotVector([1,2,3,4,5,6,7]))
-        P7 = BSplineSpace{2}(KnotVector([0,1,3,4,5,8,9]))
+        P6 = BSplineSpace{2}(knotvector" 1111111")
+        P7 = BSplineSpace{2}(knotvector"11 11111")
         @test P6 ⊑ P7
         @test P7 ⊑ P6
         @test P6 ≃ P7
diff --git a/test/test_KnotVector.jl b/test/test_KnotVector.jl
index 04388f469..c84f2a9c0 100644
--- a/test/test_KnotVector.jl
+++ b/test/test_KnotVector.jl
@@ -19,6 +19,12 @@
         @test KnotVector{Int}(k1) isa KnotVector{Int}
         @test KnotVector(k1) isa KnotVector{Int}
         @test AbstractKnotVector{Float64}(k1) isa KnotVector{Float64}
+
+        @test knotvector"11111" == KnotVector([1, 2, 3, 4, 5])
+        @test knotvector"123" == KnotVector([1, 2, 2, 3, 3, 3])
+        @test knotvector" 2 2 2" == KnotVector([2, 2, 4, 4, 6, 6])
+        @test knotvector"020202" == KnotVector([2, 2, 4, 4, 6, 6])
+        @test knotvector"     1" == KnotVector([6])
     end
 
     @testset "eltype" begin
@@ -129,11 +135,11 @@
     end
 
     @testset "inclusive relation" begin
-        k1 = KnotVector([1,2,3])
-        k2 = KnotVector([1,2,2,3])
-        k3 = KnotVector([1,2,2,3,5])
-        k4 = KnotVector([1,2,3,5])
-        k5 = KnotVector([1,2,3,4])
+        k1 = knotvector"111"
+        k2 = knotvector"121"
+        k3 = knotvector"121 1"
+        k4 = knotvector"111 1"
+        k5 = knotvector"1111"
         k6 = EmptyKnotVector()
         k7 = EmptyKnotVector{Real}()
         k8 = EmptyKnotVector{Float64}()