mcsim <-
  function(B, r, grouping_matrix, stat, verbose){
    stopifnot(isTRUE(as.integer(B) == B), identical(length(B), 1L),
              is.matrix(r), is.numeric(r))
    n <- nrow(r)
    tr <- t(r)
    if(is.null(grouping_matrix)){
      order_for_calc_epsp <- seq_len(n)
    } else {
      stopifnot(is.numeric(grouping_matrix), is.matrix(grouping_matrix),
                identical(nrow(r), nrow(grouping_matrix)))
      order_for_calc_epsp <- seq_len(ncol(grouping_matrix))
      proj_matrix <- grouping_matrix - r %*% (tr %*% grouping_matrix)
    }
    output <- matrix(NA, nrow = B, ncol = length(stat))
    for(i in seq_len(B)){
      if(isTRUE(verbose) && isTRUE(i %% as.integer(B/10) == 0))
        message("...", i, " of ", B)
      epsilon <- matrix(rnorm(n))
      if(is.null(grouping_matrix)){
        e_proj <- as.vector(epsilon - r %*% (tr %*% epsilon))
      } else {
        e_proj <- as.vector(t(epsilon) %*% proj_matrix)
      }
      epsp <- calc_epsp(transformed_residuals = e_proj, res_order = order_for_calc_epsp,
                        grouping_matrix = NULL)
      output[i,] <- calc_stats(epsp = epsp, stat = stat)
    }
    output <- as.list(as.data.frame(output))
    names(output) <- stat
    return(output)
  }
