Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Cartesian to base #5387

Merged
merged 8 commits into from
Jan 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 0 additions & 202 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,6 @@ function squeeze(A::AbstractArray, dims)
reshape(A, d)
end

function fill!(A::AbstractArray, x)
for i = 1:length(A)
A[i] = x
end
return A
end

function copy!(dest::AbstractArray, src)
i = 1
for x in src
Expand Down Expand Up @@ -337,207 +330,12 @@ imag{T<:Real}(x::AbstractArray{T}) = zero(x)
\(A::Number, B::AbstractArray) = B ./ A
\(A::AbstractArray, B::Number) = B ./ A

./(x::AbstractArray, y::AbstractArray ) = throw(MethodError(./, (x,y)))
./(x::Number,y::AbstractArray ) = throw(MethodError(./, (x,y)))
./(x::AbstractArray, y::Number) = throw(MethodError(./, (x,y)))

.^(x::AbstractArray, y::AbstractArray ) = throw(MethodError(.^, (x,y)))
.^(x::Number,y::AbstractArray ) = throw(MethodError(.^, (x,y)))
.^(x::AbstractArray, y::Number) = throw(MethodError(.^, (x,y)))

## code generator for specializing on the number of dimensions ##

#otherbodies are the bodies that reside between loops, if its a 2 dimension array.
function make_loop_nest(vars, ranges, body)
otherbodies = cell(length(vars),2)
#println(vars)
for i = 1:2*length(vars)
otherbodies[i] = nothing
end
make_loop_nest(vars, ranges, body, otherbodies)
end

function make_loop_nest(vars, ranges, body, otherbodies)
expr = body
len = size(otherbodies)[1]
for i=1:length(vars)
v = vars[i]
r = ranges[i]
l = otherbodies[i]
j = otherbodies[i+len]
expr = quote
$l
for ($v) = ($r)
$expr
end
$j
end
end
expr
end


## genbodies() is a function that creates an array (potentially 2d),
## where the first element is inside the inner most array, and the last
## element is outside most loop, and all the other arguments are
## between each loop. If it creates a 2d array, it just means that it
## specifies what it wants to do before and after each loop.
## If genbodies creates an array it must of length N.
function gen_cartesian_map(cache, genbodies, ranges, exargnames, exargs...)
if ranges === ()
ranges = (1,)
end
N = length(ranges)
if !haskey(cache,N)
if isdefined(genbodies,:code)
mod = genbodies.code.module
else
mod = Main
end
dimargnames = { symbol(string("_d",i)) for i=1:N }
ivars = { symbol(string("_i",i)) for i=1:N }
bodies = genbodies(ivars)

## creating a 2d array, to pass as bodies
if isa(bodies,Array)
if (ndims(bodies)==2)
#println("2d array noticed")
body = bodies[1]
bodies = bodies[2:end,:]
elseif (ndims(bodies)==1)
#println("1d array noticed")
body = bodies[1]
bodies_tmp = cell(N,2)
for i = 1:N
bodies_tmp[i] = bodies[i+1]
bodies_tmp[i+N] = nothing
end
bodies = bodies_tmp
end
else
#println("no array noticed")
body = bodies
bodies = cell(N,2)
for i=1:2*N
bodies[i] = nothing
end
end
fexpr =
quote
local _F_
function _F_($(dimargnames...), $(exargnames...))
$(make_loop_nest(ivars, dimargnames, body, bodies))
end
_F_
end
f = eval(mod,fexpr)
cache[N] = f
else
f = cache[N]
end
return f(ranges..., exargs...)
end


# Generate function bodies which look like this (example for a 3d array):
# offset3 = 0
# stride1 = 1
# stride2 = stride1 * size(A,1)
# stride3 = stride2 * size(A,2)
# for i3 = ind3
# offset2 = offset3 + (i3-1)*stride3
# for i2 = ind2
# offset1 = offset2 + (i2-1)*stride2
# for i1 = ind1
# linearind = offset1 + i1
# <A function, "body", of linearind>
# end
# end
# end
function make_arrayind_loop_nest(loopvars, offsetvars, stridevars, linearind, ranges, body, arrayname)
# Initialize: calculate the strides
offset = offsetvars[end]
s = stridevars[1]
exinit = quote
$offset = 0
$s = 1
end
for i = 2:length(ranges)
sprev = s
s = stridevars[i]
exinit = quote
$exinit
$s = $sprev * size($arrayname, $i-1)
end
end
# Build the innermost loop (iterating over the first index)
v = loopvars[1]
r = ranges[1]
offset = offsetvars[1]
exloop = quote
for ($v) = ($r)
$linearind = $offset + $v
$body
end
end
# Build the remaining loops
for i = 2:length(ranges)
v = loopvars[i]
r = ranges[i]
offset = offsetvars[i-1]
offsetprev = offsetvars[i]
s = stridevars[i]
exloop = quote
for ($v) = ($r)
$offset = $offsetprev + ($v - 1) * $s
$exloop
end
end
end
# Return the combined result
return quote
$exinit
$exloop
end
end

# Like gen_cartesian_map, except it builds a function creating a
# loop nest that computes a single linear index (instead of a
# multidimensional index).
# Important differences:
# - genbody is a scalar-valued function of a single scalar argument,
# the linear index. In gen_cartesian_map, this function can return
# an array to specify "pre-loop" and "post-loop" operations, but
# here those are handled explicitly in make_arrayind_loop_nest.
# - exargnames[1] must be the array for which the linear index is
# being created (it is used to calculate the strides, which in
# turn are used for computing the linear index)
function gen_array_index_map(cache, genbody, ranges, exargnames, exargs...)
N = length(ranges)
if !haskey(cache,N)
dimargnames = { symbol(string("_d",i)) for i=1:N }
loopvars = { symbol(string("_l",i)) for i=1:N }
offsetvars = { symbol(string("_offs",i)) for i=1:N }
stridevars = { symbol(string("_stri",i)) for i=1:N }
linearind = :_li
body = genbody(linearind)
fexpr = quote
local _F_
function _F_($(dimargnames...), $(exargnames...))
$(make_arrayind_loop_nest(loopvars, offsetvars, stridevars, linearind, dimargnames, body, exargnames[1]))
end
return _F_
end
f = eval(fexpr)
cache[N] = f
else
f = cache[N]
end
return f(ranges..., exargs...)
end




## Indexing: getindex ##

Expand Down
Loading