/*
 * 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.core.source64;

import java.util.List;
import java.util.ArrayList;
import org.apache.commons.rng.core.util.NumberFactory;

/**
 * Random number generator designed by Mark D.&nbsp;Overton.
 *
 * <p>It is one of the many generators described by the author in the following article series:</p>
 *  <ul>
 *   <li><a href="http://www.drdobbs.com/tools/fast-high-quality-parallel-random-number/229625477">Part one</a></li>
 *   <li><a href="http://www.drdobbs.com/tools/fast-high-quality-parallel-random-number/231000484">Part two</a></li>
 *  </ul>
 *
 * @since 1.0
 */
public class TwoCmres extends LongProvider {
    /** Error message. */
    private static final String INTERNAL_ERROR_MSG = "Internal error: Please file a bug report";
    /** A small positive integer. */
    private static final byte SEED_GUARD = 9;
    /** Factory of instances of this class. Singleton. */
    private static final Cmres.Factory FACTORY = new Cmres.Factory();
    /** First subcycle generator. */
    private final Cmres x;
    /** Second subcycle generator. */
    private final Cmres y;
    /** State of first subcycle generator. */
    private long xx;
    /** State of second subcycle generator. */
    private long yy;

    /**
     * Creates a new instance.
     *
     * @param seed Initial seed.
     * @param x First subcycle generator.
     * @param y Second subcycle generator.
     * @throws IllegalArgumentException if {@code x == y}.
     */
    private TwoCmres(int seed,
                     Cmres x,
                     Cmres y) {
        if (x.equals(y)) {
            throw new IllegalArgumentException("Subcycle generators must be different");
        }
        this.x = x;
        this.y = y;
        setSeedInternal(seed);
    }

    /**
     * Creates a new instance.
     *
     * @param seed Seed.
     */
    public TwoCmres(Integer seed) {
        this(seed, 0, 1);
    }

    /**
     * Creates a new instance.
     *
     * @param seed Seed.
     * @param i Table entry for first subcycle generator.
     * @param j Table entry for second subcycle generator.
     * @throws IllegalArgumentException if {@code i == j}.
     * @throws IndexOutOfBoundsException if {@code i < 0} or
     * {@code i >= numberOfSubcycleGenerators()}.
     * @throws IndexOutOfBoundsException if {@code j < 0} or
     * {@code j >= numberOfSubcycleGenerators()}.
     */
    public TwoCmres(Integer seed,
                    int i,
                    int j) {
        this(seed, FACTORY.get(i), FACTORY.get(j));
    }

    /** {@inheritDoc} */
    @Override
    public long next() {
        xx = x.transform(xx);
        yy = y.transform(yy);

        return xx + yy;
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return super.toString() + " (" + x + " + " + y + ")";
    }

    /**
     * @return the number of subcycle generators.
     */
    public static int numberOfSubcycleGenerators() {
        return FACTORY.numberOfSubcycleGenerators();
    }

    /** {@inheritDoc} */
    @Override
    protected byte[] getStateInternal() {
        return composeStateInternal(NumberFactory.makeByteArray(new long[] {xx, yy}),
                                    super.getStateInternal());
    }

    /** {@inheritDoc} */
    @Override
    protected void setStateInternal(byte[] s) {
        final byte[][] c = splitStateInternal(s, 16);

        final long[] state = NumberFactory.makeLongArray(c[0]);
        xx = state[0];
        yy = state[1];

        super.setStateInternal(c[1]);
    }

    /**
     * @param seed Seed.
     */
    private void setSeedInternal(int seed) {
        // The seeding procedure consists in going away from some
        // point known to be in the cycle.
        // The total number of calls to the "transform" method will
        // not exceed about 130,000 (which is negligible as seeding
        // will not occur more than once in normal usage).

        // Make two positive 16-bits integers from the 32-bit seed.
        // Add the small positive seed guard. The result will never be negative.
        final int xMax = (seed & 0xffff) + (SEED_GUARD & 0xff);
        final int yMax = (seed >>> 16)   + (SEED_GUARD & 0xff);

        xx = x.getStart();
        for (int i = xMax; i > 0; i--) {
            xx = x.transform(xx);
        }

        yy = y.getStart();
        for (int i = yMax; i > 0; i--) {
            yy = y.transform(yy);
        }
    }

    /**
     * Subcycle generator.
     * Class is immutable.
     */
    static class Cmres {
        /** Separator. */
        private static final String SEP = ", ";
        /** Hexadecimal format. */
        private static final String HEX_FORMAT = "0x%016xL";
        /** Cycle start. */
        private final int start;
        /** Multiplier. */
        private final long multiply;
        /** Rotation. */
        private final int rotate;

        /**
         * @param multiply Multiplier.
         * @param rotate Positive number. Must be in {@code [0, 64]}.
         * @param start Cycle start.
         */
        Cmres(long multiply,
              int rotate,
              int start) {
            this.multiply = multiply;
            this.rotate = rotate;
            this.start = start;
        }

        /** {@inheritDoc} */
        @Override
        public String toString() {
            final String m = String.format((java.util.Locale) null, HEX_FORMAT, multiply);
            return "Cmres: [" + m + SEP + rotate + SEP + start + "]";
        }

        /**
         * @return the multiplier.
         */
        public long getMultiply() {
            return multiply;
        }

        /**
         * @return the cycle start.
         */
        public int getStart() {
            return start;
        }

        /**
         * @param state Current state.
         * @return the new state.
         */
        long transform(long state) {
            long s = state;
            s *= multiply;
            s = Long.rotateLeft(s, rotate);
            s -= state;
            return s;
        }

        /** Factory. */
        static class Factory {
            /** List of good "Cmres" subcycle generators. */
            private static final List<Cmres> TABLE = new ArrayList<Cmres>();

            /*
             * Populates the table.
             * It lists parameters known to be good (provided in
             * the article referred to above).
             * To maintain compatibility, new entries must be added
             * only at the end of the table.
             */
            static {
                add(0xedce446814d3b3d9L, 33, 0x13b572e7);
                add(0xc5b3cf786c806df7L, 33, 0x13c8e18a);
                add(0xdd91bbb8ab9e0e65L, 31, 0x06dd03a6);
                add(0x7b69342c0790221dL, 31, 0x1646bb8b);
                add(0x0c72c0d18614c32bL, 33, 0x06014a3d);
                add(0xd8d98c13bebe26c9L, 33, 0x014e8475);
                add(0xcb039dc328bbc40fL, 31, 0x008684bd);
                add(0x858c5ef3c021ed2fL, 32, 0x0dc8d622);
                add(0x4c8be96bfc23b127L, 33, 0x0b6b20cc);
                add(0x11eab77f808cf641L, 32, 0x06534421);
                add(0xbc9bd78810fd28fdL, 31, 0x1d9ba40d);
                add(0x0f1505c780688cb5L, 33, 0x0b7b7b67);
                add(0xadc174babc2053afL, 31, 0x267f4197);
                add(0x900b6b82b31686d9L, 31, 0x023c6985);
                // Add new entries here.
            }

            /**
             * @return the number of subcycle generators.
             */
            int numberOfSubcycleGenerators() {
                return TABLE.size();
            }

            /**
             * @param index Index into the list of available generators.
             * @return the subcycle generator entry at index {@code index}.
             */
            Cmres get(int index) {
                if (index < 0 ||
                    index >= TABLE.size()) {
                    throw new IndexOutOfBoundsException("Out of interval [0, " +
                                                        (TABLE.size() - 1) + "]");
                }

                return TABLE.get(index);
            }

            /**
             * Adds an entry to the {@link Factory#TABLE}.
             *
             * @param multiply Multiplier.
             * @param rotate Rotate.
             * @param start Cycle start.
             */
            private static void add(long multiply,
                                    int rotate,
                                    int start) {
                // Sanity check: if there are duplicates, the class initialization
                // will fail (and the JVM will report "NoClassDefFoundError").
                checkUnique(TABLE, multiply);

                TABLE.add(new Cmres(multiply, rotate, start));
            }

            /**
             * Check the multiply parameter is unique (not contained in any entry in the provided
             * table).
             *
             * @param table the table
             * @param multiply the multiply parameter
             */
            static void checkUnique(List<Cmres> table, long multiply) {
                for (final Cmres sg : table) {
                    if (multiply == sg.getMultiply()) {
                        throw new IllegalStateException(INTERNAL_ERROR_MSG);
                    }
                }
            }
        }
    }
}
