Skip to content
This repository has been archived by the owner on Feb 9, 2020. It is now read-only.

Commit

Permalink
Support curly-brace notion for arithmetic on iteration-symbol indexes.
Browse files Browse the repository at this point in the history
…Fixes #3.
  • Loading branch information
timholy committed Oct 10, 2013
1 parent ae16136 commit 789b56e
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ gets translated into
A[i1+j1, i2+j2, i3+j3]
```

The `_` notation mimics the subscript notation of LaTeX; also like LaTeX, you
can use curly-braces to group sub-expressions. For example,
`d->p_{d-1}=p_d-1` generates `p2 = p3 - 1`.

## A complete example: implementing `imfilter`

With this, we have enough machinery to implement a simple multidimensional
Expand Down
18 changes: 13 additions & 5 deletions src/Cartesian.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ end

# ... using a shiftexpr, e.g., A[i1, i2+1, ...] with d->(d==2)?1:0
function _nrefshift(N::Int, A::Symbol, sym::Symbol, shiftexpr::Expr)
vars = [ popplus0(:($(namedvar(sym, i))+$(inlineanonymous(shiftexpr, i)))) for i = 1:N ]
vars = [ poparithmetic(:($(namedvar(sym, i))+$(inlineanonymous(shiftexpr, i)))) for i = 1:N ]
Expr(:escape, Expr(:ref, A, vars...))
end

Expand Down Expand Up @@ -248,8 +248,8 @@ function inlineanonymous(ex::Expr, val)
sym = ex.args[1]
ex = ex.args[2]
exout = replace(copy(ex), sym, val)
# Inline ternary expressions
exout = poplinenum(exout)
# Inline ternary expressions
if exout.head == :if
try
tf = eval(exout.args[1])
Expand Down Expand Up @@ -278,6 +278,11 @@ function replace(s::Symbol, sym::Symbol, val)
s
end
function replace(ex::Expr, sym::Symbol, val)
# Curly-brace notation
if ex.head == :curly && length(ex.args) == 2 && isa(ex.args[1], Symbol) && endswith(string(ex.args[1]), "_")
excurly = replace(ex.args[2], sym, val)
return symbol(string(ex.args[1])[1:end-1]*string(poparithmetic(excurly)))
end
for i in 1:length(ex.args)
ex.args[i] = replace(ex.args[i], sym, val)
end
Expand All @@ -295,9 +300,12 @@ function poplinenum(ex::Expr)
ex
end

# Perhaps the compiler does this?
function popplus0(ex::Expr)
if ex.head == :call && (ex.args[1] == :+ || ex.args[1] == :-) && ex.args[3] == 0
# This only handles simple stuff
function poparithmetic(ex::Expr)
if ex.head == :call && in(ex.args[1], (:+, :-, :*, :/)) && all([isa(ex.args[i], Number) for i = 2:length(ex.args)])
return eval(ex)
elseif ex.head == :call && (ex.args[1] == :+ || ex.args[1] == :-) && length(ex.args) == 3 && ex.args[3] == 0
# simplify x+0 and x-0
return ex.args[2]
end
ex
Expand Down
8 changes: 8 additions & 0 deletions test/testloops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ A2 = maxoverdims(A, 2)
@assert A2 == reshape(6:10,5,1)
@assert maxoverdims(A, (1,2)) == reshape([10], 1, 1)

# Curly-brace syntax: sum over the upper-triangle
A = reshape(1:16, 4, 4)
s = 0
Cartesian.@nloops 2 i d->d==2?(1:size(A,d)):(1:i_{d+1}) begin
s += Cartesian.@nref 2 A i
end
@assert s == sum(triu(A))

# @nref, @nrefshift, @nextract, and @nlookup
A = reshape(1:15, 3, 5)
i1 = 2
Expand Down

0 comments on commit 789b56e

Please sign in to comment.