Skip to content

Instantly share code, notes, and snippets.

@quinnj
Created July 31, 2014 12:53
Show Gist options
  • Save quinnj/8bdcab6d2f2a092f4835 to your computer and use it in GitHub Desktop.
Save quinnj/8bdcab6d2f2a092f4835 to your computer and use it in GitHub Desktop.
Macro-generated binary tree with if statements
# Recursively build binary search tree w/ known lookup values
# A is sorted array of lookup values
# R is return values for each index of A
# i.e. R[1] is returned for values < A[1], R[2] for < A[2], etc.
function searchsortedlasttree(A,R,var_name)
l = length(A)
mid = iseven(l) ? l>>>1 : (l>>>1)+1
# Handle base case
if mid == 1
if l == 1
return :($var_name < $(A[1]) ? $(R[1]) : $(R[2]))
else # l == 2
return :($var_name < $(A[1]) ? $(R[1]) :
$var_name < $(A[2]) ? $(R[2]) : $(R[3]))
end
end
iftree = Expr(:if)
iftree.args = Array(Any,3)
iftree.args[1] = :($var_name < $(A[mid])) # condition
iftree.args[2] = searchsortedlasttree(A[1:mid-1],R[1:mid],var_name)
iftree.args[3] = searchsortedlasttree(A[mid+1:end],R[mid+1:end],var_name)
return iftree
end
macro leapstree(a,r,var_name)
# var_name is the variable name that will be passed in thru the parent function
A = eval(a) # safe to eval here because 'a' is known at compile time
R = eval(r) # same here
ret = Expr(:block) # we'll store everything in a big block expression
# First we manually handle before and after the ends of our leaps array
push!(ret.args,:($var_name < $(A[1]) && return 0))
push!(ret.args,:($var_name >= $(A[end]) && return $(endof(A)*1000)))
# Now we call the recursive searchsortedlasttree to get the rest
push!(ret.args,searchsortedlasttree(A[2:(endof(A)-1)],R,var_name))
return ret
end
const SETLEAPS = [62214480000000,62230377600000,62261913600000, 62293449600000,62324985600000,62356608000000,62388144000000, 62419680000000,62451216000000,62498476800000,62530012800000, 62561548800000,62624707200000,62703676800000,62766835200000, 62798371200000,62845632000000,62877168000000,62908704000000, 62956137600000,63003398400000,63050832000000,63271756800000, 63366451200000,63476784000000]
function setleaps(ms)
# @leapstree as a macro ensures everything gets expanded
# at compile time
@leapstree(SETLEAPS,[1000:1000:((endof(SETLEAPS)-1)*1000)],ms)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment