Skip to content

Commit eed6315

Browse files
Jakob Nybo Andersenjakobnissen
authored andcommitted
Move experiemental API to stable
1 parent 414ba85 commit eed6315

File tree

6 files changed

+129
-130
lines changed

6 files changed

+129
-130
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ not be mentioned here, because they do not impact how the package is to be used.
1212
- Using the inner constructor `MemoryView{T, M}(::Unsafe, ::MemoryRef{T}, ::Int)`
1313
was never documented API and is now removed.
1414

15+
* `Matrix` and other `Array` types with a different dimensionality than 1 is now
16+
`NotMemory`, since it is not equal to its own memory view, due to shape mismatch.
17+
1518
* `MemoryView(::SubArray)` now accepts fewer subarray types. However, it is unlikely
1619
that any instance that is now no longer accepted worked previously, so it is
1720
unlikely to be breaking in practice.
1821

1922
## Other
2023
* `parentindices` now works correctly for zero-sized structs.
24+
* `Base.memoryref(::MemoryView)` obtains the `MemoryRef` in a `MemoryView`.
2125

2226
## 0.3.5
2327
* Add method `MemoryKind{::Type{<:MemoryView}}`

docs/src/interfaces.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ my_hash(x) = my_hash(MemoryKind(typeof(x)), x)
6363
my_hash(::IsMemory{<:MemoryView{UInt8}}, x) = my_hash(ImmutableMemoryView(x))
6464

6565
# IsMemory with eltype other than UInt8 can't use the fast low-level function
66-
my_hash(T::IsMemory, x) = my_hash(NotMemory(), x)
66+
my_hash(::IsMemory, x) = my_hash(NotMemory(), x)
6767

6868
function my_hash(::NotMemory, x)
6969
# fallback implementation

src/MemoryViews.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ export MemoryView,
88
NotMemory,
99
inner,
1010
split_each,
11-
unsafe_from_parts
11+
unsafe_from_parts,
12+
split_first,
13+
split_last,
14+
split_at,
15+
split_unaligned
1216

1317
public Mutable, Immutable, DelimitedIterator
1418

@@ -207,7 +211,6 @@ MemoryKind(::Type{T}) where {T <: MemoryView} = IsMemory(T)
207211

208212
include("construction.jl")
209213
include("basic.jl")
210-
include("experimental.jl")
211214
include("delimited.jl")
212215
include("base_arrays.jl")
213216
include("io.jl")

src/base_arrays.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ function Base.Memory{T}(x::MemoryView{T}) where {T}
1414
end
1515
end
1616

17-
1817
function Base.copyto!(A::Union{Memory{T}, Array{T}}, mem::MemoryView{T}) where {T}
1918
copyto!(MemoryView(A), mem)
2019
return A

src/basic.jl

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,3 +404,122 @@ function Base.iterate(x::ReverseMemoryView, state = length(x))
404404
iszero(state) && return nothing
405405
return (@inbounds(x.mem[state]), state - 1)
406406
end
407+
408+
"""
409+
split_first(v::MemoryView{T}) -> Tuple{T, MemoryView{T}}
410+
411+
Return the first element of `v` and all other elements as a new memory view.
412+
413+
This function will throw a `BoundsError` if `v` is empty.
414+
415+
See also: [`split_last`](@ref)
416+
417+
# Examples
418+
```jldoctest
419+
julia> v = MemoryView([0x01, 0x02, 0x03]);
420+
421+
julia> split_first(v)
422+
(0x01, UInt8[0x02, 0x03])
423+
424+
julia> split_first(v[1:1])
425+
(0x01, UInt8[])
426+
427+
julia> split_first(v[1:0])
428+
ERROR: BoundsError: attempt to access 0-element MutableMemoryView{UInt8} at index [1]
429+
[...]
430+
```
431+
"""
432+
function split_first(v::MemoryView)
433+
@boundscheck checkbounds(v, 1)
434+
return (@inbounds(v[1]), @inbounds(truncate_start(v, 2)))
435+
end
436+
437+
"""
438+
split_last(v::MemoryView{T}) -> Tuple{T, MemoryView{T}}
439+
440+
Return the last element of `v` and all other elements as a new memory view.
441+
442+
This function will throw a `BoundsError` if `v` is empty.
443+
444+
See also: [`split_first`](@ref)
445+
446+
# Examples
447+
```jldoctest
448+
julia> v = MemoryView([0x01, 0x02, 0x03]);
449+
450+
julia> split_last(v)
451+
(0x03, UInt8[0x01, 0x02])
452+
453+
julia> split_last(v[1:1])
454+
(0x01, UInt8[])
455+
456+
julia> split_last(v[1:0])
457+
ERROR: BoundsError: attempt to access 0-element MutableMemoryView{UInt8} at index [1]
458+
[...]
459+
```
460+
"""
461+
function split_last(v::MemoryView)
462+
@boundscheck checkbounds(v, 1)
463+
return (@inbounds(v[end]), @inbounds(truncate(v, length(v) - 1)))
464+
end
465+
466+
"""
467+
split_at(v::T, i::Int) -> Tuple{T, T} where {T <: MemoryView}
468+
469+
Split a memory view into two at an index.
470+
471+
The first will contain all indices in `1:i-1`, the second `i:end`.
472+
This function will throw a `BoundsError` if `i` is not in `1:end+1`.
473+
474+
# Examples
475+
```jldocstest
476+
julia> split_at(MemoryView([1,2,3,4,5]), 2)
477+
([1], [2, 3, 4, 5])
478+
479+
julia> split_at(MemoryView(Int8[1, 2, 3]), 4)
480+
(Int8[1, 2, 3], Int8[])
481+
```
482+
"""
483+
function split_at(v::MemoryView, i::Int)
484+
@boundscheck checkbounds(1:(lastindex(v) + 1), i)
485+
return (@inbounds(truncate(v, i - 1)), @inbounds(truncate_start(v, i)))
486+
end
487+
488+
"""
489+
split_unaligned(v::T, ::Val{A}) -> Tuple{T, T} where {T <: MemoryView}
490+
491+
Split memory view `v` into two views `a` and `b`, where `a` is the smallest prefix of `v`
492+
that guarantees the starting memory address of `b` is is aligned to the integer value `A`.
493+
`A` must be a normal bit-integer, and a power of two in the range 1:64.
494+
495+
If `v` is empty or already aligned, `a` will be empty.
496+
If no elements of `v` is aligned, `b` will be empty and `a` will be equal to `v`.
497+
The element type of `v` must be a bitstype.
498+
499+
!!! warning
500+
When using this function, make sure to `GC.@preserve v`, to make sure Julia
501+
does not move `v` in memory.
502+
503+
# Examples:
504+
```
505+
julia> split_unaligned(MemoryView(Int16[1, 2, 3]), Val(8))
506+
(Int16[], Int16[1, 2, 3])
507+
508+
julia> split_unaligned(MemoryView(collect(0x01:0x20))[6:13], Val(8))
509+
(UInt8[0x06, 0x07, 0x08], UInt8[0x09, 0x0a, 0x0b, 0x0c, 0x0d])
510+
```
511+
"""
512+
function split_unaligned(v::MemoryView{T, M}, ::Val{A}) where {A, T, M}
513+
isbitstype(eltype(v)) || error("Alignment can only be computed for views of bitstypes")
514+
A isa Bits || error("Invalid alignment")
515+
in(A, (1, 2, 4, 8, 16, 32, 64)) || error("Invalid alignment")
516+
alignment = A % UInt
517+
mask = alignment - 1
518+
sz = Base.elsize(v)
519+
# Early return here to avoid division by zero: Size sz is statically known,
520+
# this will be compiled away
521+
iszero(sz) && return (unsafe_new_memoryview(M, v.ref, 0), v)
522+
unaligned_bytes = ((alignment - (UInt(pointer(v)) & mask)) & mask)
523+
n_elements = min(length(v), div(unaligned_bytes, sz % UInt) % Int)
524+
return @inbounds split_at(v, n_elements + 1)
525+
end

src/experimental.jl

Lines changed: 0 additions & 126 deletions
This file was deleted.

0 commit comments

Comments
 (0)