/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.rng.sampling.distribution;

import org.apache.commons.rng.UniformRandomProvider;

/**
 * Sampling from an <a href="http://mathworld.wolfram.com/ExponentialDistribution.html">exponential distribution</a>.
 *
 * <p>Sampling uses {@link UniformRandomProvider#nextDouble()}.</p>
 *
 * @since 1.0
 */
public class AhrensDieterExponentialSampler
    extends SamplerBase
    implements SharedStateContinuousSampler {
    /**
     * Table containing the constants
     * \( q_i = sum_{j=1}^i (\ln 2)^j / j! = \ln 2 + (\ln 2)^2 / 2 + ... + (\ln 2)^i / i! \)
     * until the largest representable fraction below 1 is exceeded.
     *
     * Note that
     * \( 1 = 2 - 1 = \exp(\ln 2) - 1 = sum_{n=1}^\infinity (\ln 2)^n / n! \)
     * thus \( q_i \rightarrow 1 as i \rightarrow +\infinity \),
     * so the higher \( i \), the closer we get to 1 (the series is not alternating).
     *
     * By trying, n = 16 in Java is enough to reach 1.
     */
    private static final double[] EXPONENTIAL_SA_QI = new double[16];
    /** The mean of this distribution. */
    private final double mean;
    /** Underlying source of randomness. */
    private final UniformRandomProvider rng;

    /**
     * Initialize tables.
     */
    static {
        /**
         * Filling EXPONENTIAL_SA_QI table.
         * Note that we don't want qi = 0 in the table.
         */
        final double ln2 = Math.log(2);
        double qi = 0;

        for (int i = 0; i < EXPONENTIAL_SA_QI.length; i++) {
            qi += Math.pow(ln2, i + 1.0) / InternalUtils.factorial(i + 1);
            EXPONENTIAL_SA_QI[i] = qi;
        }
    }

    /**
     * @param rng Generator of uniformly distributed random numbers.
     * @param mean Mean of this distribution.
     * @throws IllegalArgumentException if {@code mean <= 0}
     */
    public AhrensDieterExponentialSampler(UniformRandomProvider rng,
                                          double mean) {
        super(null);
        if (mean <= 0) {
            throw new IllegalArgumentException("mean is not strictly positive: " + mean);
        }
        this.rng = rng;
        this.mean = mean;
    }

    /**
     * @param rng Generator of uniformly distributed random numbers.
     * @param source Source to copy.
     */
    private AhrensDieterExponentialSampler(UniformRandomProvider rng,
                                           AhrensDieterExponentialSampler source) {
        super(null);
        this.rng = rng;
        this.mean = source.mean;
    }

    /** {@inheritDoc} */
    @Override
    public double sample() {
        // Step 1:
        double a = 0;
        double u = rng.nextDouble();

        // Step 2 and 3:
        while (u < 0.5) {
            a += EXPONENTIAL_SA_QI[0];
            u *= 2;
        }

        // Step 4 (now u >= 0.5):
        u += u - 1;

        // Step 5:
        if (u <= EXPONENTIAL_SA_QI[0]) {
            return mean * (a + u);
        }

        // Step 6:
        int i = 0; // Should be 1, be we iterate before it in while using 0.
        double u2 = rng.nextDouble();
        double umin = u2;

        // Step 7 and 8:
        do {
            ++i;
            u2 = rng.nextDouble();

            if (u2 < umin) {
                umin = u2;
            }

            // Step 8:
        } while (u > EXPONENTIAL_SA_QI[i]); // Ensured to exit since EXPONENTIAL_SA_QI[MAX] = 1.

        return mean * (a + umin * EXPONENTIAL_SA_QI[0]);
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return "Ahrens-Dieter Exponential deviate [" + rng.toString() + "]";
    }

    /**
     * {@inheritDoc}
     *
     * @since 1.3
     */
    @Override
    public SharedStateContinuousSampler withUniformRandomProvider(UniformRandomProvider rng) {
        return new AhrensDieterExponentialSampler(rng, this);
    }

    /**
     * Create a new exponential distribution sampler.
     *
     * @param rng Generator of uniformly distributed random numbers.
     * @param mean Mean of the distribution.
     * @return the sampler
     * @throws IllegalArgumentException if {@code mean <= 0}
     * @since 1.3
     */
    public static SharedStateContinuousSampler of(UniformRandomProvider rng,
                                                  double mean) {
        return new AhrensDieterExponentialSampler(rng, mean);
    }
}
