001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.statistics.distribution;
018
019import org.apache.commons.numbers.gamma.Gamma;
020import org.apache.commons.numbers.gamma.RegularizedGamma;
021
022/**
023 * This class implements the <a href="http://en.wikipedia.org/wiki/Nakagami_distribution">Nakagami distribution</a>.
024 */
025public class NakagamiDistribution extends AbstractContinuousDistribution {
026    /** Support lower bound. */
027    private static final double SUPPORT_LO = 0;
028    /** Support upper bound. */
029    private static final double SUPPORT_HI = Double.POSITIVE_INFINITY;
030    /** The minimum allowed for the shape parameter. */
031    private static final double MIN_SHAPE = 0.5;
032
033    /** The shape parameter. */
034    private final double mu;
035    /** The scale parameter. */
036    private final double omega;
037
038    /**
039     * Creates a distribution.
040     *
041     * @param mu shape parameter
042     * @param omega scale parameter (must be positive)
043     * @throws IllegalArgumentException  if {@code mu < 0.5} or if
044     * {@code omega <= 0}.
045     */
046    public NakagamiDistribution(double mu,
047                                double omega) {
048        if (mu < MIN_SHAPE) {
049            throw new DistributionException(DistributionException.TOO_SMALL, mu, MIN_SHAPE);
050        }
051        if (omega <= 0) {
052            throw new DistributionException(DistributionException.NEGATIVE, omega);
053        }
054
055        this.mu = mu;
056        this.omega = omega;
057    }
058
059    /**
060     * Access the shape parameter, {@code mu}.
061     *
062     * @return the shape parameter.
063     */
064    public double getShape() {
065        return mu;
066    }
067
068    /**
069     * Access the scale parameter, {@code omega}.
070     *
071     * @return the scale parameter.
072     */
073    public double getScale() {
074        return omega;
075    }
076
077    /** {@inheritDoc} */
078    @Override
079    public double density(double x) {
080        if (x <= SUPPORT_LO ||
081            x >= SUPPORT_HI) {
082            return 0;
083        }
084
085        return 2.0 * Math.pow(mu, mu) / (Gamma.value(mu) * Math.pow(omega, mu)) *
086                     Math.pow(x, 2 * mu - 1) * Math.exp(-mu * x * x / omega);
087    }
088
089    /** {@inheritDoc} */
090    @Override
091    public double cumulativeProbability(double x) {
092        if (x <= SUPPORT_LO) {
093            return 0;
094        } else if (x >= SUPPORT_HI) {
095            return 1;
096        }
097
098        return RegularizedGamma.P.value(mu, mu * x * x / omega);
099    }
100
101    /** {@inheritDoc} */
102    @Override
103    public double getMean() {
104        return Gamma.value(mu + 0.5) / Gamma.value(mu) * Math.sqrt(omega / mu);
105    }
106
107    /** {@inheritDoc} */
108    @Override
109    public double getVariance() {
110        final double v = Gamma.value(mu + 0.5) / Gamma.value(mu);
111        return omega * (1 - 1 / mu * v * v);
112    }
113
114    /** {@inheritDoc} */
115    @Override
116    public double getSupportLowerBound() {
117        return SUPPORT_LO;
118    }
119
120    /** {@inheritDoc} */
121    @Override
122    public double getSupportUpperBound() {
123        return SUPPORT_HI;
124    }
125
126    /** {@inheritDoc} */
127    @Override
128    public boolean isSupportConnected() {
129        return true;
130    }
131
132}