I wrote the code below to calculate Collatz sequences. The basic algorithm steps are nearly identical to the code used in the library "collatz" available at CRAN. (the source tarball is here ) However, my hack code runs 10 to 50 times slower than the library's hailstone_sequence
function.
I'm at a loss as to why, unless perhaps storing re-used constants via lockBinding
makes a difference. Can anyone take a look at the two sets of code and suggest what is causing the difference? I've looked at the results of running Rprof
and there's nothing obvious there.
{{ my code follows}}
collatz<-function(x, div=2, mul=3, add= 1, maxKnown=1, maxiter = 1000) {
y <- as.bigz(x[1]) #silent dumping
maxKnown <- as.bigz(floor(maxKnown))
cyclic = FALSE
for (jj in 2:maxiter) {
y[[jj]] <- collatz_fun(y[[jj-1]],div,mul,add)
# bigz/bigz returns a bigq even if that bigq has denominator 1
# so we do a divq, "%/%", instead of div, to just get the bigz.
if (y[[jj]] <= maxKnown ) break
if(any(y[[jj]] == y[[1:(jj-1)]])) {
cyclic = TRUE
break
}
}
if (jj >= maxiter) warning('not converged (yet)')
return(invisible(list(y = y, div = div, mul=mul, add= add, cyclic = cyclic) ) )
}
collatz_fun <- function(n, d, m, a){
if (n%%d ==0 ) ( n %/% d ) else (m*n) a
}
CodePudding user response:
Turns out I was fooling myself! For a few specific starting values, e.g., 737 , hailstone_sequence
is faster. However, in general my "collatz" code is faster. Here's a table showing the tictoc times (in milliseconds) for random numbers of increasing size.
Collatz, ms hailstone, ms start
[1,] "2" "2" "89"
[2,] "7" "8" "505"
[3,] "10" "13" "4760"
[4,] "5" "8" "46125"
[5,] "57" "89" "706047"
[6,] "52" "77" "7426598"
[7,] "114" "179" "71693193"
[8,] "76" "128" "195808257"
[9,] "75" "111" "4082229980"
[10,] "89" "133" "29816905510"
[11,] "56" "86" "850451975896"
[12,] "240" "390" "5056177278457"
[13,] "179" "288" "23497279632257"
[14,] "133" "217" "667081939494479"
[15,] "183" "286" "8724848384524922"
[16,] "126" "199" "20376642404589490"
[17,] "175" "271" "195397921609459067"
[18,] "96" "146" "9068592584569983840"
[19,] "203" "317" "98435723276783667011"
[20,] "189" "288" "906945269554050299597"
[21,] "586" "934" "1942663519120549652842"
[22,] "288" "414" "32708032219025335530871"
[23,] "331" "459" "815908776331672807666938"
[24,] "379" "581" "6894029370205376937364345"
[25,] "811" "1182" "49809117889125237920557852"
[26,] "415" "605" "583415680232489269692462895"
[27,] "559" "793" "9220767227146002168685568453"
[28,] "733" "1082" "60679473842196546847954821109"
[29,] "894" "1228" "698657027947326650828429401951"
[30,] "1320" "1932" "8336688931823299843178876023479"