Reference

The following provides detailed documentation about types and methods provided by the ArrayTools package. This information is also available from the REPL by typing ? followed by the name of a method or a type.

Broadcasting

ArrayTools.bcastlazyFunction
bcastlazy(A, [T=eltype(A),] dims...)

yields a flat array of type T and dimensions dims whose values are given by A according to type conversion and broadcasting rules (see broadcast method). Compared to bcastcopy, making a copy of A is avoided if it is already an array with the correct type of elements and dimensions or if it can be reshaped (by the reshape method) to the correct type and dimensions. This means that the result may share the same contents as A. Argument A can be a scalar or an array with 1-based indices. The result has 1-based indices and contiguous elements which is suitable for fast linear indexing.

See also bcastcopy, bcastsize.

ArrayTools.bcastcopyFunction
bcastcopy(A, [T=eltype(A),] dims...)

yields a new array of element type T and dimensions dims whose values are given by A according to type conversion and broadcasting rules (like for the broadcast method). Compared to bcastlazy, it is guaranteed that the returned array does not share its contents with A.

Argument A can be a scalar value or an array.

See also bcastlazy, bcastsize.

ArrayTools.bcastsizeFunction
bcastsize(size(A), size(B), ...) -> siz

yields the size siz of the array that would result from applying broadcasting rules (see broadcast method) to arguments A, B, etc. The result is a tuple of integers (of type Int). Call check_size if you want to also make sure that the result is a list of valid dimensions.

The method can also be applied to a single dimension:

bcastsize(a, b) -> c

to yield the dimension c gievn by broadcasting dimensions a and b throwing an exception if dimensions are not compatible according to broadcasting rules. This is the same as Base.Broadcasting._bcs1 but it takes care of converting to Int.

See also standard_size, check_size, bcastcopy, bcastlazy.

Indexing

ArrayTools.ArraySizeType
ArraySize

is the union of types eligible to define array size. Calling [to_size](@ref)(dims) on any argument dims such that isa(dims,ArraySize) is true yields an array size in canonical form, that is an instance of Dims{N} which is an alias for an N-tuple of Int.

ArrayTools.RubberIndexType

RubberIndex is the singleron type that represents any number of indices. The constant .. is defined as RubberIndex() and can be used in array indexation to left and/or right justify the other indices. For instance, assuming A is a 3×4×5×6 array, then all the following equalities hold:

A[..]           == A[:,:,:,:]
A[..,3]         == A[:,:,:,3]
A[2,..]         == A[2,:,:,:]
A[..,2:4,5]     == A[:,:,2:4,5]
A[2:3,..,1,2:4] == A[2:3,:,1,2:4]

As you can see, the advantage of the rubber index .. is that it automatically expands as the number of colons needed to have the correct number of indices. The expressions are also more readable.

The rubber index may also be used for setting values. For instance:

A[..] .= 1         # to fill A with ones
A[..,3] = A[..,2]  # to copy A[:,:,:,2] in A[:,:,:,3]
A[..,3] .= A[..,2] # idem but faster
A[2,..] = A[3,..]  # to copy A[3,:,:,:] in A[2,:,:,:]
A[..,2:4,5] .= 7   # to set all elements in A[:,:,2:4,5] to 7

Leading/trailing indices may be specified as Cartesian indices (of type CartesianIndex).

Warning

There are two known limitations:

  1. The end reserved word can only be used in intervals specified before the rubber index but not after. This limitation is due to the Julia parser cannot be avoided.
  2. At most 9 indices can be specified before the rubber index. This can be extended by editing the source code.

See also: colons.

ArrayTools.colonsFunction
colons(n)

yields a n-tuple of colons : (a.k.a. Colon()).

When n is known at compile time, it is faster to call:

colons(Val(n))

This method is suitable to extract sub-arrays of build views when some kind of rubber index is needed. For instance:

slice(A::AbstractArray{T,N}, i::Integer) where {T,N} =
    A[colons(Val(N-1))..., i]

defines a function that returns the i-th slice of A assuming index i refers the last index of A. Using the rubber-index .., a shorter definition is:

slice(A::AbstractArray, i) = A[.., i]

which is also able to deal with multiple trailing indices if i is a CartesianIndex.

See also: .., RubberIndex.

ArrayTools.IndexingTypeType
IndexingType(A)

yields one of the singletons FastIndexing() or AnyIndexing() to indicate whether or not array A has standard 1-based indices and can be efficiently indexed by one integer (even if A is multidimensional) and column-major ordering is used to access the elements of A.

This method can be extended for custom array types to quickly return the correct answer.

See also is_fast_array, to_fast_array.

ArrayTools.is_fast_arrayFunction
is_fast_array(A)

yields whether array A has standard 1-based indices and is efficiently indexed by linear indices.

Several arguments can be checked in a single call:

is_fast_array(A, B, C, ...)

is the same as:

is_fast_array(A) && is_fast_array(B) && is_fast_array(C) && ...

See also IndexingType, to_fast_array, is_flat_array.

ArrayTools.to_fast_arrayFunction
to_fast_array([T=eltype(A),] A)

lazily yields a fast array equivalent to A with element type T. A fast array has standard 1-based indices and is efficiently indexed by linear indices. If A is already a fast array with element type T, A is returned; otherwise, A is converted into an Array which is returned.

See also is_fast_array, IndexingType, to_flat_array.

ArrayTools.to_sizeFunction
to_size(dims)

converts dims to an instance of Dims{N} which is an alias for an N-tuple of Int. Argument dims can be a scalar integer or a tuple of integers. Argument dims is returned if already of the correct type. This method may also be called as:

to_size(dim1, dim2, ...)

to let to_size deal with a variable number of arguments.

The union ArraySize matches the types of acceptable argument(s) for to_size(arg): scalar integers and tuples of integers.

This method is intended for fast conversion, call check_size(dims) to verify that all dimensions in dims are nonnegative.

ArrayTools.check_sizeFunction
 check_size(dims) -> len

checks the validity of the array size dims and yields the corresponding number of elements (throwing an ArgumentError exception if this is not the case). To be a valid array size, the values of dims must all be nonnegative.

See also to_size.

ArrayTools.same_sizeFunction
same_size(A, B...) -> size(A)

checks whether arrays A, B, etc., all have the same size which is returned. A DimensionMismatch exception is thrown if array sizes are not all identical.

See also same_standard_size, same_axes.

ArrayTools.same_standard_sizeFunction
same_standard_size(A, B...) -> size(A)

checks whether arrays A, B, etc., all have standard indexing and the same size which is returned. If array sizes are not all identical, a DimensionMismatch exception is thrown. If arrays have non-standard indexing (that is indices not starting at index one), an ArgumentError exception is thrown.

See also standard_size, has_standard_indexing.

ArrayTools.same_axesFunction
same_axes(A, B...) -> axes(A)

checks whether arrays A, B, etc., have the same axes and returns them. A DimensionMismatch exception is thrown if axes are not all identical.

See also same_size, all_indices.

ArrayTools.@assert_same_axesMacro
@assert_same_axes A B ...

throws a DimensionMismatch exception if arrays A, B, etc. do not have the same axes.

ArrayTools.all_indicesFunction
all_indices(A...)

yields an iterable object for visiting each index of array(s) A in an efficient manner. For array types that have opted into fast linear indexing (like Array), this is simply the range 1:length(A). For other array types, return a specialized Cartesian range to efficiently index into the array(s) with indices specified for every dimension.

If more than one AbstractArray argument are supplied, all_indices will create an iterable object that is fast for all arguments (a UnitRange if all inputs have fast linear indexing, a CartesianIndices otherwise). A DimensionMismatch exception is thrown if the arrays have different axes so that it is always safe to use @inbounds in front of a loop like:

for i in all_indices(A, B, C, D) A[i] = B[i]*C[i] + D[i] end

when A, B etc. are all (abstract) arrays.

This method is similar to eachindex except that a DimensionMismatch exception is thrown if arrays have different axes. For linearly indexed arrays, eachindex only checks that they have the same linear index range (that is the same number of elements, not the same shape).

ArrayTools.cartesian_indicesFunction
cartesian_indices(A)
cartesian_indices((n1, n2, ...))
cartesian_indices((i1:j1, i2:j2, ...))
cartesian_indices(CartesianIndex(i1, i2, ...), CartesianIndex(j1, j2, ...))
cartesian_indices(R)

all yield an instance of CartesianIndices suitable for multi-dimensional indexing of respectively: all the indices of array A, a multi-dimensional array of dimensions (n1,n2,...), a multi-dimensional region whose first and last indices are (i1,i2,...) and (j1,j2,...) or a Cartesian region defined by R, an instance of CartesianIndices.

ArrayTools.common_indicesFunction

Assuming A and B are arrays with N dimensions:

common_indices(A, B) -> inds

yields the set of all the indices that are valid for both A and B. The result is similar to axes(A) or axes(B), that is an N-tuple of integer valued unit ranges.

An offset k with a sign may be specified:

common_indices(A, B, ±, k)

to obtain the set of all indices i such that A[i] and B[i ± k] are valid and where here and above ± is either + or -. Offset k can be a tuple of integers or a Cartesian index.

Arguments A and B may be both tuples of indices or index ranges or both scalar or index range which specify the size or the axes of the arrays to be indexed. This is used in the following example, where we want to do A[i] = B[i]*C[i + k] given the offset k and for all valid indices i:

I = common_indices(same_axes(A, B), axes(C), +, k)
@inbounds @simd for i in CartesianIndices(I)
   A[i] = B[i]*C[i + k]
end

Note that same_axes(A,B) is called to get the axes of A and B while asserting that they are the same, as a result no bound checking is necessary and the loop can be optimized for vectorization.

ArrayTools.has_standard_indexingFunction
has_standard_indexing(A)

return true if the indices of A start with 1 along all axes. Can be called with multiple arguments:

has_standard_indexing(A, B, ...)

is equivalent to:

has_standard_indexing(A) && has_standard_indexing(B) && ...

Opposite of Base.has_offset_axes which is not available in version of Julia older than 0.7.

Storage

ArrayTools.StorageTypeType
StorageType(A)

yields the type of storage of the elements of argument A. If A is a flat array, that is an array with contiguous elements in column-major order and first element at index 1, the singleton FlatStorage() is returned; otherwise, the singleton AnyStorage() is returned.

This method can be extended for custom array types to quickly return the correct answer.

See also is_flat_array, to_flat_array.

ArrayTools.is_flat_arrayFunction
is_flat_array(A) -> boolean

yields whether array A can be indexed as a flat array, that is an array with contiguous elements in column-major order and first element at index 1. This also means that A has 1-based indices along all its dimensions.

Several arguments can be checked in a single call:

is_flat_array(A, B, C, ...)

is the same as:

is_flat_array(A) && is_flat_array(B) && is_flat_array(C) && ...

See also StorageType, to_flat_array, is_fast_array, has_standard_indexing.

ArrayTools.to_flat_arrayFunction
to_flat_array([T=eltype(A),] A)

lazily yields a flat array based on A, that is an array with contiguous elements in column-major order and first element at index 1. Optional argument T is to specify the element type of the result. Argument A is returned if it is already a flat array with the requested element type; otherwise, convert method is called to produce the result (an Array{T} in that case).

See also is_flat_array, to_fast_array.

Pseudo-arrays

ArrayTools.PseudoArrays.PseudoArrayType

Abstract type PseudoArray{T,N,S} is to be derived by types that want to provide an array-like interface. Parameter T is the element type, parameter N is the number of dimensions and parameter S is the index style: IndexCartesian or IndexLinear.

Note

The indexing style must be part of the signature because it must be possible to call IndexStyle() on the data type not the instance. Another possibility would have been to have the type of the embedded array be part of the signature but this is more restrictive.

Alias LinearArray{T,N} is an abstract type that can be derived by types that want to provide an array-like interface with array values stored in an array whose index style is linear.

Usage can be as simple as:

struct CustomArray{T,N,...} <: LinearArray{T,N}
    arr::Array{T,N} # can be any array type with linear index style
    ...             # anything else
end

@inline Base.parent(A::CustomArray) = A.arr

As a result, instances of CustomArray{T,N} will be seen as instances of AbstractArray{T,N} and behave as if they implement linear indexing. Apart from the needs to extend the Base.parent method, the interface to LinearArray{T,N} should provide any necessary methods for indexation, getting the dimensions, the element type, etc. for the derived custom type. You may however override these definitions by more optimized or more suitable methods specialized for your custom array-like type.

Similarly, alias CartesianArray{T,N} is an abstract type that can be derived by types that want to provide an array-like interface with array values stored in an array whose index style is Cartesian. For such array-like object, index checking requires an efficient implementation of the Base.axes() method which you may have to specialize. The default implementation is:

@inline Base.axes(A::PseudoArray) = axes(parent(A))

Utilities

ArrayTools.all_matchFunction
all_match(val, f, args...) -> bool

yields as soon as possible (short-circuit) whether f(arg) == val for each argument arg in args.... The returned value is true if there are no arguments after f.

ArrayTools.allofFunction
allof(f, args...) -> Bool

checks whether predicate function f returns true for all arguments in args..., returning false as soon as possible (short-circuiting).

allof(args...) -> Bool

checks whether all arguments args... are true, returning false as soon as possible (short-circuiting). Arguments can be booleans or arrays of booleans. The latter are considered as true if all their elements are true and are considered as false otherwise (if any of their elements are false). Arguments can also be iterables to check whether all their values are true. An empty iterable is considered as true.

This method can be much faster than all(f, args) or all(args) because its result may be determined at compile time. However, missing values are not considered as special.

See also all, anyof, noneof.

ArrayTools.anyofFunction
anyof(f, args...) -> bool

checks whether predicate function f returns true for any argument args..., returning true as soon as possible (short-circuiting).

anyof(args...) -> bool

checks whether all arguments args... are true, returning false as soon as possible (short-circuiting). Arguments can be booleans or arrays of booleans. The latter are considered as true if any of their elements are true and are considered as false otherwise (if all their elements are false). Arguments can also be iterables to check whether any of their values are true. An empty iterable is considered as false.

This method can be much faster than any(f, args) or any(args) because its result may be determined at compile time. However, missing values are not considered as special.

See also any, allof, noneof.

ArrayTools.axis_limitsFunction
axis_limits(I) = (i0,i1)

yields the limits i0 and i1 of index range I as a 2-tuple of Int's and such that i0:i1 represents the same indices as I (although not in the same order if step(I) < 0). If step(I) is not equal to ±1, an ArgumentError exception is thrown.

ArrayTools.noneofFunction
noneof(f, args...) -> bool

checks whether predicate f returns false for all argument args..., while

noneof(args...) -> bool

checks whether all argument args... are false.

See also any, allof, noneof.

TypeUtils.promote_eltypeFunction
promote_eltype(args...)

yields the promoted element type of its arguments. Arguments args... may be anything implementing the eltype method.

ArrayTools.reversemapFunction
reversemap(f, args)

applies the function f to arguments args in reverse order and return the result. For now, the arguments args must be in the form of a simple tuple and the result is the tuple: (f(args[end]),f(args[end-1]),...,f(args[1]).

Also see: map, ntuple.

ArrayTools.split_intervalFunction
split_interval(I, J, +/-, k) -> Ia, Ib, Ic

given unit ranges I and J and offset ±k, yields 3 unit ranges, such that Ia ∪ Ib ∪ Ic = I and:

  • ∀ i ∈ Ia, i ± k < first(J);

  • ∀ i ∈ Ib, i ± k ∈ J;

  • ∀ i ∈ Ic, i ± k > last(J).

Unit ranges may be replaced by their first and last values:

split_interval(first(I), last(I), first(J), last(J), +/-, k)

yields the same result as above.

ArrayTools.strictmap!Function
strictmap!(f, dst, src) -> dst
strictmap!(dst, f, src) -> dst

does dst[i] = f(src[i]) for all indices i and returns dst. Arguments dst and src must have the same axes.

Except for the strict condition on the axes, this method is similar to map!(f,dst,src).