.packageName <- "xtable"
### xtable 1.2-5  (2004/12/01)
###
### Produce LaTeX and HTML tables from R objects.
###
### Copyright 2000-2004 David B. Dahl <dahl@stat.tamu.edu>
###
### This file is part of the `xtable' library for R and related languages.
### It is made available under the terms of the GNU General Public
### License, version 2, or at your option, any later version,
### incorporated herein by reference.
###
### This program is distributed in the hope that it will be
### useful, but WITHOUT ANY WARRANTY; without even the implied
### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
### PURPOSE.  See the GNU General Public License for more
### details.
###
### You should have received a copy of the GNU General Public
### License along with this program; if not, write to the Free
### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
### MA 02111-1307, USA
print.xtable <- function(x,type="latex",file="",append=FALSE,floating=TRUE,table.placement="ht",caption.placement="bottom",latex.environments=c("center"),size=NULL,hline.after=NULL,...) {

  if (length(type)>1)
    stop("\"type\" must have length 1")
  type <- tolower(type)
  if (!all(!is.na(match(type,c("latex","html")))))
    stop("\"type\" must be in {\"latex\", \"html\"}")
  if (!all(!is.na(match(unlist(strsplit(table.placement, split="")),c("h","t","b","p","!")))))
    stop("\"table.placement\" must contain only elements of {\"h\",\"t\",\"b\",\"p\",\"!\"}")
  if (!all(!is.na(match(caption.placement,c("bottom","top")))))
    stop("\"caption.placement\" must be either {\"bottom\",\"top\"}")

  if (type=="latex") {
    BCOMMENT <- "% "
    ECOMMENT <- "\n"
# See e-mail from "John S. Walker <jsw9c@uic.edu>" dated 5-19-2003 regarding "texfloat"
    if ( floating == TRUE ) {
      # See e-mail from "Pfaff, Bernhard <Bernhard.Pfaff@drkw.com>" dated 7-09-2003 regarding "suggestion for an amendment of the source"
      # See e-mail from "Mitchell, David" <David.Mitchell@dotars.gov.au>" dated 2003-07-09 regarding "Additions to R xtable package"
      BTABLE <- paste("\\begin{table}",ifelse(!is.null(table.placement),
        paste("[",table.placement,"]",sep=""),""),"\n",sep="")
      if ( is.null(latex.environments) || (length(latex.environments)==0) ) {
        BENVIRONMENT <- ""
        EENVIRONMENT <- ""
      }
      else {
        BENVIRONMENT <- ""
        EENVIRONMENT <- ""
        for ( i in 1:length(latex.environments) ) {
          if ( latex.environments[i] == "" ) next
          BENVIRONMENT <- paste(BENVIRONMENT, "\\begin{",latex.environments[i],"}\n",sep="")
          EENVIRONMENT <- paste("\\end{",latex.environments[i],"}\n",EENVIRONMENT,sep="")
        }
      }
      ETABLE <- "\\end{table}\n"
    }
    else {
      BTABLE <- ""
      ETABLE <- ""
      BENVIRONMENT <- ""
      EENVIRONMENT <- ""
    }
#    BTABULAR <- string("\\begin{tabular}{|") + paste(attr(x,"align"),collapse="|") + "|}\n\\hline\n"
#    See e-mail from "BXC (Bendix Carstensen)" <bxc@novonordisk.com> dated Mon, 27 Aug 2001 10:11:54 +0200
    BTABULAR <- paste("\\begin{tabular}{",
                      paste(attr(x, "vsep"),
                            c(attr(x, "align"), "}\n\\hline\n"),
                            sep="", collapse=""),
                      sep="")
    ETABULAR <- "\\hline\n\\end{tabular}\n"
# BSIZE contributed by Benno Pütz <puetz@mpipsykl.mpg.de> in e-mail dated Wednesday, December 01, 2004
    if (is.null(size) || !is.character(size)){
      BSIZE <- ""
      ESIZE <- ""
    } else {
      if(length(grep("^\\\\",size))==0){
        size <- paste("\\",size,sep="")
      }
      BSIZE <- paste("{",size,"\n",sep="")
      ESIZE <- "}\n"
    }
    BLABEL <- "\\label{"
    ELABEL <- "}\n"
    BCAPTION <- "\\caption{"
    ECAPTION <- "}\n"
    BROW <- ""
    EROW <- " \\\\\n"
    BTH <- ""
    ETH <- ""
    STH <- " & "
    PHEADER <- "\\hline\n"
    BTD1 <- " & "
    BTD2 <- ""
    BTD3 <- ""
    ETD  <- ""
    sanitize <- function(str) {
      result <- str
      result <- gsub(">","$>$",result)
      result <- gsub("<","$<$",result)
      result <- gsub("\\|","$\|$",result)
      return(result)
    }
    sanitize.numbers <- function(x) {
      result <- x
      for(i in 1:length(x)) {
        result[i] <- gsub("-","$-$",result[i])
      }
      return(result)
    }
 } else {
    BCOMMENT <- "<!-- "
    ECOMMENT <- " -->\n"
    BTABLE <- "<TABLE border=1>\n"
    ETABLE <- "</TABLE>\n"
    BENVIRONMENT <- ""
    EENVIRONMENT <- ""
    BTABULAR <- ""
    ETABULAR <- ""
    BSIZE <- ""
    ESIZE <- ""
    BLABEL <- "<A NAME="
    ELABEL <- "></A>\n"
    BCAPTION <- paste("<CAPTION ALIGN=\"",caption.placement,"\"> ",sep="")
    ECAPTION <- " </CAPTION>\n"
    BROW <- "<TR>"
    EROW <- " </TR>\n"
    BTH <- " <TH> "
    ETH <- " </TH> "
    STH <- " </TH> <TH> "
    PHEADER <- ""
    BTD1 <- " <TD align=\""
    BTD2 <- matrix(attr(x,"align"),nrow=nrow(x),ncol=ncol(x)+1,byrow=TRUE)
    BTD2[BTD2=="r"] <- "right"
    BTD2[BTD2=="l"] <- "left"
    BTD2[BTD2=="c"] <- "center"
    BTD3 <- "\"> "
    ETD  <- " </TD>"
    sanitize <- function(str) {
      result <- str
      result <- gsub("&","&amp ",result)
      result <- gsub(">","&gt ",result)
      result <- gsub("<","&lt ",result)
      return(result)
    }
    sanitize.numbers <- function(x) {
      return(x)
    }
  }


  result <- string("",file=file,append=append)
  info <- R.Version()
  result <- result + BCOMMENT + type + " table generated in " +
            info$language + " " + info$major + "." + info$minor + " by xtable 1.2-5 package" + ECOMMENT
  result <- result + BCOMMENT + date() + ECOMMENT
  result <- result + BTABLE
  result <- result + BENVIRONMENT
  if ( floating == TRUE ) {
    if ((!is.null(attr(x,"caption"))) && (type=="html" || caption.placement=="top")) result <- result + BCAPTION + attr(x,"caption") + ECAPTION
    if (!is.null(attr(x,"label")) && (type=="latex" && caption.placement=="top")) result <- result + BLABEL + attr(x,"label") + ELABEL  
  }
  result <- result + BSIZE
  result <- result + BTABULAR
  result <- result + BROW + BTH + STH + paste(sanitize(names(x)),collapse=STH) + ETH + EROW
  result <- result + PHEADER

  cols <- matrix("",nrow=nrow(x),ncol=ncol(x)+1)
  cols[,1] <- row.names(x)
  disp <- function(y) {
    if (is.factor(y)) {
      y <- levels(y)[y]
    }
    if (is.list(y)) {
      y <- unlist(y)
    }
    return(y)
  }
  for(i in 1:ncol(x)) {
    ina <- is.na(x[,i])
    cols[,i+1] <- formatC(disp(x[,i]),format=attr(x,"display")[i+1],digits=attr(x,"digits")[i+1])
    if (any(ina)) cols[ina,i+1] <- ""
    cols[,i+1] <- sanitize.numbers(cols[,i+1])
  }

  multiplier <- 5
  full <- matrix("",nrow=nrow(x),ncol=multiplier*(ncol(x)+1)+2)
  full[,1] <- BROW
  full[,multiplier*(0:ncol(x))+2] <- BTD1
  full[,multiplier*(0:ncol(x))+3] <- BTD2
  full[,multiplier*(0:ncol(x))+4] <- BTD3
  full[,multiplier*(0:ncol(x))+5] <- cols
  full[,multiplier*(0:ncol(x))+6] <- ETD
# hline.after contributed by Benno Pütz <puetz@mpipsykl.mpg.de> in e-mail dated Wednesday, December 01, 2004
  full[,multiplier*(ncol(x)+1)+2] <- ifelse(1:nrow(x) %in% hline.after,paste(EROW,PHEADER,sep=""),EROW)
  if (type=="latex") full[,2] <- ""

  result <- result + paste(t(full),collapse="")
  result <- result + ETABULAR
  result <- result + ESIZE
  if ( floating == TRUE ) {
    if ((!is.null(attr(x,"caption"))) && (type=="latex" && caption.placement=="bottom")) result <- result + BCAPTION + attr(x,"caption") + ECAPTION
    if (!is.null(attr(x,"label")) && caption.placement=="bottom") result <- result + BLABEL + attr(x,"label") + ELABEL  
  }
  result <- result + EENVIRONMENT
  result <- result + ETABLE
  print(result)

  return(invisible())
}

"+.string" <- function(x,y) {
  x$text <- paste(x$text,as.string(y)$text,sep="")
  return(x)
}

print.string <- function(x,...) {
  cat(x$text,file=x$file,append=x$append)
  return(invisible())
}

string <- function(text,file="",append=FALSE) {
  x <- list(text=text,file=file,append=append)
  class(x) <- "string"
  return(x)
}

as.string <- function(x,file="",append=FALSE) {
  if (is.null(attr(x,"class")))
  switch(data.class(x),
      character=return(string(x,file,append)),
      numeric=return(string(as.character(x),file,append)),
      stop("Cannot coerse argument to a string"))
  if (class(x)=="string")
    return(x)
  stop("Cannot coerse argument to a string")
}

is.string <- function(x) {
  return(class(x)=="string")
}

### xtable 1.2-5  (2004/12/01)
###
### Produce LaTeX and HTML tables from R objects.
###
### Copyright 2000-2004 David B. Dahl <dahl@stat.tamu.edu>
###
### This file is part of the `xtable' library for R and related languages.
### It is made available under the terms of the GNU General Public
### License, version 2, or at your option, any later version,
### incorporated herein by reference.
###
### This program is distributed in the hope that it will be
### useful, but WITHOUT ANY WARRANTY; without even the implied
### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
### PURPOSE.  See the GNU General Public License for more
### details.
###
### You should have received a copy of the GNU General Public
### License along with this program; if not, write to the Free
### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
### MA 02111-1307, USA

"caption<-" <- function(x,value) UseMethod("caption<-")
"caption<-.xtable" <- function(x,value) {
  if (length(value)>1)
    stop("\"caption\" must have length 1")
  attr(x,"caption") <- value
  return(x)
}

caption <- function(x,...) UseMethod("caption")
caption.xtable <- function(x,...) {
  return(attr(x,"caption"))
}

"label<-" <- function(x,value) UseMethod("label<-")
"label<-.xtable" <- function(x,value) {
  if (length(value)>1)
    stop("\"label\" must have length 1")
  attr(x,"label") <- value
  return(x)
}

label <- function(x,...) UseMethod("label")
label.xtable <- function(x,...) {
  return(attr(x,"label"))
}

"align<-" <- function(x,value) UseMethod("align<-")
"align<-.xtable" <- function(x,value) {
# Based on contribution from Benno Pütz <puetz@mpipsykl.mpg.de> in e-mail dated Wednesday, December 01, 2004
  # cat("%",value,"\n")
  if ( (!is.null(value)) && ( is.character(value) ) && ( length(value) == 1 ) && ( nchar(value) > 1 ) ) {
    value <- strsplit(value,"")[[1]]
  }
  if (!all(!is.na(match(value,c("r","l","c","|"))))){
    stop("\"align\" must be containing elements of {\"r\",\"l\",\"c\",\"|\"}")
  }
  c.value <- if (any(!is.na(match(value,"|")))) {
                value[-which(value=='|')]
             } else {
                value
             }
  if (length(c.value)!=ncol(x)+1)
      stop(paste("\"align\" must have length equal to",ncol(x)+1,"( ncol(x) + 1 )"))

  attr(x,"align") <- value
  return(x)
}

align <- function(x,...) UseMethod("align")
align.xtable <- function(x,...) {
  return(attr(x,"align"))
}

"vsep<-" <- function(x,value) UseMethod("vsep<-")
"vsep<-.xtable" <- function(x, value) {
  if(is.null(value))
    vsep <- ""
    if(length(value) == 1)
      value <- rep(value, ncol(x) + 2)
    if (length(value) != ncol(x) + 2)
                                        # +2 due to table edges
    stop(paste("\"vsep\" must have length equal to", ncol(x)+2,
               "( ncol(x) + 2 )"))
  attr(x, "vsep") <- value
  return(x)
}

vsep <- function(x, ...) UseMethod("vsep")
vsep.xtable <- function(x, ...) {
  return(attr(x, "vsep"))
}

"digits<-" <- function(x,value) UseMethod("digits<-")
"digits<-.xtable" <- function(x,value) {
  if (length(value)!=ncol(x)+1)
    stop(paste("\"digits\" must have length equal to",ncol(x)+1,"( ncol(x) + 1 )"))
  if (!is.numeric(value))
    stop("\"digits\" must be numeric")
  attr(x,"digits") <- value
  return(x)
}

digits <- function(x,...) UseMethod("digits")
digits.xtable <- function(x,...) {
  return(attr(x,"digits"))
}

"display<-" <- function(x,value) UseMethod("display<-")
"display<-.xtable" <- function(x,value) {
  if (length(value)!=ncol(x)+1)
    stop(paste("\"display\" must have length equal to",ncol(x)+1,"( ncol(x) + 1 )"))
  if (!all(!is.na(match(value,c("d","f","e","E","g","G","fg","s")))))
    stop("\"display\" must be in {\"d\",\"f\",\"e\",\"E\",\"g\",\"G\", \"fg\", \"s\"}")
  attr(x,"display") <- value
  return(x)
}

display <- function(x,...) UseMethod("display")
display.xtable <- function(x,...) {
  return(attr(x,"display"))
}

### xtable 1.2-5  (2004/12/01)
###
### Produce LaTeX and HTML tables from R objects.
###
### Copyright 2000-2004 David B. Dahl <dahl@stat.tamu.edu>
###
### This file is part of the `xtable' library for R and related languages.
### It is made available under the terms of the GNU General Public
### License, version 2, or at your option, any later version,
### incorporated herein by reference.
###
### This program is distributed in the hope that it will be
### useful, but WITHOUT ANY WARRANTY; without even the implied
### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
### PURPOSE.  See the GNU General Public License for more
### details.
###
### You should have received a copy of the GNU General Public
### License along with this program; if not, write to the Free
### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
### MA 02111-1307, USA

xtable <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                   digits=NULL,display=NULL,...) {
  UseMethod("xtable")
}


## data.frame and matrix objects

xtable.data.frame <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                              digits=NULL,display=NULL,...) {
  characters <- unlist(lapply(x,is.character))
  factors <- unlist(lapply(x,is.factor))

  class(x) <- c("xtable","data.frame")
  caption(x) <- caption
  label(x) <- label
  align(x) <- switch(1+is.null(align), align,
                     c("r",c("r","l")[(characters|factors)+1]))
  vsep(x) <- switch(1+is.null(vsep), vsep,
                    rep("", ncol(x) + 2))
  digits(x) <- switch(1+is.null(digits),digits,c(0,rep(2,ncol(x))))
  display(x) <- switch(1+is.null(display),display,c("s",c("f","s")[(characters|factors)+1]))
  return(x)
}

xtable.matrix <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                          digits=NULL,display=NULL,...) {
  return(xtable.data.frame(data.frame(x,check.names=FALSE),
                           caption=caption,label=label,align=align, vsep=vsep,
                           digits=digits,display=display))
}


## anova objects

xtable.anova <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                         digits=NULL,display=NULL,...) {
  suggested.digits <- c(0,rep(2,ncol(x)))
  suggested.digits[grep("Pr\\(>",names(x))+1] <- 4
  suggested.digits[grep("P\\(>",names(x))+1] <- 4
  suggested.digits[grep("Df",names(x))+1] <- 0

  class(x) <- c("xtable","data.frame")
  caption(x) <- caption
  label(x) <- label
  align(x) <- switch(1+is.null(align),align,c("l",rep("r",ncol(x))))
  digits(x) <- switch(1+is.null(digits),digits,suggested.digits)
  display(x) <- switch(1+is.null(display),display,c("s",rep("f",ncol(x))))
  return(x)
}


## aov objects

xtable.aov <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                       digits=NULL,display=NULL,...) {
  return(xtable.anova(anova(x,...),caption=caption,label=label,
                      align=align, vsep=vsep, digits=digits,display=display))
}

xtable.summary.aov <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                               digits=NULL,display=NULL,...) {
  return(xtable.anova(x[[1]],caption=caption,label=label,
                      align=align, vsep=vsep, digits=digits,display=display))
}

xtable.aovlist <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                           digits=NULL,display=NULL,...) {
  return(xtable.summary.aovlist(summary(x),caption=caption,label=label,
                                align=align, vsep=vsep,
                                digits=digits,display=display))
}

xtable.summary.aovlist <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                                   digits=NULL,display=NULL,...) {
  for(i in 1:length(x)) {
    if (i==1) result <- xtable.summary.aov(x[[i]],caption=caption,label=label,
          align=align, vsep=vsep, digits=digits,display=display)
    else result <- rbind(result,xtable.anova(x[[i]][[1]],caption=caption,
                                             label=label,
                                             align=align, vsep=vsep,
                                             digits=digits,display=display))
  }
  return(result)
}


## lm objects

xtable.lm <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                      digits=NULL,display=NULL,...) {
  return(xtable.summary.lm(summary(x),caption=caption,label=label,
                           align=align, vsep=vsep, digits=digits,display=display))
}

xtable.summary.lm <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                              digits=NULL,display=NULL,...) {
  x <- data.frame(x$coef,check.names=FALSE)

  class(x) <- c("xtable","data.frame")
  caption(x) <- caption
  label(x) <- label
  align(x) <- switch(1+is.null(align),align,c("r","r","r","r","r"))
  vsep(x) <- switch(1+is.null(vsep), vsep,
                    rep("", ncol(x) + 2))
  digits(x) <- switch(1+is.null(digits),digits,c(0,4,4,2,4))
  display(x) <- switch(1+is.null(display),display,c("s","f","f","f","f"))
  return(x)
}


## glm objects

xtable.glm <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                       digits=NULL,display=NULL,...) {
  return(xtable.summary.glm(summary(x),caption=caption,label=label,align=align,vsep=vsep,
                            digits=digits,display=display))
}

xtable.summary.glm <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                               digits=NULL,display=NULL,...) {
  return(xtable.summary.lm(x,caption=caption,label=label,
                           align=align, vsep=vsep, digits=digits,display=display))
}


## prcomp objects

xtable.prcomp <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                          digits=NULL,display=NULL,...) {
  x <- data.frame(x$rotation,check.names=FALSE)

  class(x) <- c("xtable","data.frame")
  caption(x) <- caption
  label(x) <- label
  align(x) <- switch(1+is.null(align),align,c("r",rep("r",ncol(x))))
  vsep(x) <- switch(1+is.null(vsep), vsep, rep("", ncol(x) + 2))
  digits(x) <- switch(1+is.null(digits),digits,c(0,rep(4,ncol(x))))
  display(x) <- switch(1+is.null(display),display,c("s",rep("f",ncol(x))))
  return(x)
}

xtable.summary.prcomp <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                                  digits=NULL,display=NULL,...) {
  x <- data.frame(x$importance,check.names=FALSE)

  class(x) <- c("xtable","data.frame")
  caption(x) <- caption
  label(x) <- label
  align(x) <- switch(1+is.null(align),align,c("r",rep("r",ncol(x))))
  vsep(x) <- switch(1+is.null(vsep), vsep, rep("", ncol(x) + 2))
  digits(x) <- switch(1+is.null(digits),digits,c(0,rep(4,ncol(x))))
  display(x) <- switch(1+is.null(display),display,c("s",rep("f",ncol(x))))
  return(x)
}


# Slightly modified version of xtable.coxph contributed on r-help by
#   Date: Wed, 2 Oct 2002 17:47:56 -0500 (CDT)
#   From: Jun Yan <jyan@stat.wisc.edu>
#   Subject: Re: [R] xtable for Cox model output
xtable.coxph <- function (x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                          digits=NULL,display=NULL,...)
{
  cox <- x
  beta <- cox$coef
  se <- sqrt(diag(cox$var))
  if (is.null(cox$naive.var)) {
    tmp <- cbind(beta, exp(beta), se, beta/se, 1 - pchisq((beta/se)^2, 1))
    dimnames(tmp) <- list(names(beta),
      c("coef", "exp(coef)", "se(coef)", "z", "p"))
  }
  else {
    tmp <- cbind( beta, exp(beta), nse, se, beta/se,
      signif(1 - pchisq((beta/se)^2, 1), digits - 1))
    dimnames(tmp) <- list(names(beta),
      c("coef", "exp(coef)", "se(coef)", "robust se", "z", "p"))
  }
  return(xtable(tmp, caption = caption, label = label, align = align,
                vsep = vsep, digits = digits, display = display))
}

# Additional method: xtable.ts
# Contributed by David Mitchell (davidm@netspeed.com.au)
# Date: July 2003
xtable.ts <- function(x,caption=NULL,label=NULL,align=NULL,vsep=NULL,
                      digits=NULL,display=NULL,...) {

  if (inherits(x, "ts") && !is.null(ncol(x))) {
    # COLNAMES <- paste(colnames(x));
    tp.1 <- trunc(time(x))
    tp.2 <- trunc(cycle(x))
    day.abb <- c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
    ROWNAMES <- switch(frequency(x),
                       tp.1,
                       "Arg2", "Arg3",              ## Dummy arguments
                       paste(tp.1, c("Q1", "Q2", "Q3", "Q4")[tp.2], sep=" "),
                       "Arg5", "Arg6",
                       paste("Wk.", tp.1, " ", day.abb[tp.2], sep=""),
                       "Arg8", "Arg9", "Arg10", "Arg11",
                       paste(tp.1, month.abb[tp.2], sep=" "))
    tmp <- data.frame(x, row.names=ROWNAMES);
  }
  else if (inherits(x, "ts") && is.null(ncol(x))) {
    COLNAMES <- switch(frequency(x),
                       "Value",
                       "Arg2", "Arg3",              ## Dummy arguments
                       c("Q1", "Q2", "Q3", "Q4"),
                       "Arg5", "Arg6",
                       day.abb,
                       "Arg8", "Arg9", "Arg10", "Arg11",
                       month.abb)
    ROWNAMES <- seq(from=start(x)[1], to=end(x)[1])
    tmp <- data.frame(matrix(c(rep(NA, start(x)[2] - 1), x,
                               rep(NA, frequency(x) - end(x)[2])),
                             ncol=frequency(x)), row.names=ROWNAMES)
    names(tmp) <- COLNAMES
  }
  return(xtable(tmp, caption = caption, label = label, align = align,
                vsep = vsep, digits = digits, display = display))
}
