3

is there a way to "metaprogrammatically" obtain a block of code with the following structure:

if r1 < R1
   s = 1

   elseif r1 < R2
      s = 2

      ... etc until N

   end
end

Thanks!

epx
  • 799
  • 4
  • 12
  • Check out `Base.Cartesian.@nif` – spencerlyon2 Sep 21 '16 at 14:54
  • 2
    But there is probably another (better?) way to achieve what you want. What are you trying to do? – David P. Sanders Sep 21 '16 at 15:43
  • @DavidP.Sanders Hola again David. (big fan here from Argentina)... What I want to do is "summarized" here: http://pastebin.com/2qYcBWfR I didn't want to post all that in here to make the question less confusing. But yeah, this is basically the kind of problem a chemical engineer student with no real programming background would find when doing its PhD around here. Thanks for the attention. – epx Sep 21 '16 at 17:52
  • Are you sure that your two pieces of code do the same thing? From pastebin, your `sample` function calculates the cumulative sums of `R`, while the unrolled version seems to just compare directly to the `R*` variables. A different point is that calling `rand()` actually has a significant cost. You may be able to speed things up by allocating a block `rand(N)` and then pulling samples from that. – DNF Sep 22 '16 at 11:08
  • One more thing (again referring to the code on Pastebin): Running the sampling `10^10` times with `length(R)`=14 takes roughly 4 minutes on my laptop. How can you shave more than half an hour off that? I think there must be something more going on. – DNF Sep 22 '16 at 11:33
  • @DNF Hey man, thanks for looking this up. Yes both functions do the same. I created this jupyter notebook to illustrate everything in a better way: https://nbviewer.jupyter.org/urls/dl.dropbox.com/s/76vwf9a2yjms1ee/reaction%20selection%20tests.ipynb Answering your questions: Yes, both function do the same thing. Calling rand() or rand(N) and pulling samples makes no difference in Julia. The number of iteration varies and its of the ^10 order (maybe even more), but there are many more calculations inside each iteration, that's why it takes more time too. – epx Sep 22 '16 at 14:27
  • Did you try using @inbounds with the array accesses? – David P. Sanders Sep 25 '16 at 18:32
  • In the array version in the notebook, replace the awful if else with R[selected ] = rand() ! – David P. Sanders Sep 25 '16 at 18:36
  • Yes, I tried using @inbounds (same results). And the reason that awful if-else block is there it's because in reality that block exists and inside each if there are a lot of things happening, for the purpose of this example all those calculations are irrelevant, but I wanted to keep both versions of the code (the one with local variables and vectorized) as equal as possible. That's why I left them both with the same structure. – epx Sep 25 '16 at 19:08

1 Answers1

5

Check out Base.Cartesian.@nif

I think this should work for you...

julia> macroexpand(:(@nif 10 d->(r1 < R_d) d->begin s=d; break end))
:(if r1 < R_1 # REPL[9], line 1:
        s = 1 # REPL[9], line 1:
        break
    else
        if r1 < R_2 # REPL[9], line 1:
            s = 2 # REPL[9], line 1:
            break
        else
            if r1 < R_3 # REPL[9], line 1:
                s = 3 # REPL[9], line 1:
                break
            else
                if r1 < R_4 # REPL[9], line 1:
                    s = 4 # REPL[9], line 1:
                    break
                else
                    if r1 < R_5 # REPL[9], line 1:
                        s = 5 # REPL[9], line 1:
                        break
                    else
                        if r1 < R_6 # REPL[9], line 1:
                            s = 6 # REPL[9], line 1:
                            break
                        else
                            if r1 < R_7 # REPL[9], line 1:
                                s = 7 # REPL[9], line 1:
                                break
                            else
                                if r1 < R_8 # REPL[9], line 1:
                                    s = 8 # REPL[9], line 1:
                                    break
                                else
                                    if r1 < R_9 # REPL[9], line 1:
                                        s = 9 # REPL[9], line 1:
                                        break
                                    else  # REPL[9], line 1:
                                        s = 10 # REPL[9], line 1:
                                        break
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end)
spencerlyon2
  • 9,476
  • 4
  • 30
  • 39