Nothing
#' @rdname sumofsquares
#' @title Sum of Squared Integers
#' @aliases sum_sq
#' @description Decomposes an integer `n` into a sum of squared integers (\eqn{n = \sum_{i=1}^k x_i^2}; \eqn{1\leq x_i <n})
#' with \eqn{k\leq nmax}.
#' If `zerosum` is true then it is ensured that \eqn{\sum_{i=1}^k c_i x_i = 0} with \eqn{c_i=-1} or \eqn{c_i=+1}.
#' The computation of the \eqn{x_i}'s is limited by `maxt` seconds, which may result that not all possible
#' solutions are found. To reduce computing time, \code{rbind}'s in the function are replaced by allocating
#' matrices with \code{size} rows to fill in the results.
#' Note that the following data sets are available:
#' * \code{sos100=sumofsquares(100, 10, zerosum=TRUE, maxt=Inf)},
#' * \code{sos200=sumofsquares(200, 10, zerosum=TRUE, maxt=Inf)},
#' * \code{sos400=sumofsquares(400, 10, zerosum=TRUE, maxt=Inf)},
#' * \code{sos800=sumofsquares(800, 10, zerosum=TRUE, maxt=Inf)}, and
#' * \code{sos1000=sumofsquares(100, 10, zerosum=TRUE, maxt=Inf)}
#'
#' @param n integer: number to decompose as sum of squares
#' @param nmax integer: maximum number of squares in the sum
#' @param zerosum logical: should the solution sum up to one (default: \code{FALSE})
#' @param maxt numeric: maximal number of seconds the routine should run
#' @param size numeric: length of additional matrix size (default: \code{100000L})
#'
#' @md
#' @return A matrix with `nmax` column with \eqn{x_i}'s. \code{NA} means number has not been used.
#' @export
#'
#' @examples
#' sos <- sumofsquares(100, 6) # 23 solutions
#' head(sos)
#' table(rowSums(!is.na(sos)))
#' # one solution with one or two x_i
#' # five solutions with four x_i
#' # six solutions with five x_i
#' # ten solutions with six x_i
#' rowSums(sos^2, na.rm=TRUE) # all 100
#' sos <- sumofsquares(100, 6, zerosum=TRUE)
#' head(sos)
#' rowSums(sos^2, na.rm=TRUE) # all 100
#' rowSums(sos, na.rm=TRUE) # all 0
sumofsquares <- function(n, nmax=10, zerosum=FALSE, maxt=30, size=100000L) {
#browser()
stopifnot(nmax>3)
smax <- floor(sqrt(n))
smin <- ceiling(sqrt(n)/nmax)
sos <- matrix(NA_integer_, nrow=size, ncol=nmax+1)
nsos <- (smax-smin+1)
sos[1:nsos,1] <- n-(smax:smin)^2
sos[1:nsos,2] <- smax:smin
i <- 1
t <- as.numeric(Sys.time())
while(i<=nrow(sos)) {
if ((i%%1000)==0) {
# cat(sprintf("%.0f/%.0f/%0.f\n", i, nsos, nsos-i))
if ((as.numeric(Sys.time())-t)>maxt) break
}
ni <- sos[i,1]
if (is.na(ni)) break
if (ni>0) {
nas <- is.na(sos[i,])
if (any(nas)) {
col <- min(which(nas))
smax <- min(sos[i,col-1], floor(sqrt(ni)))
smin <- 1 # floor(sqrt(ni/(nmax-col)))
if (smin==smax) {
sosi <- sos[i,]
sosi[col] <- smin
sosi[1] <- n-sum(sosi[-1]^2, na.rm=TRUE)
if (nrow(sos)==nsos) sos <- rbind(sos, matrix(NA_integer_, nrow=size, ncol=nmax+1))
nsos <- nsos+1
sos[nsos,] <- sosi
}
if (smin<smax) {
sosi <- t(t(rep(1, smax-smin+1))) %*% sos[i,]
sosi[,col] <- sample(smax:smin)
sosi[,1] <- n-rowSums(sosi[,-1]^2, na.rm=TRUE)
if (nrow(sos)<nsos+nrow(sosi)) sos <- rbind(sos, matrix(NA_integer_, nrow=size, ncol=nmax+1))
sos[nsos+(1:nrow(sosi)),] <- sosi
nsos <- nsos+nrow(sosi)
}
}
}
i <- i+1
}
full <- i>nsos
sos <- sos[1:nsos,]
#browser()
sos <- sos[sos[,1]==0,-1]
if (zerosum) {
soszero <- matrix(0, nrow=size, ncol=ncol(sos))
nsoszero <- 0
sos[is.na(sos)] <- 0
bits <- sapply(0:((2^nmax)-1), intToBits)
ones <- matrix(-1, nrow=nrow(bits), ncol=ncol(bits))
ones[bits>0] <- +1
ones <- ones[1:nmax,]
#browser()
msum <- sos%*%ones
ind <- which(msum==0, arr.ind = TRUE)
if (length(ind)) {
for (i in 1:nrow(ind)) {
sosi <- sos[ind[i,1],]*ones[,ind[i,2]]
#browser()
if (nrow(soszero)==nsoszero) soszero <- rbind(soszero, matrix(0, nrow=size, ncol=ncol(sos)))
nsoszero <- nsoszero+1
soszero[nsoszero,] <- sosi
}
}
sos <- soszero
sos <- sos[1:nsoszero,]
sos[sos==0] <- NA_integer_
}
sos <- t(apply(sos, 1, sort, na.last=TRUE))
sos <- sos[!duplicated(sos),]
attr(sos, "full") <- full
sos
}
#' @rdname sumofsquares
#' @export
# sum_sq <- function(...){
# sumofsquares(...)}
sum_sq <- sumofsquares
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.