private double density(double x) { // Based on the function randVMFMeanDir, available in the // SphericalDistributionsRand repository under BSD license, // originally written by Yu-Hui Chen, University of Michigan. // https://github.com/yuhuichen1015/SphericalDistributionsRand int p = Dimension; double g1 = Gamma.Function((p - 1.0) / 2.0); double g2 = Gamma.Function(1.0 / 2.0); double bi = Bessel.I(p / 2 - 1, kappa); double num = Math.Pow(kappa / 2.0, p / 2.0 - 1.0); double den = g1 * g2 * bi; double c = num / den; double a = Math.Exp(kappa * x); double b = Math.Pow(1.0 - x * x, (p - 3.0) / 2.0); double y = c * a * b; return(y); }
/// <summary> /// Constructs a Von-Mises Fisher distribution with unit mean. /// </summary> /// /// <param name="mean">The mean direction vector (with unit length).</param> /// <param name="concentration">The concentration value κ (kappa).</param> /// public VonMisesFisherDistribution(double[] mean, double concentration) : base(mean.Length) { if (concentration < 0) { throw new ArgumentOutOfRangeException("concentration", "Concentration parameter kappa must be non-negative."); } if (!Norm.Euclidean(mean).IsRelativelyEqual(1, 1e-10)) { throw new ArgumentOutOfRangeException("mean", "The mean vector must have unit length."); } this.mean = mean; this.kappa = concentration; int p = Dimension; double num = Math.Pow(concentration, p / 2 - 1); double den = Math.Pow(2 * Math.PI, p / 2) * Bessel.I(p / 2 - 1, concentration); this.constant = num / den; }