# Kaiser normalization

#NormalizingWeight <- function(A, normalize=FALSE){
# if ("function" == mode(normalize)) normalize <- normalize(A)
# if (is.logical(normalize)){
#    if (normalize) normalize <- sqrt(rowSums(A^2))
#    else return(array(1, dim(A)))
#    }
# if (is.vector(normalize)) 
#    {if(nrow(A) != length(normalize))
#        stop("normalize length wrong in NormalizingWeight")
#     return(array(normalize, dim(A)))
#    }
# stop("normalize argument not recognized in NormalizingWeight")
#}
# 

#
# Version below submitted by Kim-Laura Speck, Uni Kassel, 25 October 2023
#
# avoid NaNs in matrix A by adding machine precision values to zeros


NormalizingWeight <- function(A, normalize = FALSE) {

  if (is.function(normalize)) normalize <- normalize(A)

  # String shortcuts --- convert to weight vector
  if (is.character(normalize)) {
    normalize <- switch(normalize,
      Kaiser = pmax(sqrt(rowSums(A^2)), .Machine$double.eps),
      CM     = {
        Dk    <- diag(1 / pmax(sqrt(diag(A %*% t(A))),
                               .Machine$double.eps)) %*% A
        wghts <- rep(0, nrow(A))
        fpls  <- Dk[, 1]
        acosi <- acos(ncol(A)^(-1/2))
        for (i in 1:nrow(A)) {
          num      <- acosi - acos(abs(fpls[i]))
          dem      <- acosi - (function(a, m)
                        ifelse(abs(a) < (m^(-1/2)), pi/2, 0))(fpls[i], ncol(A))
          wghts[i] <- cos(num / dem * pi/2)^2 + 0.001
        }
        wghts / pmax(sqrt(diag(A %*% t(A))), .Machine$double.eps)
      },
      stop("normalize string not recognized in NormalizingWeight", call. = FALSE)
    )
  }

  # Logical shortcut --- TRUE maps to Kaiser
  if (is.logical(normalize)) {
    if (normalize)
      normalize <- pmax(sqrt(rowSums(A^2)), .Machine$double.eps)
    else
      return(array(1, dim(A)))
  }

  # Weight vector --- apply to all columns
  if (is.vector(normalize)) {
    if (nrow(A) != length(normalize))
      stop("normalize length wrong in NormalizingWeight", call. = FALSE)
    return(matrix(normalize, nrow(A), ncol(A)))
  }

  stop("normalize argument not recognized in NormalizingWeight", call. = FALSE)
}
  