diff --git a/base/array.jl b/base/array.jl index 7644748427d6db..fc75d6d17ca7b2 100644 --- a/base/array.jl +++ b/base/array.jl @@ -220,6 +220,19 @@ linspace(start::Real, stop::Real) = linspace(start, stop, 100) logspace(start::Real, stop::Real, n::Integer) = 10.^linspace(start, stop, n) logspace(start::Real, stop::Real) = logspace(start, stop, 50) + +arrayslice(A, i::Int, n::Int) = arrayslice(A, i, (n,)) +arrayslice(A, dims::Tuple, n::Tuple) = arrayslice(A, sub2ind(size(A),dims...), n) +arrayslice(A, dims::Tuple, n::Int) = arrayslice(A, dims, (n,)) +function arrayslice{T, N}(A::Array{T}, i::Int, n::NTuple{N,Int}) + len = prod(n) + @assert 0 < i <= length(A) + @assert 0 <= len + @assert i-1+len <= length(A) + ccall(:jl_slice_owned_array, Array{T,N}, (Any, Any, Any, Uint), + Array{T,N}, A, n, uint(i-1)) +end + ## Conversions ## convert{T,n}(::Type{Array{T}}, x::Array{T,n}) = x diff --git a/base/exports.jl b/base/exports.jl index 176c0626844b00..53291a840cfce7 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -491,6 +491,7 @@ export zeta, # arrays + arrayslice, bitbroadcast, broadcast!, broadcast!_function, diff --git a/doc/helpdb.jl b/doc/helpdb.jl index 61bbb25100b681..cf734a0621f8bf 100644 --- a/doc/helpdb.jl +++ b/doc/helpdb.jl @@ -5964,6 +5964,15 @@ popdisplay(d::Display) "), +("Base","arrayslice","arrayslice(A, pos, dims) + + Create an array of size \"dims\" with the data shared with the + given array. The returned array uses the contiguous memory of + \"A\" starting at \"pos\" to \"prod(dims)\". The \"pos\" and + \"dims\" arguments may be tuple or integer arguments. + +"), + ("Base","broadcast","broadcast(f, As...) Broadcasts the arrays \"As\" to a common size by expanding diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 3b6405d7c91d2e..0f1fcf29c48c05 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -4104,6 +4104,11 @@ Constructors Construct a vector of ``n`` logarithmically-spaced numbers from ``10^start`` to ``10^stop``. +.. function:: arrayslice(A, pos, dims) + + Create an array of size ``dims`` with the data shared with the given array. The returned array uses the contiguous memory of ``A`` starting at ``pos`` to ``prod(dims)``. The ``pos`` and ``dims`` arguments may be tuple or integer arguments. + + Mathematical operators and functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/array.c b/src/array.c index ad661ab80dc15a..81f5f120b91f70 100644 --- a/src/array.c +++ b/src/array.c @@ -293,6 +293,64 @@ jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_tuple_t *dims, return a; } +jl_array_t *jl_slice_owned_array(jl_value_t *atype, jl_array_t *data, jl_tuple_t *dims, size_t offset) +{ + size_t i; + jl_array_t *a; + size_t ndims = jl_tuple_len(dims); + + int ndimwords = jl_array_ndimwords(ndims); + a = (jl_array_t*)allocobj((sizeof(jl_array_t) + sizeof(void*) + ndimwords*sizeof(size_t) + 15)&-16); + a->type = atype; + a->ndims = ndims; + a->offset = 0; + a->data = NULL; + a->isaligned = data->isaligned; + jl_value_t *el_type = jl_tparam0(atype); + if (store_unboxed(el_type)) { + a->elsize = jl_datatype_size(el_type); + a->ptrarray = 0; + } + else { + a->elsize = sizeof(void*); + a->ptrarray = 1; + } + JL_GC_PUSH1(&a); + + jl_array_data_owner(a) = (jl_value_t*)data; + a->how = 3; + a->data = (data->data) + offset*(a->elsize); + a->isshared = 1; + data->isshared = 1; + + if (ndims == 1) { + size_t l = jl_unbox_long(jl_tupleref(dims,0)); +#ifdef STORE_ARRAY_LEN + a->length = l; +#endif + a->nrows = l; + a->maxsize = l; + } + else { + size_t *adims = &a->nrows; + size_t l=1; + wideint_t prod; + for(i=0; i < ndims; i++) { + adims[i] = jl_unbox_long(jl_tupleref(dims, i)); + prod = (wideint_t)l * (wideint_t)adims[i]; + if (prod > (wideint_t) MAXINTVAL) + jl_error("invalid Array dimensions"); + l = prod; + } +#ifdef STORE_ARRAY_LEN + a->length = l; +#endif + } + JL_GC_POP(); + + return a; +} + jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims) { size_t ndims = jl_tuple_len(dims); diff --git a/src/julia.h b/src/julia.h index e6734b21f2f892..0b5a5c0818c8f0 100644 --- a/src/julia.h +++ b/src/julia.h @@ -735,6 +735,8 @@ DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer); DLLEXPORT jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_tuple_t *dims, int own_buffer); +DLLEXPORT jl_array_t *jl_slice_owned_array(jl_value_t *atype, jl_array_t *data, + jl_tuple_t *dims, size_t offset); int jl_array_store_unboxed(jl_value_t *el_type); DLLEXPORT jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr); diff --git a/test/arrayops.jl b/test/arrayops.jl index bce81a01b13712..1db13e90da3d70 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -695,6 +695,23 @@ begin @test size(n1) == (6,1,4) && size(n2) == (6,3,1) && size(n3) == (2,6,1) end +# arrayslice +x = rand(3,5) +y = arrayslice(x,7,(3,3)) +y[:] *= 5 +x[7:end] = y[:]*2 +@test reshape(x[7:end],(3,3)) == y +y = arrayslice(x,1,4) +@test Array{eltype(x),1} == typeof(y) +@test length(y) == 4 +y = arrayslice(x,1,0) +@test y == eltype(y)[] +y = arrayslice(x,(1,3),2) +@test y[1] == x[1,3] +y = arrayslice(x,(3,1),(1,2)) +@test y[:] == x[3:4] +y = arrayslice(x,1,(5,3)) +@test reshape(x,(5,3)) == y # single multidimensional index let