I came across in a code base # TODO this seems very clumsy to duplicate the loop code like this?
so I figured I'd give it a shot as a learning exercise. I'd like some feedback on what I came up with, particularly:
- Is this proper idiomatic Julia, or close? Or am I just writing Python in Julia?
- What explains the difference in allocations between the two approaches?
(Arguments used:[1,1], octaves=10
)Old: 0.000013 seconds (63 allocations: 1.062 KiB)
New: 0.000008 seconds (41 allocations: 1.500 KiB)
Thanks!
Original function:
# coords is [x] or [x, y] or [x, y, z] or [x, y, z, w]
function _octaves(coords::Array{T, 1} where T <: Real;
octaves::Int = 1,
persistence=1.0)
total = 0.0
frequency = 1.0
amplitude = 1.0
maxval = 0.0
# TODO this seems very clumsy to duplicate the loop code like this?
l = length(coords)
if l == 1
for i in 1:octaves
total += simplexnoise(coords[1] * frequency) * amplitude
maxval += amplitude
amplitude *= persistence
frequency *= 2
end
elseif l == 2
for i in 1:octaves
total += simplexnoise(coords[1] * frequency, coords[2] * frequency) * amplitude
maxval += amplitude
amplitude *= persistence
frequency *= 2
end
elseif l == 3
for i in 1:octaves
total += simplexnoise(coords[1] * frequency, coords[2] * frequency, coords[3] * frequency) * amplitude
maxval += amplitude
amplitude *= persistence
frequency *= 2
end
elseif l == 4
for i in 1:octaves
total += simplexnoise(coords[1] * frequency, coords[2] * frequency, coords[3] * frequency, coords[4] * frequency) * amplitude
maxval += amplitude
amplitude *= persistence
frequency *= 2
end
end
return total / maxval
end
And my refactor:
function _octaves(coords::Array{T, 1} where T <: Real;
octaves::Int = 1,
persistence=1.0)
total = 0.0
frequency = 1.0
amplitude = 1.0
maxval = 0.0
for _ in 1:octaves
inputs = coords .* frequency
total += simplexnoise(inputs...) * amplitude
maxval += amplitude
amplitude *= persistence
frequency *= 2
end
return total / maxval
end