convert_z <- function(z, bigz){
if (bigz){
return(gmp::as.bigz(z))
} else if (abs(z) < .Machine$integer.max) {
return(as.integer(z))
} else {
stop("Integer overflow. Consider the `bigz` argument.", call. = FALSE)
}
}
#' Calculate multinomial coefficient
#'
#' This function calculates the multinomial coefficient
#' \deqn{\frac{(\sum n_j)!}{\prod n_j!}.}{(\sum n_j)! / \prod n_j!.}
#' where \eqn{n_j}{n_j}'s are the number of multiplicities in the multiset.
#'
#' @param n a vector of group sizes
#' @param bigz use gmp's Big Interger
#' @return multinomial coefficient
#' @examples
#' # (3+1+1)!/ (3! 1! 1!) = 20
#' multichoose(c(3,1,1))
#' @export
multichoose <- function(n, bigz=FALSE){
out <- gmp::factorialZ(sum(n))
for (m in n) {
out <- gmp::as.bigz(out / gmp::factorialZ(m))
}
convert_z(out, bigz)
}
#' Calculate the number of r-permutations of a multiset
#' @param f the frequencies of the mutliset
#' @param r the number of object drawn from the multiset
#' @param bigz use gmp's Big Interger
#' @return the number of r-permutations (Big Integer from gmp)
#' @examples
#' x = c("a","a","b")
#' # possible permutations of size 2 are "aa", "ab" and "ba".
#' np_multiset(table(x), 2) # = 3
#' @export
np_multiset <- function(f, r, bigz=FALSE){
n <- sum(f)
if (r > n){
out <- 0
} else if (r == 0){
out <- 1
} else {
g <- gmp::factorialZ(0:min(r, max(f)))
p <- gmp::as.bigz(rep(0L, r + 1))
for (i in seq_along(f)){
if (i == 1){
p[[1:min(r + 1, f[i] + 1)]] <- gmp::factorialZ(r) / g[[1:min(r + 1, f[i] + 1)]]
}else{
for (j in r:1){
p[[j + 1]] <- sum(
p[[(j + 1):max(1, j + 1 - f[i])]] / g[[1:min(j + 1, f[i] + 1)]]
)
}
}
}
out <- p[[r + 1]]
}
convert_z(out, bigz)
}
#' Calculate the number of r-combinations of a multiset
#' @param f the frequencies of the mutliset
#' @param r the number of object drawn from the multiset
#' @param bigz use gmp's Big Interger
#' @return the number of combinations (Big Integer from gmp)
#' @examples
#' x <- c("a","a","b")
#' # possible combinations of size 2 are "aa" and "ab".
#' nc_multiset(table(x), 2) # <- 2
#' @export
nc_multiset <- function(f, r, bigz=FALSE){
n <- sum(f)
if (r > n){
out <- 0
} else if (r == 0){
out <- 1
} else {
p <- gmp::as.bigz(rep(0L, r + 1))
for (i in seq_along(f)){
if (i == 1){
p[[1:min(r + 1, f[i] + 1)]] <- 1
}else{
for (j in r:1){
p[[j + 1]] <- sum(p[[(j + 1):max(1, j + 1 - f[i])]])
}
}
}
out <- p[[r + 1]]
}
convert_z(out, bigz)
}
#' Wrap iterpc objects by iterators::iter
#' @param I the iterpc object
#' @param d number of permutation(s)/combination(s) wanted in each iteration, default to 1
#' @return a iter object compatible with iterators package
#' @examples
#' library(iterators)
#' I <- iterpc(5, 2)
#' it <- iter_wrapper(I)
#' nextElem(it)
#' nextElem(it)
#'
#' library(foreach)
#' I <- iterpc(5, 2)
#' it <- iter_wrapper(I)
#' foreach(x=it, .combine=c) %do% { sum(x) }
#' @export
iter_wrapper <- function(I, d=1){
iterators::iter(function() {
out <- getnext(I, d)
!is.null(out) || stop("StopIteration", call. = FALSE)
out
})
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.