#############################################################################
# This function is used to match up a vector of column names to the
# entire set of column names, providing the proper column indices.
# The name choice was based on the phrase "multiple map" though
# perhaps we should have made a different choice.
mmap = function(x, y) {
if (is.null(x)) return(NULL)
ans <- match(x, y)
if (any(is.na(ans))) stop("Couldn't find a match to one of the arguments.")
return(ans)
}
checkReadOnly <- function(x)
{
if (is.readonly(x)) {
stop("you may not modify a read-only big.matrix object")
}
}
#############################################################################
setClass('big.matrix', representation(address='externalptr'))
setClass('descriptor', representation(description='list'))
setClass('big.matrix.descriptor', contains='descriptor')
# Here, x is a big.matrix, and the result is a descriptor.
# Here, x is a descriptor, and the result is the description which is
# the relevant data needed for the attach.
setGeneric('description', function(x) standardGeneric('description'))
setMethod('describe', signature(x='big.matrix'),
function(x)
{
return(new('big.matrix.descriptor', description=DescribeBigMatrix(x)))
})
big.matrix <- function(nrow, ncol, type=options()$bigmemory.default.type,
init=NULL, dimnames=NULL, separated=FALSE,
backingfile=NULL, backingpath=NULL, descriptorfile=NULL,
binarydescriptor=FALSE, shared=TRUE)
{
if (!is.null(backingfile))
{
if (!shared) warning("All filebacked objects are shared.")
return(filebacked.big.matrix(nrow=nrow, ncol=ncol, type=type, init=init,
dimnames=dimnames, separated=separated,
backingfile=backingfile, backingpath=backingpath,
descriptorfile=descriptorfile,
binarydescriptor=binarydescriptor))
}
if (nrow < 1 | ncol < 1)
stop('A big.matrix must have at least one row and one column')
typeVal <- NULL
if (type == 'integer') typeVal <- 4
if (type == 'double') typeVal <- 8
if (type == 'short') typeVal <- 2
if (type == 'char') typeVal <- 1
if (is.null(typeVal)) stop('invalid type')
if (!is.null(dimnames)) {
rownames <- dimnames[[1]]
colnames <- dimnames[[2]]
} else {
rownames <- NULL
colnames <- NULL
}
if (is.null(init)) init <- NA
if (shared) {
address <- .Call('CreateSharedMatrix', as.double(nrow),
as.double(ncol), as.character(colnames), as.character(rownames),
as.integer(typeVal), as.double(init), as.logical(separated))
} else {
address <- .Call('CreateLocalMatrix', as.double(nrow),
as.double(ncol), as.character(colnames), as.character(rownames),
as.integer(typeVal), as.double(init), as.logical(separated))
}
if (is.null(address)) {
stop(paste("Error: memory could not be allocated for instance",
"of type big.matrix"))
}
x <- new("big.matrix", address=address)
if (is.null(x)) {
stop("Error encountered when creating instance of type big.matrix")
}
return(x)
}
setGeneric('is.big.matrix', function(x) standardGeneric('is.big.matrix'))
setMethod('is.big.matrix', signature(x='big.matrix'),
function(x) return(TRUE))
setMethod('is.big.matrix', definition=function(x) return(FALSE))
setGeneric('as.big.matrix',
function(x, type=NULL, separated=FALSE,
backingfile=NULL, backingpath=NULL,
descriptorfile=NULL, binarydescriptor=FALSE, shared=TRUE) standardGeneric('as.big.matrix'))
setMethod('as.matrix', signature(x='big.matrix'),
function(x) return(x[,]))
setMethod('as.big.matrix', signature(x='matrix'),
function(x, type, separated, backingfile, backingpath, descriptorfile,
binarydescriptor, shared)
{
if (!is.numeric(x)) {
warning("Casting to numeric type")
x <- matrix(as.numeric(x), nrow=nrow(x), dimnames=dimnames(x))
}
if (is.null(type)) type <- typeof(x)
if (type=="integer" | type=="double" | type=="short" | type=="char")
{
y <- big.matrix(nrow=nrow(x), ncol=ncol(x), type=type,
init=NULL, dimnames=dimnames(x), separated=separated,
backingfile=backingfile, backingpath=backingpath,
descriptorfile=descriptorfile, binarydescriptor=binarydescriptor,
shared=shared)
y[1:nrow(x),1:ncol(x)] <- x
junk <- gc()
} else stop('bigmemory: that type is not implemented.')
return(y)
})
setMethod('as.big.matrix', signature(x='data.frame'),
function(x, type, separated, backingfile, backingpath, descriptorfile,
binarydescriptor, shared)
{
warning("Coercing data.frame to matrix via factor level numberings.")
if (is.null(type)) type <- options()$bigmemory.default.type
if (type=="integer" | type=="double" | type=="short" | type=="char")
{
y <- big.matrix(nrow=nrow(x), ncol=ncol(x), type=type,
init=NULL, dimnames=dimnames(x), separated=separated,
backingfile=backingfile, backingpath=backingpath,
descriptorfile=descriptorfile, binarydescriptor=binarydescriptor,
shared=shared)
oldbtw <- options()$bigmemory.typecast.warning
options(bigmemory.typecast.warning=FALSE)
for (i in 1:ncol(x)) {
if (is.character(x[,i])) x[,i] <- factor(x[,i])
if (is.factor(x[,i])) x[,i] <- as.numeric(x[,i])
y[,i] <- x[,i]
}
options(bigmemory.typecast.warning=oldbtw)
junk <- gc()
} else stop('bigmemory: that type is not implemented.')
return(y)
})
setMethod('as.big.matrix', signature(x='vector'),
function(x, type, separated, backingfile, backingpath, descriptorfile,
binarydescriptor, shared)
{
if (!is.numeric(x)) {
warning("Casting to numeric type")
x <- as.numeric(x)
}
x <- matrix(x, length(x), 1)
warning("Coercing vector to a single-column matrix.")
return(as.big.matrix(x, type, separated, backingfile,
backingpath, descriptorfile, binarydescriptor, shared))
})
colnames.bm <- function(x)
{
ret <- .Call("GetColumnNamesBM", x@address)
if (length(ret)==0) return(NULL)
return(ret)
}
rownames.bm <- function(x)
{
ret <- .Call("GetRowNamesBM", x@address)
if (length(ret)==0) return(NULL)
return(ret)
}
assign('colnames.bm<-',
function(x, value) {
checkReadOnly(x)
if (is.character(value)) {
if (any(value=="")) {
stop("empty strings prohibited in column names")
}
} else {
if (!is.null(value)) {
value <- as.character(value)
warning("column names coerced to character")
}
}
if (!is.null(value) & length(value) != ncol(x))
stop("length of 'colnames' not equal to array extent.")
.Call("SetColumnNames", x@address, value)
return(x)
})
assign('rownames.bm<-',
function(x,value) {
checkReadOnly(x)
if (is.character(value)) {
if (any(value=="")) {
stop("empty strings prohibited in row names")
}
} else {
if (!is.null(value)) {
value <- as.character(value)
warning("row names coerced to character")
}
}
if (length(value) != nrow(x) & !is.null(value))
stop("length of 'rownames' not equal to array extent.")
.Call("SetRowNames", x@address, value)
return(x)
})
setMethod('ncol', signature(x="big.matrix"),
function(x) return(.Call("CGetNcol", x@address)))
setMethod('nrow', signature(x="big.matrix"),
function(x) return(.Call("CGetNrow", x@address)))
setMethod('dim', signature(x="big.matrix"),
function(x) return(c(nrow(x), ncol(x))))
setMethod('length', signature(x="big.matrix"),
function(x) return(prod(dim(x))))
GetElements.bm <- function(x, i, j, drop=TRUE)
{
if (!is.numeric(i) & !is.character(i) & !is.logical(i))
stop("row indices must be numeric, logical, or character vectors.")
if (!is.numeric(j) & !is.character(j) & !is.logical(j))
stop("column indices must be numeric, logical, or character vectors.")
if (is.character(i))
if (is.null(rownames(x))) stop("row names do not exist.")
else i <- mmap(i, rownames(x))
if (is.character(j))
if (is.null(colnames(x))) stop("column names do not exist.")
else j <- mmap(j, colnames(x))
if (is.logical(i)) {
if (length(i) != nrow(x))
stop("row vector length must match the number of rows of the matrix.")
i <- which(i)
}
if (is.logical(j)) {
if (length(j) != ncol(x))
stop(paste("column vector length must match the number of",
"columns of the matrix."))
j <- which(j)
}
tempi <- .Call("CCleanIndices", as.double(i), as.double(nrow(x)))
if (is.null(tempi[[1]])) stop("Illegal row index usage in extraction.\n")
if (tempi[[1]]) i <- tempi[[2]]
tempj <- .Call("CCleanIndices", as.double(j), as.double(ncol(x)))
if (is.null(tempj[[1]])) stop("Illegal column index usage in extraction.\n")
if (tempj[[1]]) j <- tempj[[2]]
retList <- .Call("GetMatrixElements", x@address, as.double(j), as.double(i))
mat = .addDimnames(retList, length(i), length(j), drop)
return(mat)
}
# Function contributed by Peter Haverty at Genentech.
GetIndivElements.bm <- function(x,i) {
# Check i
if (is.logical(i)) {
stop("Logical indices not allowed when subsetting by a matrix.")
}
if (ncol(i) != 2) {
stop("When subsetting with a matrix, it must have two columns.")
}
if (is.character(i)) {
if (is.null(rownames(x))) stop("row names do not exist.")
if (is.null(colnames(x))) stop("column names do not exist.")
i <- matrix(c(mmap(i[,1], rownames(x)), mmap(i[,2], colnames(x))), ncol=2)
}
tempi <- .Call("CCleanIndices", as.double(i[,1]), as.double(nrow(x)))
if (is.null(tempi[[1]])) stop("Illegal row index usage in assignment.\n")
if (tempi[[1]]) i[,1] <- tempi[[2]]
tempj <- .Call("CCleanIndices", as.double(i[,2]), as.double(ncol(x)))
if (is.null(tempj[[1]])) stop("Illegal column index usage in assignment.\n")
if (tempj[[1]]) i[,2] <- tempj[[2]]
# Call .Call C++
return(.Call("GetIndivMatrixElements", x@address, as.double(i[,2]),
as.double(i[,1])))
}
GetCols.bm <- function(x, j, drop=TRUE)
{
if (!is.numeric(j) & !is.character(j) & !is.logical(j))
stop("column indices must be numeric, logical, or character vectors.")
if (is.character(j))
if (is.null(colnames(x))) stop("column names do not exist.")
else j <- mmap(j, colnames(x))
if (is.logical(j)) {
if (length(j) != ncol(x))
stop(paste("column vector length must match the number of",
"columns of the matrix."))
j <- which(j)
}
tempj <- .Call("CCleanIndices", as.double(j), as.double(ncol(x)))
if (is.null(tempj[[1]])) stop("Illegal column index usage in extraction.\n")
if (tempj[[1]]) j <- tempj[[2]]
retList <- .Call("GetMatrixCols", x@address, as.double(j))
mat = .addDimnames(retList, nrow(x), length(j), drop)
return(mat)
}
GetRows.bm <- function(x, i, drop=TRUE)
{
if (!is.numeric(i) & !is.character(i) & !is.logical(i))
stop("row indices must be numeric, logical, or character vectors.")
if (is.character(i))
if (is.null(rownames(x))) stop("row names do not exist.")
else i <- mmap(i, rownames(x))
if (is.logical(i)) {
if (length(i) != nrow(x))
stop("row vector length must match the number of rows of the matrix.")
i <- which(i)
}
tempi <- .Call("CCleanIndices", as.double(i), as.double(nrow(x)))
if (is.null(tempi[[1]])) stop("Illegal row index usage in extraction.\n")
if (tempi[[1]]) i <- tempi[[2]]
retList <- .Call("GetMatrixRows", x@address, as.double(i))
mat = .addDimnames(retList, length(i), ncol(x), drop)
return(mat)
}
GetAll.bm <- function(x, drop=TRUE)
{
retList <- .Call("GetMatrixAll", x@address)
mat = .addDimnames(retList, nrow(x), ncol(x), drop)
return(mat)
}
setMethod("[",
signature(x = "big.matrix", drop = "missing"),
function(x, i, j) return(GetElements.bm(x, i, j)))
setMethod("[",
signature(x = "big.matrix", drop = "logical"),
function(x, i, j, drop) return(GetElements.bm(x, i, j, drop)))
setMethod("[",
signature(x = "big.matrix", i="missing", drop = "missing"),
function(x, j) return(GetCols.bm(x, j)))
setMethod("[",
signature(x = "big.matrix", i="missing", drop = "logical"),
function(x, j, drop) return(GetCols.bm(x, j, drop)))
setMethod("[",
signature(x = "big.matrix", j="missing", drop = "missing"),
function(x, i) return(GetRows.bm(x, i)))
setMethod("[",
signature(x = "big.matrix", j="missing", drop = "logical"),
function(x, i, drop) return(GetRows.bm(x, i, drop)))
setMethod("[",
signature(x = "big.matrix", i="missing", j="missing", drop = "missing"),
function(x) return(GetAll.bm(x)))
setMethod("[",
signature(x = "big.matrix", i="missing", j="missing", drop = "logical"),
function(x, drop) return(GetAll.bm(x, drop)))
# Function contributed by Peter Haverty at Genentech.
setMethod('[',
signature(x = "big.matrix",i="matrix",j="missing",drop="missing"),
function(x, i) return(GetIndivElements.bm(x, i)))
SetElements.bm <- function(x, i, j, value)
{
checkReadOnly(x)
if (!is.numeric(i) & !is.character(i) & !is.logical(i))
stop("row indices must be numeric, logical, or character vectors.")
if (!is.numeric(j) & !is.character(j) & !is.logical(j))
stop("column indices must be numeric, logical, or character vectors.")
if (is.character(i))
if (is.null(rownames(x))) stop("row names do not exist.")
else i <- mmap(i, rownames(x))
if (is.character(j))
if (is.null(colnames(x))) stop("column names do not exist.")
else j <- mmap(j, colnames(x))
if (is.logical(i)) {
if (length(i) != nrow(x))
stop("row vector length must match the number of rows of the matrix.")
i <- which(i)
}
if (is.logical(j)) {
if (length(j) != ncol(x))
stop(paste("column vector length must match the number of",
"columns of the matrix."))
j <- which(j)
}
tempi <- .Call("CCleanIndices", as.double(i), as.double(nrow(x)))
if (is.null(tempi[[1]])) stop("Illegal row index usage in assignment.\n")
if (tempi[[1]]) i <- tempi[[2]]
tempj <- .Call("CCleanIndices", as.double(j), as.double(ncol(x)))
if (is.null(tempj[[1]])) stop("Illegal column index usage in assignment.\n")
if (tempj[[1]]) j <- tempj[[2]]
if ( options()$bigmemory.typecast.warning &&
((typeof(value) == "double") && (typeof(x) != "double") ||
(typeof(value) == "integer" &&
(typeof(x) != "double" && typeof(x) != "integer"))) )
{
warning(cat("Assignment will down cast from ", typeof(value), " to ",
typeof(x), "\nHint: To remove this warning type: ",
"options(bigmemory.typecast.warning=FALSE)\n", sep=''))
}
totalts <- length(i) * length(j)
# If we are assigning from a matrix, make sure the dimensions agree.
if (is.matrix(value))
{
if (ncol(value) != length(j) | nrow(value) != length(i))
{
stop("Matrix dimensions do not agree with big.matrix instance set size.")
}
} else if (length(value) != totalts) {
# Otherwise, make sure we are assigning the correct number of things
# (rep if necessary)
numReps <- totalts / length(value)
if (numReps != round(numReps))
{
stop(paste("number of items to replace is not a multiple of",
"replacement length"))
}
}
if (typeof(x) != 'double') {
integerVals = na.omit(as.integer(value))
if ( sum(integerVals == na.omit(as.integer(value))) !=
length(integerVals) | is.factor(value))
{
warning("non-integer (possibly Inf or -Inf) typecast to integer")
}
}
# Note: we pass doubles as doubles, but anything else as integers.
if (typeof(x) == 'double') {
.Call("SetMatrixElements", x@address, as.double(j), as.double(i),
as.double(value))
} else {
.Call("SetMatrixElements", x@address, as.double(j), as.double(i),
as.integer(value))
}
return(x)
}
SetIndivElements.bm <- function(x, i, value) {
# Check i
checkReadOnly(x)
if (is.logical(i)) {
stop("Logical indices not allowed when subsetting by a matrix.")
}
if (ncol(i) != 2) {
stop("When subsetting with a matrix, it must have two columns.")
}
if (is.character(i)) {
if (is.null(rownames(x))) stop("row names do not exist.")
if (is.null(colnames(x))) stop("column names do not exist.")
i <- matrix(c(mmap(i[,1], rownames(x)), mmap(i[,2], colnames(x))), ncol=2)
}
tempi <- .Call("CCleanIndices", as.double(i[,1]), as.double(nrow(x)))
if (is.null(tempi[[1]])) stop("Illegal row index usage in assignment.\n")
if (tempi[[1]]) i[,1] <- tempi[[2]]
tempj <- .Call("CCleanIndices", as.double(i[,2]), as.double(ncol(x)))
if (is.null(tempj[[1]])) stop("Illegal column index usage in assignment.\n")
if (tempj[[1]]) i[,2] <- tempj[[2]]
# Check value length, rep as necessary
if (length(value) > nrow(i) || nrow(i) %% length(value) != 0) {
stop("number of items to replace is not a multiple of replacement length")
}
if (length(value) < nrow(i)) {
value = rep(value, nrow(i) %/% length(value))
}
# Give typecast warning if necessary
if ( options()$bigmemory.typecast.warning &&
((typeof(value) == "double") && (typeof(x) != "double") ||
(typeof(value) == "integer" &&
(typeof(x) != "double" && typeof(x) != "integer"))) )
{
warning(cat("Assignment will down cast from ", typeof(value), " to ",
typeof(x), "\nHint: To remove this warning type: ",
"options(bigmemory.typecast.warning=FALSE)\n", sep=''))
}
# Call appropriate .Call C++
if (typeof(x) == 'double') {
.Call("SetIndivMatrixElements", x@address, as.double(i[,2]),
as.double(i[,1]), as.double(value))
} else {
.Call("SetIndivMatrixElements", x@address, as.double(i[,2]),
as.double(i[,1]), as.integer(value))
}
return(x)
}
SetCols.bm <- function(x, j, value)
{
checkReadOnly(x)
if (!is.numeric(j) & !is.character(j) & !is.logical(j))
stop("column indices must be numeric, logical, or character vectors.")
if (is.character(j))
if (is.null(colnames(x))) stop("column names do not exist.")
else j <- mmap(j, colnames(x))
if (is.logical(j)) {
if (length(j) != ncol(x))
stop(paste("column vector length must match the number of",
"columns of the matrix."))
j <- which(j)
}
tempj <- .Call("CCleanIndices", as.double(j), as.double(ncol(x)))
if (is.null(tempj[[1]])) stop("Illegal column index usage in extraction.\n")
if (tempj[[1]]) j <- tempj[[2]]
if ( options()$bigmemory.typecast.warning &&
((typeof(value) == "double") && (typeof(x) != "double") ||
(typeof(value) == "integer" &&
(typeof(x) != "double" && typeof(x) != "integer"))) )
{
warning(cat("Assignment will down cast from ", typeof(value), " to ",
typeof(x), "\nHint: To remove this warning type: ",
"options(bigmemory.typecast.warning=FALSE)\n", sep=''))
}
totalts <- nrow(x) * length(j)
# If we are assigning from a matrix, make sure the dimensions agree.
if (is.matrix(value)){
if (ncol(value) != length(j) | nrow(value) != nrow(x))
{
stop("Matrix dimensions do not agree with big.matrix instance set size.")
}
}
else if (length(value) != totalts)
{
# Otherwise, make sure we are assigning the correct number of things
# (rep if necessary)
numReps <- totalts / length(value)
if (numReps != round(numReps)) {
stop(paste("number of items to replace is not a multiple of",
"replacement length"))
}
}
if (typeof(x) != 'double') {
integerVals = na.omit(as.integer(value))
if ( sum(integerVals == na.omit(as.integer(value))) !=
length(integerVals) | is.factor(value)) {
warning("non-integer (possibly Inf or -Inf) typecast to integer")
}
}
# Note: we pass doubles as doubles, but anything else as integers.
if (typeof(x) == 'double')
{
.Call("SetMatrixCols", x@address, as.double(j), as.double(value))
}
else
{
.Call("SetMatrixCols", x@address, as.double(j), as.integer(value))
}
return(x)
}
SetRows.bm <- function(x, i, value)
{
checkReadOnly(x)
if (!is.numeric(i) & !is.character(i) & !is.logical(i))
stop("row indices must be numeric, logical, or character vectors.")
if (is.character(i))
if (is.null(rownames(x))) stop("row names do not exist.")
else i <- mmap(i, rownames(x))
if (is.logical(i)) {
if (length(i) != nrow(x))
stop("row vector length must match the number of rows of the matrix.")
i <- which(i)
}
tempi <- .Call("CCleanIndices", as.double(i), as.double(nrow(x)))
if (is.null(tempi[[1]])) stop("Illegal row index usage in extraction.\n")
if (tempi[[1]]) i <- tempi[[2]]
if ( options()$bigmemory.typecast.warning &&
((typeof(value) == "double") && (typeof(x) != "double") ||
(typeof(value) == "integer" &&
(typeof(x) != "double" && typeof(x) != "integer"))) )
{
warning(cat("Assignment will down cast from ", typeof(value), " to ",
typeof(x), "\nHint: To remove this warning type: ",
"options(bigmemory.typecast.warning=FALSE)\n", sep=''))
}
# Note: i may be a mwhich statement in which case we _must_ ensure
# that we disable read locking before it is evaluated or we will
# have a race condition. - Jay and Mike.
totalts <- length(i) * ncol(x)
# If we are assigning from a matrix, make sure the dimensions agree.
if (is.matrix(value))
{
if (ncol(value) != ncol(x) | nrow(value) != length(i))
{
stop("Matrix dimensions do not agree with big.matrix instance set size.")
}
}
else if (length(value) != totalts)
{
# Otherwise, make sure we are assigning the correct number of things
# (rep if necessary)
numReps <- totalts / length(value)
if (numReps != round(numReps))
{
stop(paste("number of items to replace is not a multiple of",
"replacement length"))
}
}
if (typeof(x) != 'double')
{
integerVals <- na.omit(as.integer(value))
if ( sum(integerVals == na.omit(as.integer(value))) !=
length(integerVals) | is.factor(value)) {
warning("non-integer (possibly Inf or -Inf) typecast to integer")
}
}
# Note: we pass doubles as doubles, but anything else as integers.
if (typeof(x) == 'double') {
.Call("SetMatrixRows", x@address, as.double(i), as.double(value))
}
else
{
.Call("SetMatrixRows", x@address, as.double(i), as.integer(value))
}
return(x)
}
SetAll.bm <- function(x, value)
{
checkReadOnly(x)
if ( options()$bigmemory.typecast.warning &&
((typeof(value) == "double") && (typeof(x) != "double") ||
(typeof(value) == "integer" &&
(typeof(x) != "double" && typeof(x) != "integer"))) )
{
warning(cat("Assignment will down cast from ", typeof(value), " to ",
typeof(x), "\nHint: To remove this warning type: ",
"options(bigmemory.typecast.warning=FALSE)\n", sep=''))
}
totalts <- nrow(x) * ncol(x)
# If we are assigning from a matrix, make sure the dimensions agree.
if (is.matrix(value))
{
if (ncol(value) != ncol(x) | nrow(value) != nrow(x))
{
stop("Matrix dimensions do not agree with big.matrix instance set size.")
}
}
else if (length(value) != totalts)
{
# Otherwise, make sure we are assigning the correct number of things
# (rep if necessary)
numReps <- totalts / length(value)
if (numReps != round(numReps)) {
stop(paste("number of items to replace is not a multiple of",
"replacement length"))
}
}
if (typeof(x) != 'double')
{
integerVals = na.omit(as.integer(value))
if ( sum(integerVals == na.omit(as.integer(value))) !=
length(integerVals) | is.factor(value))
{
warning("non-integer (possibly Inf or -Inf) typecast to integer")
}
}
# Note: we pass doubles as doubles, but anything else as integers.
if (typeof(x) == 'double')
{
.Call("SetMatrixAll", x@address, as.double(value))
}
else
{
.Call("SetMatrixAll", x@address, as.integer(value))
}
return(x)
}
setMethod('[<-',
signature(x = "big.matrix"),
function(x, i, j, value) return(SetElements.bm(x, i, j, value)))
setMethod('[<-',
signature(x = "big.matrix", i="missing"),
function(x, j, value) return(SetCols.bm(x, j, value)))
setMethod('[<-',
signature(x = "big.matrix", j="missing"),
function(x, i, value) return(SetRows.bm(x, i, value)))
setMethod('[<-',
signature(x = "big.matrix", i="missing", j="missing"),
function(x, value) return(SetAll.bm(x, value)))
# Function contributed by Peter Haverty at Genentech.
setMethod('[<-',
signature(x = "big.matrix",i="matrix",j="missing"),
function(x, i, value) return(SetIndivElements.bm(x, i, value)))
setMethod('typeof', signature(x="big.matrix"),
function(x) return(.Call('GetTypeString', x@address)))
setMethod('head', signature(x="big.matrix"),
function(x, n = 6) {
n <- min(as.integer(n), nrow(x))
if (n<1 | n>nrow(x)) stop("n must be between 1 and nrow(x)")
return(x[1:n,])
})
setMethod('tail', signature(x="big.matrix"),
function(x, n = 6) {
n <- min(as.integer(n), nrow(x))
if (n<1 | n>nrow(x)) stop("n must be between 1 and nrow(x)")
return(x[(nrow(x)-n+1):nrow(x),])
})
setMethod('print', signature(x='big.matrix'),
function(x) {
if (options()$bigmemory.print.warning==TRUE)
{
cat("Warning: This is not advised. Here is the head of the matrix:\n")
print(head(x))
}
else
{
# Should change this to a C print function, unfortunately, for proper
# formatting, this means we would also have to pass the terminal
# width.
print(x[,])
}
})
###################################################################
# mwhich()
#
# x big.matrix
# cols is.numeric or is.character
# vals list of scalar or 2-vectors otherwise
# comps could be missing, in which case we'll fill in 'eq' in signature,
# a list of comparisons matching dim of associated vals component
setGeneric('mwhich', function(x, cols, vals, comps, op = 'AND')
standardGeneric('mwhich'))
setMethod('mwhich',
signature(x='big.matrix', op='character'),
function(x, cols, vals, comps, op) {
return(mwhich.internal(x, cols, vals, comps, op, 'MWhichBigMatrix'))
})
setMethod('mwhich',
signature(x='matrix', op='character'),
function(x, cols, vals, comps, op)
{
if (is.integer(x))
return(mwhich.internal(x, cols, vals, comps, op, 'MWhichRIntMatrix'))
if (is.numeric(x))
return(mwhich.internal(x, cols, vals, comps, op, 'MWhichRNumericMatrix'))
stop("Unsupported matrix type given to mwhich")
})
setMethod('mwhich',
signature(x='big.matrix', op='missing'),
function(x, cols, vals, comps)
return(mwhich.internal(x, cols, vals, comps, op='AND',
whichFuncName='MWhichBigMatrix')))
setMethod('mwhich',
signature(x='matrix', op='missing'),
function(x, cols, vals, comps)
{
if (is.integer(x))
return(mwhich.internal(x, cols, vals, comps, op='AND',
whichFuncName='MWhichRIntMatrix'))
if (is.numeric(x))
return(mwhich.internal(x, cols, vals, comps, op='AND',
whichFuncName='MWhichRNumericMatrix'))
stop("Unsupported matrix type given to mwhich")
})
mwhich.internal <- function(x, cols, vals, comps, op, whichFuncName)
{
cols <- cleanupcols(cols, ncol(x), colnames(x))
if (length(setdiff(cols, 1:ncol(x))) > 0)
stop('Invalid column(s) in which()')
# if vals or comps are not lists but are length 1 or 2, make them
# trivial lists.
if ( !is.list(vals) &
(length(vals)==1 || length(vals)==2) ) {
vals <- list(vals)
} else {
if (!is.list(vals)) stop('vals should be a list')
}
if ( !is.list(comps) &
(length(comps)==1 || length(comps)==2)) {
comps <- list(comps)
} else {
if (!is.list(comps)) stop('comps should be a list')
}
# Replicate vals or comps if appropriate.
if (length(cols)!=length(vals)) {
if (length(vals)==1) {
vals <- data.frame(matrix(unlist(vals), length(vals), length(cols)))
} else stop('length(vals) must be 1 or length(cols)')
}
if (length(cols)!=length(comps)) {
if (length(comps)==1) {
comps <- data.frame(matrix(unlist(comps), length(comps), length(cols)),
stringsAsFactors=FALSE)
} else stop('length(comps) must be 1 or length(cols)')
}
if (length(comps)!=length(vals))
stop('length of comps must equal length of vals')
if (any(!unlist(lapply(comps, is.character))) ||
any(!(unlist(comps) %in% c('eq', 'neq', 'le', 'lt', 'ge', 'gt')))) {
stop('comps must contain eq, neq, le, lt, ge, or gt')
}
testCol <- cols
opVal <- 0
if (op == 'OR') opVal <- 1
minVal <- rep(NA, length(cols))
maxVal <- rep(NA, length(cols))
chkmin <- rep(0, length(cols))
chkmax <- rep(0, length(cols))
for (i in 1:length(cols)) {
if (length(vals[[i]])==1) {
# Here, we have the easy comparisons.
if (is.na(vals[[i]]) && (comps[[i]]!='eq' && comps[[i]]!='neq'))
stop('NA comparison limited to eq and neq, not le, lt, gt, or ge')
if (length(comps[[i]])==1) {
if (comps[[i]]=='eq' || comps[[i]]=='neq') {
minVal[i] <- vals[[i]]
maxVal[i] <- vals[[i]]
}
if (comps[[i]]=='neq') {
chkmin[i] <- -1
chkmax[i] <- -1 # Not used, but....
}
if (comps[[i]]=='ge' || comps[[i]]=='gt') {
minVal[i] <- vals[[i]]
maxVal[i] <- Inf
if (comps[[i]]=='gt') chkmin[i] <- 1
}
if (comps[[i]]=='le' || comps[[i]]=='lt') {
minVal[i] <- -Inf
maxVal[i] <- vals[[i]]
if (comps[[i]]=='lt') chkmax[i] <- 1
}
} else stop('vals/comps must be componentwise of same dimension')
} else {
# Here, we have two vals and two comps
if (any(is.na(vals[[i]]))) stop('NAs not allowed in interval comparison')
minVal[i] <- vals[[i]][1]
maxVal[i] <- vals[[i]][2]
if (comps[[i]][1]=='gt') chkmin[i] <- 1
if (comps[[i]][2]=='lt') chkmax[i] <- 1
if (comps[[i]][1]!='gt' && comps[[i]][1]!='ge')
stop('invalid comparison of lower bound')
if (comps[[i]][2]!='lt' && comps[[i]][2]!='le')
stop('invalid comparison of upper bound')
}
} # End of the for loop
##### The new C function has new vectors chkmin and chkmax;
##### the value 0 indicates comparison with equality,
##### the value 1 indicates a strict inequality,
##### the value -1 indicates a 'neq' check;
##### if is.na checking is required, only the minVal needs to be
##### used, with chkmin = 0 being is.na and chkmin = 1 being !is.na.
ret = NULL
if (whichFuncName == 'MWhichBigMatrix')
ret = .Call(whichFuncName, x@address, as.double(testCol),
as.double(minVal), as.double(maxVal),
as.integer(chkmin), as.integer(chkmax), as.integer(opVal))
else
ret = .Call(whichFuncName, x, nrow(x),
as.double(testCol),
as.double(minVal), as.double(maxVal),
as.integer(chkmin), as.integer(chkmax), as.integer(opVal))
return(ret)
}
setMethod('dimnames', signature(x = "big.matrix"),
function(x) return(list(rownames.bm(x), colnames.bm(x))))
setMethod('dimnames<-', signature(x = "big.matrix", value='list'),
function(x, value) {
if (options()$bigmemory.allow.dimnames) {
rownames.bm(x) <- value[[1]]
colnames.bm(x) <- value[[2]]
} else {
stop(paste("Changing dimnames is not allowed; to override, please set",
"options(bigmemory.allow.dimnames=TRUE)."))
}
return(x)
})
setGeneric('read.big.matrix',
function(filename, sep=',', header=FALSE, col.names=NULL, row.names=NULL,
has.row.names=FALSE, ignore.row.names=FALSE, type=NA, skip=0,
separated=FALSE, backingfile=NULL, backingpath=NULL,
descriptorfile=NULL, binarydescriptor=FALSE, extraCols=NULL,
shared=TRUE)
standardGeneric('read.big.matrix'))
setMethod('read.big.matrix', signature(filename='character'),
function(filename, sep, header, col.names, row.names, has.row.names,
ignore.row.names, type, skip, separated, backingfile, backingpath,
descriptorfile, binarydescriptor, extraCols, shared=TRUE)
{
if (!is.logical(header))
stop("header argument must be logical")
if (is.logical(col.names) || is.logical(row.names))
stop("row.names and col.names, if used, must only be vectors of names (not logicals).")
if ( (header || is.character(col.names)) && is.numeric(extraCols) )
{
stop(paste("When column names are specified, extraCols must be the names",
"of the extra columns."))
}
if (!header && is.null(col.names) && is.character(extraCols))
stop(paste("No header and no column names were specified, so extraCols",
"must be an integer."))
if (!file.exists(filename))
stop(paste("The file", filename, "could not be found"))
headerOffset <- as.numeric(header)
colNames <- NULL
if (header) {
colNames <- unlist(strsplit(
scan(filename, what='character', skip=skip, nlines=1, sep="\n",
quiet=TRUE), split=sep))
colNames <- gsub("\"", "", colNames, perl=TRUE)
colNames <- gsub("\'", "", colNames, perl=TRUE)
if (is.na(colNames[1])) colNames <- colNames[-1]
if (is.character(col.names)) {
warning("Using supplied column names and skipping the header row.\n")
colNames <- col.names
} else {
if (!is.null(col.names))
stop("Invalid header/col.names usage (col.names must be a vector of names if used).\n")
}
} else {
if (is.character(col.names)) colNames <- col.names
}
# Get the first line of data
firstLine <- scan(filename, what='character', skip=(skip+headerOffset),
nlines=1, sep="\n", quiet=TRUE)
firstLineVals <- unlist(strsplit(firstLine, split=sep))
numFields <- length(firstLineVals)
firstLineVals[firstLineVals=="NA"] <- NA
if (length(firstLineVals) < numFields) {
firstLineVals <- c(firstLineVals, NA)
}
# At this point, we assume there are length(colNames) columns of data if
# available, otherwise, figure it out.
if (!is.null(colNames)) numCols <- length(colNames)
else {
numCols <- length(firstLineVals) - has.row.names
}
if (length(firstLineVals) - has.row.names != numCols)
stop("Dimension mismatch between header row and first data row.\n")
rowNames <- NULL
if (!is.null(row.names)) {
if (is.character(row.names)) {
rowNames <- row.names
ignore.row.names <- TRUE
} else { stop("Invalid row.names (must be a vector of names if used).\n") }
}
if (is.na(type)) {
type <- 'double'
if (has.row.names) firstLineVals <- firstLineVals[-1]
if (sum(na.omit(as.integer(firstLineVals)) ==
na.omit(as.double(firstLineVals))) ==
numCols )
type <- 'integer'
warning(paste("Because type was not specified, we chose", type,
"based on the first line of data."))
}
lineCount <- .Call("CCountLines", filename) - skip - headerOffset
numRows <- lineCount
createCols <- numCols
if (is.numeric(extraCols)) createCols <- createCols + extraCols
if (is.character(extraCols)) {
createCols <- createCols + length(extraCols)
colNames <- c(colNames, extraCols)
}
bigMat <- big.matrix(nrow=numRows, ncol=createCols, type=type,
dimnames=list(rowNames, colNames), init=NULL,
separated=separated, backingfile=backingfile,
backingpath=backingpath,
descriptorfile=descriptorfile,
binarydescriptor=binarydescriptor, shared=TRUE)
# has.row.names indicates whether or not there are row names;
# we take ignore.row.names from the user, but pass (essentially)
# use.row.names (which is !ignore.row.names) to C:
.Call('ReadMatrix', filename, bigMat@address,
as.integer(skip+headerOffset), as.double(numRows),
as.double(numCols), as.character(sep), as.logical(has.row.names),
as.logical(!ignore.row.names))
return(bigMat)
})
setGeneric('write.big.matrix',
function(x, filename, row.names=FALSE, col.names=FALSE, sep=",")
standardGeneric('write.big.matrix'))
setMethod('write.big.matrix', signature(x='big.matrix',filename='character'),
function(x, filename, row.names, col.names, sep)
{
if (is.character(row.names))
stop("You must set the row names before writing.\n")
if (is.character(col.names))
stop("You must set the column names before writing.\n")
if (row.names & !.Call("HasRowColNames",x@address)[1]) {
row.names <- FALSE
warning("No row names exist, overriding your row.names option.\n")
}
if (col.names & !.Call("HasRowColNames",x@address)[2]) {
col.names <- FALSE
warning("No column names exist, overriding your col.names option.\n")
}
.Call('WriteMatrix', x@address, filename, as.logical(row.names),
as.logical(col.names), sep)
invisible(NULL)
})
setGeneric('is.separated', function(x) standardGeneric('is.separated'))
setMethod('is.separated', signature(x='big.matrix'),
function(x) return(.Call("IsSeparated", x@address)))
cleanupcols <- function(cols=NULL, nc=NULL, colnames=NULL) {
if (is.null(cols)) cols <- 1:nc
else {
if (!is.numeric(cols) & !is.character(cols) & !is.logical(cols))
stop("column indices must be numeric, logical, or character vectors.")
if (is.character(cols))
if (is.null(colnames)) stop("column names do not exist.")
else cols <- mmap(cols, colnames)
if (is.logical(cols)) {
if (length(cols) != nc)
stop(paste("column vector length must match the number of",
"columns of the matrix."))
cols <- which(cols)
}
tempj <- .Call("CCleanIndices", as.double(cols), as.double(nc))
if (is.null(tempj[[1]])) stop("Illegal column index usage in extraction.\n")
if (tempj[[1]]) cols <- tempj[[2]]
}
return(cols)
}
cleanuprows <- function(rows=NULL, nr=NULL, rownames=NULL) {
if (is.null(rows)) rows <- 1:nr
else {
if (!is.numeric(rows) & !is.character(rows) & !is.logical(rows))
stop("column indices must be numeric, logical, or character vectors.")
if (is.character(rows))
if (is.null(rownames)) stop("row names do not exist.")
else rows <- mmap(rows, rownames)
if (is.logical(rows)) {
if (length(rows) != nr)
stop(paste("row vector length must match the number of",
"rows of the matrix."))
rows <- which(rows)
}
tempj <- .Call("CCleanIndices", as.double(rows), as.double(nr))
if (is.null(tempj[[1]])) stop("Illegal row index usage in extraction.\n")
if (tempj[[1]]) rows <- tempj[[2]]
}
return(rows)
}
deepcopy <- function(x, cols=NULL, rows=NULL,
y=NULL, type=NULL, separated=NULL,
backingfile=NULL, backingpath=NULL,
descriptorfile=NULL, binarydescriptor=FALSE,
shared=TRUE)
{
cols <- cleanupcols(cols, ncol(x), colnames(x))
rows <- cleanuprows(rows, nrow(x), rownames(x))
if (nrow(x) > 2^31-1)
stop(paste("Too many rows to copy at this point in time;",
"this may be fixed in the future."))
if (is.null(type)) type <- typeof(x)
if (is.big.matrix(x)) {
if (is.null(separated)) separated <- is.separated(x)
} else {
separated <- FALSE
}
if (is.null(y)) {
y <- big.matrix(nrow=length(rows), ncol=length(cols), type=type, init=NULL,
dimnames=dimnames(x), separated=separated,
backingfile=backingfile, backingpath=backingpath,
descriptorfile=descriptorfile,
binarydescriptor=binarydescriptor, shared)
}
if (is.big.matrix(x) && is.big.matrix(y))
.Call("CDeepCopy", x@address, y@address, as.double(rows), as.double(cols),
getOption("bigmemory.typecast.warning"))
else
for (i in 1:length(cols)) y[,i] <- x[rows,cols[i]]
return(y)
}
# Following the R convention we are going to assume Unix directory
# separators '/' as opposed to the Windows convention '\'.
setGeneric('is.sub.big.matrix', function(x)
standardGeneric('is.sub.big.matrix'))
setMethod('is.sub.big.matrix', signature(x='big.matrix'),
function(x) return(.Call('CIsSubMatrix', x@address)) )
# For now a submatrix only goes over a range of columns and a range
# of row. This could be made more sophiticated but it would probably
# take a lot of work.
setGeneric('sub.big.matrix', function(x, firstRow=1, lastRow=NULL,
firstCol=1, lastCol=NULL, backingpath=NULL) standardGeneric('sub.big.matrix'))
setMethod('sub.big.matrix', signature(x='big.matrix'),
function(x, firstRow, lastRow, firstCol, lastCol, backingpath)
{
return(sub.big.matrix(describe(x), firstRow, lastRow, firstCol, lastCol,
backingpath))
})
setMethod('sub.big.matrix', signature(x='big.matrix.descriptor'),
function( x, firstRow, lastRow, firstCol, lastCol, backingpath)
{
rowOffset <- firstRow-1
colOffset <- firstCol-1
rbm <- attach.resource(x, path=backingpath)
if (is.null(lastRow)) lastRow <- nrow(rbm)
if (is.null(lastCol)) lastCol <- ncol(rbm)
numCols <- lastCol-firstCol+1
numRows <- lastRow-firstRow+1
if (colOffset < 0 || rowOffset < 0 || numCols < 1 || numRows < 1 ||
colOffset+numCols > ncol(rbm) || rowOffset+numRows > nrow(rbm))
{
rm(rbm)
stop(paste("A sub.big.matrix object could not be created",
"with the specified parameters"))
}
.Call("SetRowOffsetInfo", rbm@address,
as.double(rowOffset + .Call("GetRowOffset", rbm@address)),
as.double(numRows) )
.Call("SetColumnOffsetInfo", rbm@address,
as.double(colOffset + .Call("GetColOffset", rbm@address)),
as.double(numCols))
return(rbm)
})
filebacked.big.matrix <- function(nrow, ncol,
type=options()$bigmemory.default.type,
init=NULL, dimnames=NULL, separated=FALSE,
backingfile=NULL, backingpath=NULL,
descriptorfile=NULL, binarydescriptor=FALSE)
{
if (nrow < 1 | ncol < 1)
stop('A big.matrix must have at least one row and one column')
if (nrow < 1 | ncol < 1)
stop('A big.matrix must have at least one row and one column')
typeVal=NULL
if (type == 'integer') typeVal <- 4
if (type == 'double') typeVal <- 8
if (type == 'short') typeVal <- 2
if (type == 'char') typeVal <- 1
if (is.null(typeVal)) stop('invalid type')
if (!is.null(dimnames)) {
rownames <- dimnames[[1]]
colnames <- dimnames[[2]]
} else {
rownames <- NULL
colnames <- NULL
}
if (is.null(backingfile))
{
stop('You must specify a backing file')
}
anon.backing <- ifelse( backingfile == '', TRUE, FALSE )
if (anon.backing)
{
backingfile <- tempfile()
backingpath <- dirname(backingfile)
backingfile <- basename(backingfile)
}
if (is.null(descriptorfile) && !anon.backing)
{
warning(paste("No descriptor file given, it will be named",
paste(backingfile, '.desc', sep='')))
descriptorfile <- paste(backingfile, '.desc', sep='')
}
if ( !anon.backing && ((basename(backingfile) != backingfile) ||
(basename(descriptorfile) != descriptorfile)) )
{
stop(paste("The path to the descriptor and backing file are",
"specified with the backingpath option"))
}
if (is.null(backingpath)) backingpath <- '.'
backingpath <- path.expand(backingpath)
backingpath <- file.path(backingpath, '.')
backingpath <- substr( backingpath, 1, nchar(backingpath)-1 )
address <- .Call('CreateFileBackedBigMatrix', as.character(backingfile),
as.character(backingpath), as.double(nrow), as.double(ncol),
as.character(colnames), as.character(rownames), as.integer(typeVal),
as.double(init), as.logical(separated))
if (is.null(address))
{
stop("Error encountered when creating instance of type big.matrix")
}
x <- new("big.matrix", address=address)
if (is.null(x))
{
stop("Error encountered when creating instance of type big.matrix")
}
if (is.null(descriptorfile) && !anon.backing)
{
warning(paste("A descriptor file has not been specified. ",
"A descriptor named ", backingfile,
".desc will be created.", sep=''))
descriptorfile <- paste(backingfile, ".desc", sep='' )
}
if (!anon.backing)
{
descriptorfilepath <- file.path(backingpath, descriptorfile)
if(binarydescriptor)
{
saveRDS(describe(x), file=descriptorfilepath)
} else {
dput(describe(x), descriptorfilepath)
}
}
return(x)
}
setMethod('description', signature(x='big.matrix.descriptor'),
function(x) return(x@description))
DescribeBigMatrix = function(x)
{
if (!is.filebacked(x))
{
if (is.shared(x)) {
ret <- list(sharedType = 'SharedMemory',
sharedName = shared.name(x),
totalRows = .Call("GetTotalRows", x@address),
totalCols = .Call("GetTotalColumns", x@address),
rowOffset = .Call("GetRowOffset", x@address),
colOffset = .Call("GetColOffset", x@address),
nrow=nrow(x), ncol=ncol(x),
rowNames=rownames(x), colNames=colnames(x), type=typeof(x),
separated=is.separated(x))
} else {
stop("you can't describe a non-shared big.matrix.")
}
}
else
{
ret = list(sharedType='FileBacked',
filename=file.name(x),
totalRows = .Call("GetTotalRows", x@address),
totalCols = .Call("GetTotalColumns", x@address),
rowOffset = .Call("GetRowOffset", x@address),
colOffset = .Call("GetColOffset", x@address),
nrow=nrow(x), ncol=ncol(x),
rowNames=rownames(x), colNames=colnames(x), type=typeof(x),
separated=is.separated(x))
}
}
attach.big.matrix = function(obj, ...)
{
if (!is.null( list(...)[['backingpath']]))
return(attach.resource(obj, path=list(...)[['backingpath']], ...))
return(attach.resource(obj, ...))
}
setMethod('attach.resource', signature(obj='character'),
function(obj, ...)
{
path <- list(...)[['path']]
if (is.null(path))
{
path <- '.'
}
path <- path.expand(path)
if (basename(obj) != obj)
{
if (path != ".")
warning(paste("Two paths were specified in attach.resource.",
"The one associated with the file will be used.", sep=" "))
path <- dirname(obj)
obj <- basename(obj)
}
fileWithPath <- file.path(path, obj)
fi = file.info(fileWithPath)
if (is.na(fi$isdir))
stop( paste("The file", fileWithPath, "could not be found") )
if (fi$isdir)
stop( fileWithPath, "is a directory" )
info <- tryCatch(readRDS(file=fileWithPath), error=function(er){return(dget(fileWithPath))})
return(attach.resource(info, path=path))
})
setMethod('attach.resource', signature(obj='big.matrix.descriptor'),
function(obj, ...)
{
path <- list(...)[['path']]
if (is.null(path))
{
path <- '.'
}
info <- description(obj)
typeLength <- NULL
if (info$type == 'char') typeLength <- 1
if (info$type == 'short') typeLength <- 2
if (info$type == 'integer') typeLength <- 4
if (info$type == 'double') typeLength <- 8
if (is.null(typeLength))
stop('invalid type')
path <- path.expand(path)
fi = file.info(path)
if (path != '.' && is.na(fi$isdir))
stop( paste("The directory", path, "could not be found") )
if (!is.na(fi$isdir) && !fi$isdir)
stop( paste(path, "is not a directory.") )
path = file.path(path, '.')
path <- substr(path, 1, nchar(path)-1)
if (substr(path, nchar(path), nchar(path)) == "/") {
path <- substr(path, 1, nchar(path)-1)
}
readOnly <- ifelse( is.null(list(...)$readonly), FALSE, list(...)$readonly)
if (!is.logical(readOnly)) {
stop("The readOnly argument must be of type logical")
}
if (info$sharedType == 'SharedMemory')
{
address <- .Call('CAttachSharedBigMatrix', info$sharedName,
info$totalRows, info$totalCols, as.character(info$rowNames),
as.character(info$colNames), as.integer(typeLength), info$separated,
readOnly)
}
else
{
if (!info$separated) {
if (!file.exists(file.path(path, info$filename)))
{
stop(paste("The backing file", paste(path, info$filename, sep=''),
"could not be found"))
}
} else {
# It's separated and we need to check for each column.
for (i in 1:info$ncol) {
fn <- paste(info$filename, "_column_", (i-1), sep='')
if (!file.exists(file.path(path, fn)))
{
stop(paste("The backing file", file.path(path, fn),
"could not be found"))
}
}
}
address <- .Call('CAttachFileBackedBigMatrix',
info$filename, path, info$totalRows, info$totalCols,
as.character(info$rowNames), as.character(info$colNames),
as.integer(typeLength), info$separated, readOnly)
}
if (!is.null(address))
{
.Call("SetRowOffsetInfo", address, info$rowOffset, info$nrow)
.Call("SetColumnOffsetInfo", address, info$colOffset, info$ncol)
ret <- new('big.matrix', address=address)
# If the user did not specify read-only but the big matrix could
# only be opened read-only then issue a warning.
if (readOnly != is.readonly(ret)) {
warning("big.matrix object could only be opened read-only.")
}
}
else
{
stop("Fatal error in attach: big.matrix could not be attached.")
}
return(ret)
})
setGeneric('is.filebacked', function(x) standardGeneric('is.filebacked'))
setMethod('is.filebacked', signature(x='big.matrix'),
function(x) return(.Call("IsFileBackedBigMatrix", x@address)))
setGeneric('shared.name', function(x) standardGeneric('shared.name'))
setMethod('shared.name', signature(x='big.matrix'),
function(x) return(.Call('SharedName', x@address)))
setGeneric('file.name', function(x) standardGeneric('file.name'))
setMethod('file.name', signature(x='big.matrix'),
function(x)
{
if (!is.filebacked(x))
{
stop("The argument is not a file backed big.matrix.")
}
return(.Call('FileName', x@address))
})
transpose.big.matrix <- function(x, backingfile=NULL,
backingpath=NULL, descriptorfile=NULL,
binarydescriptor=FALSE, shared=TRUE) {
temp <- big.matrix(nrow=ncol(x), ncol=nrow(x), type=typeof(x),
dimnames=dimnames(x)[[2:1]], separated=is.separated(x),
backingfile=backingfile, backingpath=backingpath,
descriptorfile=descriptorfile, binarydescriptor=binarydescriptor,
shared=TRUE)
for (i in 1:nrow(x)) {
temp[,i] <- x[i,]
}
return(temp)
}
setGeneric('flush', function(con) standardGeneric('flush'))
setMethod('flush', signature(con='big.matrix'),
function(con)
{
if (!is.filebacked(con))
{
warning("You cannot call flush on a non-filebacked big.matrix")
return(invisible(TRUE))
}
return(invisible(.Call("Flush", con@address)))
})
setGeneric('is.shared', function(x) standardGeneric('is.shared'))
setMethod('is.shared', signature(x='big.matrix'),
function(x) return(.Call("IsShared", x@address)))
morder <- function(x, cols, na.last=TRUE, decreasing = FALSE)
{
if (is.character(cols)) cols <- mmap( cols, colnames(x) )
if (sum(cols > ncol(x)) > 0 | sum(cols < 1) > 0 | sum(is.na(cols) > 0))
{
stop("Bad column indices.")
}
if (class(x) == 'big.matrix')
{
return(.Call('OrderBigMatrix', x@address, as.double(cols),
as.integer(na.last), as.logical(decreasing) ))
}
else if (class(x) == 'matrix')
{
if (typeof(x) == 'integer')
{
return(.Call('OrderRIntMatrix', x, nrow(x), as.double(cols),
as.integer(na.last), as.logical(decreasing) ))
}
else if (typeof(x) == 'double')
{
return(.Call('OrderRNumericMatrix', x, nrow(x), as.double(cols),
as.integer(na.last), as.logical(decreasing) ))
}
else
stop("Unsupported matrix value type.")
}
else
stop("Unsupported matrix type.")
}
mpermute <- function(x, order=NULL, cols=NULL, allow.duplicates=FALSE, ...)
{
if (is.null(order) && is.null(cols))
stop("You must specify either order or cols.")
if (!is.null(order) && !is.null(cols))
stop("You must specify either order or cols.")
if (!is.null(order))
{
if (length(order) != nrow(x))
stop("order parameter must have the same length as nrow(x)")
if (!allow.duplicates && sum(duplicated(order)) > 0)
stop("order parameter contains duplicated entries.")
r = range(order)
if (is.na(r[1]))
stop("order parameter contains NAs")
if (r[1] < 1 || r[2] > nrow(x))
stop("order parameter contains values that are out-of-range.")
}
else
order = morder(x, cols, ...)
if (class(x) == 'big.matrix')
{
.Call('ReorderBigMatrix', x@address, order)
}
else if (class(x) == 'matrix')
{
if (typeof(x) == 'integer')
{
.Call('OrderRIntMatrix', x, nrow(x), ncol(x), order)
}
else if (typeof(x) == 'double')
{
.Call('ReorderRNumericMatrix', x, nrow(x), ncol(x), order)
}
else
stop("Unsupported matrix value type.")
}
return(invisible(TRUE))
}
is.nil <- function(address) {
if (class(address)!="externalptr") stop("address is not an externalptr.")
ans <- .Call("isnil", address)
return(ans)
}
setGeneric('is.readonly', function(x) standardGeneric('is.readonly'))
setMethod('is.readonly', signature(x='big.matrix'),
function(x) .Call("IsReadOnly", x@address))
getCType <- function(x) {
if (!inherits(x, "big.matrix"))
stop("getCType takes a big.matrix as an argument.")
return(.Call("CGetType", x@address, PACKAGE="bigmemory"))
}
.addDimnames <- function(retList, nrow, ncol, drop) {
if (drop && !is.matrix(retList[[1]]) ) {
if (length(retList[[1]]) > 1) {
if (ncol == 1) {
thesenames <- retList[[2]]
} else if (nrow == 1)
thesenames <- retList[[3]]
} else {
thesenames <- NULL
}
if (!is.null(thesenames)) {
names(retList[[1]]) <- thesenames
}
} else {
if (!is.matrix(retList[[1]])) { retList[[1]] = matrix(retList[[1]], nrow=nrow, ncol=ncol) }
if (!is.null(retList[[2]]) || !is.null(retList[[3]])) {
dimnames(retList[[1]]) <- list( retList[[2]], retList[[3]] )
}
}
return(retList[[1]])
}
resizeBM <- function(obj, nRow, nCol, ...){
if(class(obj) != "big.matrix"){
stop("Error: 'obj' is not of class 'big.matrix'")
}
info <- describe(obj)@description
newRows <- info$totalRows + nRow
newCols <- info$totalCols + nCol
# Check if want to only allow reshaping instead of increasing overall size
# Currently unable to add rows.
# if(info$totalRows*info$totalCols != newRows*newCols){
# stop("Error: new dimensions product must equal old dimensions product")
# }
typeLength <- NULL
if (info$type == 'char') typeLength <- 1
if (info$type == 'short') typeLength <- 2
if (info$type == 'integer') typeLength <- 4
if (info$type == 'double') typeLength <- 8
readOnly <- ifelse( is.null(list(...)$readonly), FALSE, list(...)$readonly)
if (!is.logical(readOnly)) {
stop("The readOnly argument must be of type logical")
}
address <- .Call('CResizeSharedBigMatrix', obj@address, info$sharedName,
newRows, newCols, as.character(info$rowNames),
as.character(info$colNames), as.integer(typeLength), info$separated,
readOnly)
ret <- paste(c("big.matrix", address, "was modified"), collapse=" ")
return(ret)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.