RMS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, 
                limits = NULL, siglev = 0.95, conf = TRUE, parallel = FALSE,
                ncores = NULL) {       
  #
  #  Remove data along compROW dim if there is at least one NA between limits
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  if (is.null(compROW) == FALSE) {
    if (is.null(limits) == TRUE) {
      limits <- c(1, dim(var_obs)[compROW])
    }
    outrows <- (is.na(Mean1Dim(var_obs, compROW, narm = FALSE, limits))) 
    outrows <- InsertDim(outrows, compROW, dim(var_obs)[compROW])
    var_obs[which(outrows)] <- NA
  }
  
  #
  #  Enlarge var_exp & var_obs to 10 dim + move posloop & posRMS to 1st & 2nd 
  #  pos 
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  dimsvar <- dim(var_exp)
  dim_names <- names(dim(var_exp))
  for (iind in 1:length(dimsvar)) {
    if (iind != posloop & dim(var_obs)[iind] != dimsvar[iind]) { 
      stop("var_exp & var_obs must have same dimensions except along posloop")
    }
  }
  if (dimsvar[posRMS] < 2 ) {
    stop("At least 2 values required to compute RMSE")
  }
  if (is.null(dim(var_exp))) {
    var_exp <- Insert1Dim(var_exp, 1, 1)
    var_obs <- Insert1Dim(var_obs, 1, 1)
  }

  #
  #  RMS & its confidence interval computation
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  var_exp <- aperm(var_exp, c(posloop, posRMS, c(1:length(dim(var_exp)))[-c(posloop, posRMS)]))
  var_obs <- aperm(var_obs, c(posloop, posRMS, c(1 :length(dim(var_obs)))[-c(posloop, posRMS)]))
  margins <- list(c(1 : length(dim(var_exp)))[-2], c(1 : length(dim(var_obs)))[-2])   
  
  RMS <- Apply(list(var_exp, var_obs), margins = margins, AtomicFun = ".RMS", 
                siglev = siglev, conf = conf, parallel = parallel, ncores = ncores)
  #  
  #  Output
  # ~~~~~~~~
  #
  names(dim(RMS))[2 : length(dim(RMS))] <- dim_names[-posRMS]
  RMS
}

.RMS <- function(exp, obs, siglev = 0.95, conf = TRUE) {       
  #
  #  RMS & its confidence interval computation
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  if (conf) {
    conf_low <- (1 - siglev) / 2
    conf_high <- 1 - conf_low
  }
  if (is.matrix(exp)) {
    dif <- rowMeans(exp) - obs
  } else {
    dif <- exp - obs
  }
  enlrms <- mean(dif ** 2, na.rm = TRUE) ** 0.5
  if (conf) {
    eno <- Eno(dif, 1)
    ndat <- length(sort(dif))
    conf_int <- c((eno * enlrms ** 2 / qchisq(conf_high, eno - 1)) ** 0.5,
                  (eno * enlrms ** 2 / qchisq(conf_low, eno - 1)) ** 0.5)
    names(conf_int) <- c("conf_low","conf_high")
  } else {
    conf_int <- c()
    names(conf_int) <- c() 
  }

  results <- c(conf_int[1], enlrms, conf_int[2]) 
  return(results)
}
