/
gammas.R
127 lines (117 loc) · 4.04 KB
/
gammas.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# gammas.R
# CholWishart: Sample the Cholesky Factor of the Wishart and Other Functions
# Copyright (C) 2018 GZ Thompson <gzthompson@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# 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, a copy is available at
# https://www.R-project.org/Licenses/
#' Multivariate Gamma Function
#'
#' @description A special mathematical function related to the gamma function,
#' generalized for multivariate gammas. \code{lmvgamma} is the log of the
#' multivariate gamma, \code{mvgamma}.
#'
#' The multivariate gamma function for a dimension p is defined as:
#'
#' \deqn{\Gamma_{p}(a)=\pi^{p(p-1)/4}\prod_{j=1}^{p}
#' \Gamma [a+(1-j)/2]}{Gamma_p(a)=\pi^{p(p-1)/4}* Prod_{j=1}^{p}
#' \Gamma[a+(1-j)/2]}
#' For \eqn{p = 1}, this is the same as the usual gamma function.
#' @param x non-negative numeric vector, matrix, or array
#' @param p positive integer, dimension of a square matrix
#'
#' @return For \code{lmvgamma} log of multivariate gamma of dimension \code{p}
#' for each entry of \code{x}. For non-log variant,
#' use \code{mvgamma}.
#'
#' @seealso \code{\link{gamma}} and \code{\link{lgamma}}
#' @references
#' A. K. Gupta and D. K. Nagar 1999. \emph{Matrix variate distributions}.
#' Chapman and Hall.
#'
#' Multivariate gamma function.
#' In \emph{Wikipedia, The Free Encyclopedia},from
#' \url{https://en.wikipedia.org/w/index.php?title=Multivariate_gamma_function}
#'
#' @export
#'
#' @examples
#' lgamma(1:12)
#' lmvgamma(1:12, 1L)
#' mvgamma(1:12, 1L)
#' gamma(1:12)
lmvgamma <- function(x, p) {
if (!all(is.numeric(x), is.numeric(p))) {
stop("non-numeric input")
}
# making sure that object
# returned is same shape as object passed
dims <- if (is.vector(x)) {
length(x)
} else {
dim(as.array(x))
}
result <- .Call("C_lmvgamma", as.numeric(x), as.integer(p),
PACKAGE = "CholWishart"
)
return(array(result, dim = dims))
}
#' @describeIn lmvgamma Multivariate gamma function.
#' @export
mvgamma <- function(x, p) {
exp(lmvgamma(x, p))
}
#' Multivariate Digamma Function
#'
#' @description A special mathematical function related to the gamma function,
#' generalized for multivariate distributions.
#' The multivariate digamma function is the derivative of the log of the
#' multivariate gamma function; for \eqn{p = 1} it is the same as the
#' univariate digamma function.
#'
#' \deqn{\psi_{p}(a)=\sum _{i=1}^{p}\psi(a+(1-i)/2)
#' }{psi_p(a)=\sum psi(a+(1-i)/2)}
#' where \eqn{\psi}{psi} is the univariate digamma function (the
#' derivative of the log-gamma function).
#' @param x non-negative numeric vector, matrix, or array
#' @param p positive integer, dimension of a square matrix
#' @return vector of values of multivariate digamma function.
#'
#' @seealso \code{\link{gamma}}, \code{\link{lgamma}},
#' \code{\link{digamma}}, and \code{\link{mvgamma}}
#' @export
#' @references
#' A. K. Gupta and D. K. Nagar 1999. \emph{Matrix variate distributions}.
#' Chapman and Hall.
#'
#' Multivariate gamma function.
#' In \emph{Wikipedia, The Free Encyclopedia},from
#' \url{https://en.wikipedia.org/w/index.php?title=Multivariate_gamma_function}
#'
#' @examples
#' digamma(1:10)
#' mvdigamma(1:10, 1L)
mvdigamma <- function(x, p) {
if (!all(is.numeric(x), is.numeric(p))) {
stop("non-numeric input")
}
dims <- if (is.vector(x)) {
length(x)
} else {
dim(as.array(x))
}
result <- .Call("C_mvdigamma", as.numeric(x), as.integer(p),
PACKAGE = "CholWishart"
)
return(array(result, dim = dims))
}