Skip to content

Commit ea0f602

Browse files
authored
[NDTensors] Add SmallVectors submodule (#1202)
1 parent d56b4a7 commit ea0f602

File tree

11 files changed

+800
-0
lines changed

11 files changed

+800
-0
lines changed

NDTensors/src/NDTensors.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ using TupleTools
1919

2020
include("SetParameters/src/SetParameters.jl")
2121
using .SetParameters
22+
include("SmallVectors/src/SmallVectors.jl")
23+
using .SmallVectors
2224

2325
using Base: @propagate_inbounds, ReshapedArray, DimOrInd, OneTo
2426

NDTensors/src/SmallVectors/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# SmallVectors
2+
3+
## Introduction
4+
5+
A module that defines small (mutable and immutable) vectors with a maximum length. Externally they have a dynamic/runtime length, but internally they are backed by a statically sized vector. This makes it so that operations can be performed faster because they can remain on the stack, but it provides some more convenience compared to StaticArrays.jl where the length is encoded in the type.
6+
7+
## Examples
8+
9+
For example:
10+
```julia
11+
using NDTensors.SmallVectors
12+
13+
mv = MSmallVector{10}([1, 2, 3]) # Mutable vector with length 3, maximum length 10
14+
push!(mv, 4)
15+
mv[2] = 12
16+
sort!(mv; rev=true)
17+
18+
v = SmallVector{10}([1, 2, 3]) # Immutable vector with length 3, maximum length 10
19+
v = SmallVectors.push(v, 4)
20+
v = SmallVectors.setindex(v, 12, 2)
21+
v = SmallVectors.sort(v; rev=true)
22+
```
23+
This also has the advantage that you can efficiently store collections of `SmallVector`/`MSmallVector` that have different runtime lengths, as long as they have the same maximum length.
24+
25+
## List of functionality
26+
27+
`SmallVector` and `MSmallVector` are subtypes of `AbstractVector` and therefore can be used in `Base` `AbstractVector` functions, though `SmallVector` will fail for mutating functions like `setindex!` because it is immutable.
28+
29+
`MSmallVector` has specialized implementations of `Base` functions that involve resizing such as:
30+
- `resize!`
31+
- `push!`
32+
- `pushfirst!`
33+
- `pop!`
34+
- `popfirst!`
35+
- `append!`
36+
- `prepend!`
37+
- `insert!`
38+
- `deleteat!`
39+
which are guaranteed to not realocate memory, and instead just use the memory buffer that already exists, unlike Base's `Vector` which may have to reallocate memory depending on the operation. However, they will error if they involve operations that resize beyond the maximum length of the `MSmallVector`, which you can access with `SmallVectors.maxlength(v)`.
40+
41+
In addition, `SmallVector` and `MSmallVector` implement basic non-mutating operations such as:
42+
- `SmallVectors.setindex`
43+
, non-mutating resizing operations:
44+
- `SmallVector.resize`
45+
- `SmallVector.push`
46+
- `SmallVector.pushfirst`
47+
- `SmallVector.pop`
48+
- `SmallVector.popfirst`
49+
- `SmallVector.append`
50+
- `SmallVector.prepend`
51+
- `SmallVector.insert`
52+
- `SmallVector.deleteat`
53+
which output a new vector. In addition, it implements:
54+
- `SmallVectors.circshift`
55+
- `sort` (overloaded from `Base`).
56+
57+
Finally, it provides some new helpful functions that are not in `Base`:
58+
- `SmallVectors.insertsorted[!]`
59+
- `SmallVectors.insertsortedunique[!]`
60+
- `SmallVectors.mergesorted[!]`
61+
- `SmallVectors.mergesortedunique[!]`
62+
63+
## TODO
64+
65+
Add specialized overloads for:
66+
- `splice[!]`
67+
- `union[!]` (``)
68+
- `intersect[!]` (``)
69+
- `setdiff[!]`
70+
- `symdiff[!]`
71+
- `unique[!]`
72+
73+
Please let us know if there are other operations that would warrant specialized implmentations for `AbstractSmallVector`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module SmallVectors
2+
using StaticArrays
3+
4+
export SmallVector, MSmallVector, SubSmallVector
5+
6+
struct NotImplemented <: Exception
7+
msg::String
8+
end
9+
NotImplemented() = NotImplemented("Not implemented.")
10+
11+
include("abstractsmallvector/abstractsmallvector.jl")
12+
include("abstractsmallvector/deque.jl")
13+
include("msmallvector/msmallvector.jl")
14+
include("smallvector/smallvector.jl")
15+
include("subsmallvector/subsmallvector.jl")
16+
end
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
A vector with a fixed maximum length, backed by a fixed size buffer.
3+
"""
4+
abstract type AbstractSmallVector{T} <: AbstractVector{T} end
5+
6+
# Required buffer interface
7+
buffer(vec::AbstractSmallVector) = throw(NotImplemented())
8+
9+
similar_type(vec::AbstractSmallVector) = typeof(vec)
10+
11+
# Required buffer interface
12+
maxlength(vec::AbstractSmallVector) = length(buffer(vec))
13+
14+
# Required AbstractArray interface
15+
Base.size(vec::AbstractSmallVector) = throw(NotImplemented())
16+
17+
# Derived AbstractArray interface
18+
function Base.getindex(vec::AbstractSmallVector, index::Integer)
19+
return throw(NotImplemented())
20+
end
21+
function Base.setindex!(vec::AbstractSmallVector, item, index::Integer)
22+
return throw(NotImplemented())
23+
end
24+
Base.IndexStyle(::Type{<:AbstractSmallVector}) = IndexLinear()
25+
26+
function Base.convert(::Type{T}, a::AbstractArray) where {T<:AbstractSmallVector}
27+
return a isa T ? a : T(a)::T
28+
end

0 commit comments

Comments
 (0)