Skip to content

Commit

Permalink
eliminate StoredArray, rename DenseArray -> RegularArray (fix JuliaLa…
Browse files Browse the repository at this point in the history
…ng#6212, JuliaLang#987); UniformScaling is no longer an AbstractArray (JuliaLang#5810)
  • Loading branch information
stevengj committed Mar 24, 2014
1 parent c81664a commit ed1feae
Show file tree
Hide file tree
Showing 20 changed files with 87 additions and 79 deletions.
6 changes: 3 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ New language features
* Default "inner" constructors now accept any arguments. Constructors that
look like `MyType(a, b) = new(a, b)` can and should be removed ([#4026]).

* Expanded array type hierarchy, including ``StoredArray`` for all
container-like arrays, and ``DenseArray`` for in-memory arrays with
standard strided storage ([#987], [#2345]).
* Expanded array type hierarchy, including ``RegularArray`` for
in-memory arrays with standard strided storage ([#987], [#2345],
[#6212]).

* When reloading code, types whose definitions have not changed can be
ignored in some cases.
Expand Down
24 changes: 12 additions & 12 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ function squeeze(A::AbstractArray, dims)
reshape(A, d)
end

function copy!(dest::StoredArray, src)
function copy!(dest::AbstractArray, src)
i = 1
for x in src
dest[i] = x
Expand All @@ -174,7 +174,7 @@ end

# copy with minimal requirements on src
# if src is not an AbstractArray, moving to the offset might be O(n)
function copy!(dest::StoredArray, doffs::Integer, src, soffs::Integer=1)
function copy!(dest::AbstractArray, doffs::Integer, src, soffs::Integer=1)
st = start(src)
for j = 1:(soffs-1)
_, st = next(src, st)
Expand All @@ -191,13 +191,13 @@ end
# NOTE: this is to avoid ambiguity with the deprecation of
# copy!(dest::AbstractArray, src, doffs::Integer)
# Remove this when that deprecation is removed.
function copy!(dest::StoredArray, doffs::Integer, src::Integer)
function copy!(dest::AbstractArray, doffs::Integer, src::Integer)
dest[doffs] = src
return dest
end

# this method must be separate from the above since src might not have a length
function copy!(dest::StoredArray, doffs::Integer, src, soffs::Integer, n::Integer)
function copy!(dest::AbstractArray, doffs::Integer, src, soffs::Integer, n::Integer)
n == 0 && return dest
st = start(src)
for j = 1:(soffs-1)
Expand All @@ -212,7 +212,7 @@ function copy!(dest::StoredArray, doffs::Integer, src, soffs::Integer, n::Intege
end

# if src is an AbstractArray and a source offset is passed, use indexing
function copy!(dest::StoredArray, doffs::Integer, src::AbstractArray, soffs::Integer, n::Integer=length(src))
function copy!(dest::AbstractArray, doffs::Integer, src::AbstractArray, soffs::Integer, n::Integer=length(src))
for i = 0:(n-1)
dest[doffs+i] = src[soffs+i]
end
Expand Down Expand Up @@ -248,9 +248,9 @@ for (f,t) in ((:char, Char),
(:uint128,Uint128))
@eval begin
($f)(x::AbstractArray{$t}) = x
($f)(x::StoredArray{$t}) = x
($f)(x::AbstractArray{$t}) = x

function ($f)(x::StoredArray)
function ($f)(x::AbstractArray)
y = similar(x,$t)
i = 1
for e in x
Expand All @@ -266,9 +266,9 @@ for (f,t) in ((:integer, Integer),
(:unsigned, Unsigned))
@eval begin
($f){T<:$t}(x::AbstractArray{T}) = x
($f){T<:$t}(x::StoredArray{T}) = x
($f){T<:$t}(x::AbstractArray{T}) = x

function ($f)(x::StoredArray)
function ($f)(x::AbstractArray)
y = similar(x,typeof(($f)(one(eltype(x)))))
i = 1
for e in x
Expand Down Expand Up @@ -1228,7 +1228,7 @@ end


## 1 argument
function map_to!(f::Callable, first, dest::StoredArray, A::AbstractArray)
function map_to!(f::Callable, first, dest::AbstractArray, A::AbstractArray)
dest[1] = first
for i=2:length(A)
dest[i] = f(A[i])
Expand All @@ -1244,7 +1244,7 @@ function map(f::Callable, A::AbstractArray)
end

## 2 argument
function map_to!(f::Callable, first, dest::StoredArray, A::AbstractArray, B::AbstractArray)
function map_to!(f::Callable, first, dest::AbstractArray, A::AbstractArray, B::AbstractArray)
dest[1] = first
for i=2:length(A)
dest[i] = f(A[i], B[i])
Expand All @@ -1263,7 +1263,7 @@ function map(f::Callable, A::AbstractArray, B::AbstractArray)
end

## N argument
function map_to!(f::Callable, first, dest::StoredArray, As::AbstractArray...)
function map_to!(f::Callable, first, dest::AbstractArray, As::AbstractArray...)
n = length(As[1])
i = 1
ith = a->a[i]
Expand Down
25 changes: 12 additions & 13 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ typealias Vector{T} Array{T,1}
typealias Matrix{T} Array{T,2}
typealias VecOrMat{T} Union(Vector{T}, Matrix{T})

typealias DenseVector{T} DenseArray{T,1}
typealias DenseMatrix{T} DenseArray{T,2}
typealias DenseVecOrMat{T} Union(DenseVector{T}, DenseMatrix{T})

typealias StoredVector{T} StoredArray{T,1}
typealias StridedArray{T,N,A<:DenseArray} Union(DenseArray{T,N}, SubArray{T,N,A})
typealias StridedVector{T,A<:DenseArray} Union(DenseArray{T,1}, SubArray{T,1,A})
typealias StridedMatrix{T,A<:DenseArray} Union(DenseArray{T,2}, SubArray{T,2,A})
typealias RegularVector{T} RegularArray{T,1}
typealias RegularMatrix{T} RegularArray{T,2}
typealias RegularVecOrMat{T} Union(RegularVector{T}, RegularMatrix{T})

typealias StridedArray{T,N,A<:RegularArray} Union(RegularArray{T,N}, SubArray{T,N,A})
typealias StridedVector{T,A<:RegularArray} Union(RegularArray{T,1}, SubArray{T,1,A})
typealias StridedMatrix{T,A<:RegularArray} Union(RegularArray{T,2}, SubArray{T,2,A})
typealias StridedVecOrMat{T} Union(StridedVector{T}, StridedMatrix{T})

## Basic functions ##
Expand Down Expand Up @@ -689,7 +688,7 @@ end

## Unary operators ##

function conj!{T<:Number}(A::StoredArray{T})
function conj!{T<:Number}(A::AbstractArray{T})
for i=1:length(A)
A[i] = conj(A[i])
end
Expand Down Expand Up @@ -994,7 +993,7 @@ end
rotr90(A::AbstractMatrix, k::Integer) = rotl90(A,-k)
rot180(A::AbstractMatrix, k::Integer) = mod(k, 2) == 1 ? rot180(A) : copy(A)

# note: probably should be StridedVector or StoredVector
# note: probably should be StridedVector or AbstractVector
function reverse(A::AbstractVector, s=1, n=length(A))
B = similar(A)
for i = 1:s-1
Expand Down Expand Up @@ -1392,7 +1391,7 @@ _cumsum_type(v) = typeof(v[1]+v[1])
for (f, fp, op) = ((:cumsum, :cumsum_pairwise, :+),
(:cumprod, :cumprod_pairwise, :*) )
# in-place cumsum of c = s+v(i1:n), using pairwise summation as for sum
@eval function ($fp)(v::StoredVector, c::StoredVector, s, i1, n)
@eval function ($fp)(v::AbstractVector, c::AbstractVector, s, i1, n)
if n < 128
@inbounds c[i1] = ($op)(s, v[i1])
for i = i1+1:i1+n-1
Expand All @@ -1405,7 +1404,7 @@ for (f, fp, op) = ((:cumsum, :cumsum_pairwise, :+),
end
end

@eval function ($f)(v::StoredVector)
@eval function ($f)(v::AbstractVector)
n = length(v)
c = $(op===:+ ? (:(similar(v,_cumsum_type(v)))) :
(:(similar(v))))
Expand Down Expand Up @@ -1445,7 +1444,7 @@ for (f, fp, op) = ((:cumsum, :cumsum_pairwise, :+),
end

for (f, op) = ((:cummin, :min), (:cummax, :max))
@eval function ($f)(v::StoredVector)
@eval function ($f)(v::AbstractVector)
n = length(v)
cur_val = v[1]
res = similar(v, n)
Expand Down
2 changes: 1 addition & 1 deletion base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ num_bit_chunks(n::Int) = @_div64 (n+63)

# notes: bits are stored in contiguous chunks
# unused bits must always be set to 0
type BitArray{N} <: DenseArray{Bool, N}
type BitArray{N} <: RegularArray{Bool, N}
chunks::Vector{Uint64}
len::Int
dims::NTuple{N,Int}
Expand Down
7 changes: 3 additions & 4 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@
#end

#abstract AbstractArray{T,N}
#abstract StoredArray{T,N} <: AbstractArray{T,N}
#abstract DenseArray{T,N} <: StoredArray{T,N}
#abstract RegularArray{T,N} <: AbstractArray{T,N}

#type Array{T,N} <: DenseArray{T,N}
#type Array{T,N} <: RegularArray{T,N}
#end

#type Module
Expand Down Expand Up @@ -118,7 +117,7 @@ export
# key types
Any, DataType, Vararg, ANY, NTuple, None, Top,
Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, UnionType, Void,
AbstractArray, StoredArray, DenseArray,
AbstractArray, RegularArray,
# special objects
Box, Function, IntrinsicFunction, LambdaStaticData, Method, MethodTable,
Module, Nothing, Symbol, Task, Array,
Expand Down
2 changes: 1 addition & 1 deletion base/darray.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type DArray{T,N,A} <: StoredArray{T,N}
type DArray{T,N,A} <: AbstractArray{T,N}
dims::NTuple{N,Int}

chunks::Array{RemoteRef,N}
Expand Down
6 changes: 3 additions & 3 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export
Complex64,
Complex32,
DArray,
DenseMatrix,
DenseVecOrMat,
DenseVector,
RegularMatrix,
RegularVecOrMat,
RegularVector,
DevNull,
Diagonal,
Dict,
Expand Down
7 changes: 7 additions & 0 deletions base/linalg/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ size(D::Diagonal,d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? l
full(D::Diagonal) = diagm(D.diag)
getindex(D::Diagonal, i::Integer, j::Integer) = i == j ? D.diag[i] : zero(eltype(D.diag))

function getindex(D::Diagonal, i::Integer)
n = length(D.diag)
id = div(i-1, n)
id + id * n == i-1 && return D.diag[id+1]
zero(eltype(D.diag))
end

ishermitian(D::Diagonal) = true
issym(D::Diagonal) = true
isposdef(D::Diagonal) = all(D.diag .> 0)
Expand Down
4 changes: 3 additions & 1 deletion base/linalg/uniformscaling.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import Base: +, -, *, /, copy, ctranspose, getindex, showarray, transpose
import Base.LinAlg: SingularException
immutable UniformScaling{T<:Number} <: AbstractMatrix{T}
immutable UniformScaling{T<:Number}
λ::T
end

const I = UniformScaling(1)

eltype{T}(J::UniformScaling{T}) = T
ndims(J::UniformScaling) = 2
getindex(J::UniformScaling, i::Integer,j::Integer) = ifelse(i==j,J.λ,zero(J.λ))

showarray(io::IO,J::UniformScaling;kw...) = print(io,"$(typeof(J))\n$(J.λ)*I")
Expand Down
4 changes: 2 additions & 2 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,14 @@ eval(ngenerate(:N, nothing, :(setindex!{T}(s::SubArray{T,N}, v, ind::Integer)),

### from abstractarray.jl

@ngenerate N typeof(A) function fill!{T,N}(A::StoredArray{T,N}, x)
@ngenerate N typeof(A) function fill!{T,N}(A::AbstractArray{T,N}, x)
@nloops N i A begin
@inbounds (@nref N A i) = x
end
A
end

@ngenerate N typeof(dest) function copy!{T,N}(dest::StoredArray{T,N}, src::StoredArray{T,N})
@ngenerate N typeof(dest) function copy!{T,N}(dest::AbstractArray{T,N}, src::AbstractArray{T,N})
if @nall N d->(size(dest,d) == size(src,d))
@nloops N i dest begin
@inbounds (@nref N dest i) = (@nref N src i)
Expand Down
2 changes: 1 addition & 1 deletion base/sharedarray.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type SharedArray{T,N} <: DenseArray{T,N}
type SharedArray{T,N} <: RegularArray{T,N}
dims::NTuple{N,Int}
pids::Vector{Int}
refs::Array{RemoteRef}
Expand Down
6 changes: 3 additions & 3 deletions base/statistics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ function sturges(n) # Sturges' formula
iceil(log2(n))+1
end

function hist!{HT}(h::StoredArray{HT}, v::AbstractVector, edg::AbstractVector; init::Bool=true)
function hist!{HT}(h::AbstractArray{HT}, v::AbstractVector, edg::AbstractVector; init::Bool=true)
n = length(edg) - 1
length(h) == n || error("length(h) must equal length(edg) - 1.")
if init
Expand All @@ -166,7 +166,7 @@ hist(v::AbstractVector, edg::AbstractVector) = hist!(Array(Int, length(edg)-1),
hist(v::AbstractVector, n::Integer) = hist(v,histrange(v,n))
hist(v::AbstractVector) = hist(v,sturges(length(v)))

function hist!{HT}(H::StoredArray{HT,2}, A::AbstractMatrix, edg::AbstractVector; init::Bool=true)
function hist!{HT}(H::AbstractArray{HT,2}, A::AbstractMatrix, edg::AbstractVector; init::Bool=true)
m, n = size(A)
size(H) == (length(edg)-1, n) || error("Incorrect size of H.")
if init
Expand All @@ -184,7 +184,7 @@ hist(A::AbstractMatrix) = hist(A,sturges(size(A,1)))


## hist2d
function hist2d!{HT}(H::StoredArray{HT,2}, v::AbstractMatrix,
function hist2d!{HT}(H::AbstractArray{HT,2}, v::AbstractMatrix,
edg1::AbstractVector, edg2::AbstractVector; init::Bool=true)
size(v,2) == 2 || error("hist2d requires an Nx2 matrix.")
n = length(edg1) - 1
Expand Down
2 changes: 1 addition & 1 deletion base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

typealias RangeIndex Union(Int, Range{Int}, Range1{Int})

type SubArray{T,N,A<:StoredArray,I<:(RangeIndex...,)} <: StoredArray{T,N}
type SubArray{T,N,A<:AbstractArray,I<:(RangeIndex...,)} <: AbstractArray{T,N}
parent::A
indexes::I
dims::NTuple{N,Int}
Expand Down
2 changes: 1 addition & 1 deletion base/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ macro test_fails(ex)
:(@test_throws $ex)
end

approx_full(x::StoredArray) = x
approx_full(x::AbstractArray) = x
approx_full(x::Number) = x
approx_full(x) = full(x)

Expand Down
2 changes: 1 addition & 1 deletion contrib/julia-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
].* \\(in\\)\\(\\s-\\|$\\)+")

(defconst julia-font-lock-keywords
(list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|StoredArray\\|DenseArray\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Ranges\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" .
(list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|RegularArray\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Ranges\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" .
font-lock-type-face)
(cons
(concat "\\<\\("
Expand Down
36 changes: 22 additions & 14 deletions doc/manual/arrays.rst
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ Implementation
--------------

The base array type in Julia is the abstract type
``AbstractArray{T,n}``. It is parametrized by the number of dimensions
``n`` and the element type ``T``. ``AbstractVector`` and
``AbstractArray{T,N}``. It is parametrized by the number of dimensions
``N`` and the element type ``T``. ``AbstractVector`` and
``AbstractMatrix`` are aliases for the 1-d and 2-d cases. Operations on
``AbstractArray`` objects are defined using higher level operators and
functions, in a way that is independent of the underlying storage.
Expand All @@ -402,25 +402,33 @@ specific array implementation.
The ``AbstractArray`` type includes anything vaguely array-like, and
implementations of it might be quite different from conventional
arrays. For example, elements might be computed on request rather than
stored. Or, it might not be possible to assign or access every array
location.

``StoredArray`` is an abstract subtype of ``AbstractArray`` intended to
include all arrays that behave like memories: all elements are independent,
can be accessed, and (for mutable arrays) all elements can be assigned.
``DenseArray`` is a further abstract subtype of ``StoredArray``. Arrays of
this type have storage for every possible index, and provide uniform access
performance for all elements.

The ``Array{T,n}`` type is a specific instance of ``DenseArray``
stored. However, any concrete ``AbstractArray{T,N}`` type should
generally implement at least ``size(A)`` (returing an ``Int`` tuple),
``getindex(A,i)`` and ``getindex(A,i1,...,iN)`` (returning an element
of type ``T``); mutable arrays should also implement ``setindex!``. It
is recommended that these operations have nearly constant time complexity,
or technically Õ(1) complexity, as otherwise some array functions may
be unexpectedly slow.

``RegularArray`` is an abstract subtype of ``AbstractArray`` intended
to include all arrays that are laid out at regular offsets in memory,
and which can therefore be passed to external C and Fortran functions
expecting this memory layout. Subtypes should provide a method
``stride(A,k)`` that returns the "stride" of dimension ``k``:
increasing the index of dimension ``k`` by ``1`` should increase the
index ``i`` of ``getindex(A,i)`` by ``stride(A,k)``. If a
pointer conversion method ``convert(Ptr{T}, A)`` is provided, the
memory layout should correspond in the same way to these strides.

The ``Array{T,N}`` type is a specific instance of ``RegularArray``
where elements are stored in column-major order (see additional notes in
:ref:`man-performance-tips`). ``Vector`` and ``Matrix`` are aliases for
the 1-d and 2-d cases. Specific operations such as scalar indexing,
assignment, and a few other basic storage-specific operations are all
that have to be implemented for ``Array``, so that the rest of the array
library can be implemented in a generic manner.

``SubArray`` is a specialization of ``StoredArray`` that performs
``SubArray`` is a specialization of ``AbstractArray`` that performs
indexing by reference rather than by copying. A ``SubArray`` is created
with the ``sub`` function, which is called the same way as ``getindex`` (with
an array and a series of index arguments). The result of ``sub`` looks
Expand Down
3 changes: 1 addition & 2 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1048,8 +1048,7 @@ void jl_init_primitives(void)
add_builtin("Task", (jl_value_t*)jl_task_type);

add_builtin("AbstractArray", (jl_value_t*)jl_abstractarray_type);
add_builtin("StoredArray", (jl_value_t*)jl_storedarray_type);
add_builtin("DenseArray", (jl_value_t*)jl_densearray_type);
add_builtin("RegularArray", (jl_value_t*)jl_regulararray_type);
add_builtin("Array", (jl_value_t*)jl_array_type);

add_builtin("Expr", (jl_value_t*)jl_expr_type);
Expand Down
Loading

0 comments on commit ed1feae

Please sign in to comment.