Search code examples
rvectorizationfactorialgmp

Is it possible to Vectorize functions that output bigz objects?


I suspect that there must be some way, for example gmp's factorialZ seems pre-vectorized:

> library(gmp)
> factorialZ(0:9)
Big Integer ('bigz') object of length 10:
 [1] 1      1      2      6      24     120    720    5040   40320  362880

and it appears to be comfortable being used with base R functions that take a vector input and give vector output

> cumsum(factorialZ(0:9))
Big Integer ('bigz') object of length 10:
 [1] 1      2      4      10     34     154    874    5914   46234  409114

However, probably because of coercion, attempting to Vectorize a function that outputs bigZ objects will be met with horrible failure:

leftFactorial<-function(n)
{
  sum(factorialZ(0:(n-1)))
}
> Vectorize(leftFactorial)(1:10)
  [1] 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 01 00 00
 [36] 00 01 00 00 00 01 00 00 00 04 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 0a 00 00 00 01 00 00 00 01 00
 [71] 00 00 01 00 00 00 22 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 9a 00 00 00 01 00 00 00 01 00 00 00 01
[106] 00 00 00 6a 03 00 00 01 00 00 00 01 00 00 00 01 00 00 00 1a 17 00 00 01 00 00 00 01 00 00 00 01 00 00 00
[141] 9a b4 00 00 01 00 00 00 01 00 00 00 01 00 00 00 1a 3e 06 00

So what should we do when we want to Vectorize a function that outputs bigZ objects?


Solution

  • dput allows to visualize the internal structure of a bigZ object : a vector of raw

    > dput(factorialZ(0:9))
    structure(as.raw(c(0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
    0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 
    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 
    0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 
    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
    0xd0, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
    0x00, 0xb0, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 
    0x00, 0x00, 0x80, 0x9d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 
    0x00, 0x00, 0x00, 0x80, 0x89, 0x05, 0x00)), class = "bigz")
    

    Using Vectorize with SIMPLIFY = TRUE results in a simplified vector of raw objects.

    As noted in comments, SIMPLIFY = FALSE works because it keeps the original Big Integer type:

    Vectorize(leftFactorial, SIMPLIFY = FALSE)(1:10)
    
    [[1]]
    Big Integer ('bigz') :
    [1] 1
    
    [[2]]
    Big Integer ('bigz') :
    [1] 2
    
    [[3]]
    Big Integer ('bigz') :
    [1] 4
    
    [[4]]
    Big Integer ('bigz') :
    [1] 10
    
    [[5]]
    Big Integer ('bigz') :
    [1] 34
    
    [[6]]
    Big Integer ('bigz') :
    [1] 154
    
    [[7]]
    Big Integer ('bigz') :
    [1] 874
    
    [[8]]
    Big Integer ('bigz') :
    [1] 5914
    
    [[9]]
    Big Integer ('bigz') :
    [1] 46234
    
    [[10]]
    Big Integer ('bigz') :
    [1] 409114