1

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
}
Carl Witthoft
  • 20,573
  • 9
  • 43
  • 73
  • 1
    Just as a convenience, would you mind linking directly to the code you want us to compare to? – Gregor Thomas Nov 07 '22 at 21:39
  • @GregorThomas the code is the source for the package link I provided. I'll add a link to the source tarball as well. – Carl Witthoft Nov 07 '22 at 21:52
  • 1
    Without digging so deep in the code, i can see, as you say, that an [environment](https://github.com/Skenvy/Collatz/blob/main/R/R/utils.R) here is storing known sequences. – Ric Nov 07 '22 at 21:53
  • 1
    And assuming you've seen this [collatz discussion - Rcpp v Base](https://stackoverflow.com/questions/52635518/collatz-conjecture-in-r). – Chris Nov 07 '22 at 22:36
  • Following the github link on the CRAN package page, [here's the relevant function on github](https://github.com/Skenvy/Collatz/blob/main/R/R/hailstone_sequence.R#L51) so folks can look at it without downloading the package. – Gregor Thomas Nov 07 '22 at 23:52
  • 1
    In fact, it's almost certainly the stored data. I compared the two funcs with an input of `fooint <-as.bigz('1111111111111111111111111111111111')` and my `collatz` function was faster! – Carl Witthoft Nov 08 '22 at 01:03
  • Is it faster in the long run, as `fooint` goes to 1K, 10K, 100K in `length(`? And I ask out of curiosity as I try to follow your `bigz` explorations and haplessly learn something. – Chris Nov 08 '22 at 01:23
  • @Chris I can run some `microbenchmark` tests & post up the results "soon" . Keep in mind that some very large numbers converge wicked fast, so it's important to pick a starting point that has a reasonably long sequence. – Carl Witthoft Nov 08 '22 at 15:47

1 Answers1

1

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"
Carl Witthoft
  • 20,573
  • 9
  • 43
  • 73