Some thing like this:
proc fn(foo: baked[bool]) =
...
when foo:
...
proc fn(true)
Maybe using the type system?
I am trying to gain maximum performance and my code is kind of complex. But lets simplify it to a loop like this:
proc simpleLoop(foo: bool, bar: bool, baz: int) =
var s = newSeq[int](1000)
for i in 0 ..< s.len:
# some complex logic
if foo:
if bar or baz > 10:
s[i] = 1
else:
if baz < 10:
s[i] = 2
I am doing a ton of ifs and inside the loop. I would like to remove them outside of the loop:
proc invertLoop(foo: bool, bar: bool, baz: int) =
var s = newSeq[int](1000)
if foo:
if bar or baz > 10:
for i in 0 ..< s.len:
# some complex logic
s[i] = 1
else:
if baz < 10:
for i in 0 ..< s.len:
# some complex logic
s[i] = 2
But then I am doing some complex logic twice or more!
There is a trick you can do with template to speed up code by baking the parameters at compile time:
template staticLoop(foo: bool, bar: bool, baz: int) =
var s = newSeq[int](1000)
for i in 0 ..< s.len:
# some complex logic
when foo:
when bar or baz > 10:
s[i] = 1
else:
when baz < 10:
s[i] = 2
We are back to our simpler loop. But how do we call it? We have to have if or switch statements!
if foo == false and bar == false and baz == 0: staticLoop(false, false, 0)
if foo == true and bar == false and baz == 0: staticLoop(true, false, 0)
if foo == true and bar == true and baz == 0: staticLoop(true, true, 0)
if foo == false and bar == true and baz == 0: staticLoop(false, true, 0)
My question is is there a way to bake that in so that nim does that work for me? Some thing like?
proc simpleLoop(foo: baked[bool], bar: baked[bool], baz: baked[int]) =
var s = newSeq[int](1000)
for i in 0 ..< s.len:
# some complex logic
if foo:
if bar or baz > 10:
s[i] = 1
else:
if baz < 10:
s[i] = 2
Thanks!
For the purposes of code generation, all static params are treated as generic params - the proc will be compiled separately for each unique supplied value (or combination of values).
Yes! The static[bool] and static[enum] is exactly what I want. Great feature!
Thank you for answering!
Hmm after working with it a bit. Yes I can use static yes, but it really does what template does already. I wish nim would dispatch dynamic variables into static procs.
proc run(on: static[bool]) =
discard
var v = true
run(v)
I get error: v is type bool but it wants static[bool]
Instead I have to do:
if v == true: run(true)
elif v == false: run(false)
Maybe I could write a macro...
It would use if/case statements.
See here: https://github.com/treeform/pixie/blob/master/src/pixie/images.nim#L834
My huge if-case tree that calls 92 static versions of my single function.
This quest for speed let me down the path of shaving a few branches here and there.
What monstrosity is that? Why not just do
drawUberStatic(a, b, c, start, stepX, stepY, lines, blendMode, true, false)
I hope this gets the point accross.
type
Mat = object
a: array[10, array[20, int]]
proc apply(m: var Mat; op: proc (x: var int)) =
# callback style
for i in 0..<10:
for j in 0..<20:
op(m.a[i][j])
var m: Mat
apply m, (proc (x: var int) = inc x, 2)
template applyT(m: var Mat; op: untyped) =
# template style
for i in 0..<10:
for j in 0..<20:
op(m.a[i][j])
template opInc(x) = inc x, 2
applyT m, opInc