/*
 * 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.logging.log4j.perf.nogc;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.StringMap;
import org.apache.logging.log4j.spi.ThreadContextMap;
import org.apache.logging.log4j.util.BiConsumer;
import org.apache.logging.log4j.util.TriConsumer;

/**
 * Open hash map-based implementation of the {@code ReadOnlyStringMap} interface.
 * Implementation based on <a href="http://fastutil.di.unimi.it/">fastutil</a>'s
 * <a href="http://fastutil.di.unimi.it/docs/it/unimi/dsi/fastutil/objects/Object2ObjectOpenHashMap.html">Object2ObjectOpenHashMap</a>.
 * <p>
 * A type-specific hash map with a fast, small-footprint implementation.
 *
 * <P>
 * Instances of this class use a hash table to represent a map. The table is
 * filled up to a specified <em>load factor</em>, and then doubled in size to
 * accommodate new entries. If the table is emptied below <em>one fourth</em> of
 * the load factor, it is halved in size. However, halving is not performed when
 * deleting entries from an iterator, as it would interfere with the iteration
 * process.
 *
 * <p>
 * Note that {@link #clear()} does not modify the hash table size. Rather, the
 * {@link #trim(int)} method lets you control the size of
 * the table; this is particularly useful if you reuse instances of this class.
 * <p>
 * <ul>
 *   <li>Garbage-free iteration over key-value pairs with {@code BiConsumer} and {@code TriConsumer}.</li>
 *   <li>Fast copy. If the ThreadContextMap is also an instance of {@code OpenHashStringMap},
 *     the full thread context data can be transferred with two array copies and five field updates.</li>
 * </ul>
 *
 * @since 2.7
 */
public class OpenHashStringMap<K, V> implements StringMap, ThreadContextMap {
    /** The initial default size of a hash table. */
    public static final int DEFAULT_INITIAL_SIZE = 16;

    /** The default load factor of a hash table. */
    public static final float DEFAULT_LOAD_FACTOR = .75f;

    private static final String FROZEN = "Frozen collection cannot be modified";
    private static final long serialVersionUID = -1486744623338827187L;

    /** The array of keys. */
    protected transient K[] keys;
    /** The array of values. */
    protected transient V[] values;
    /** The mask for wrapping a position counter. */
    protected transient int mask;
    /** Whether this set contains the key zero. */
    protected transient boolean containsNullKey;
    /** The current table size. */
    protected transient int arraySize;
    /**
     * Threshold after which we rehash. It must be the table size times {@link #loadFactor}.
     */
    protected transient int maxFill;
    /** Number of entries in the set (including the key zero, if present). */
    protected int size;
    /** The acceptable load factor. */
    protected final float loadFactor;

    private final V defRetValue = null;
    private boolean immutable;
    private transient boolean iterating;

    /**
     * Creates a new hash map with initial expected
     * {@link #DEFAULT_INITIAL_SIZE} entries and
     * {@link #DEFAULT_LOAD_FACTOR} as load factor.
     */
    public OpenHashStringMap() {
        this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR);
    }
    /**
     * Creates a new hash map with {@link #DEFAULT_LOAD_FACTOR} as load factor.
     *
     * @param expected
     *            the expected number of elements in the hash map.
     */
    public OpenHashStringMap(final int expected) {
        this(expected, DEFAULT_LOAD_FACTOR);
    }
    /**
     * Creates a new hash map.
     *
     * <p>
     * The actual table size will be the least power of two greater than
     * <code>expected</code>/<code>f</code>.
     *
     * @param expected
     *            the expected number of elements in the hash set.
     * @param f
     *            the load factor.
     */
    @SuppressWarnings("unchecked")
    public OpenHashStringMap(final int expected, final float f) {
        if (f <= 0 || f > 1) {
            throw new IllegalArgumentException(
                    "Load factor must be greater than 0 and smaller than or equal to 1");
        }
        if (expected < 0){
            throw new IllegalArgumentException(
                    "The expected number of elements must be nonnegative");
        }
        this.loadFactor = f;
        arraySize = HashCommon.arraySize(expected, f);
        mask = arraySize - 1;
        maxFill = HashCommon.maxFill(arraySize, f);
        keys = (K[]) new Object[arraySize + 1];
        values = (V[]) new Object[arraySize + 1];
    }
    /**
     * Creates a new hash map with {@link #DEFAULT_LOAD_FACTOR} as load
     * factor copying a given one.
     *
     * @param map
     *            a {@link Map} to be copied into the new hash map.
     */
    public OpenHashStringMap(final Map<? extends K, ? extends V> map) {
        this(map, DEFAULT_LOAD_FACTOR);
    }
    /**
     * Creates a new hash map copying a given one.
     *
     * @param map
     *            a {@link Map} to be copied into the new hash map.
     * @param f
     *            the load factor.
     */
    public OpenHashStringMap(final Map<? extends K, ? extends V> map, final float f) {
        this(map.size(), f);
        putAll(map);
    }

    /**
     * Creates a new hash map with {@link #DEFAULT_LOAD_FACTOR} as load
     * factor copying a given type-specific one.
     *
     * @param contextData
     *            a type-specific map to be copied into the new hash map.
     */
    public OpenHashStringMap(final ReadOnlyStringMap contextData) {
        this(contextData, DEFAULT_LOAD_FACTOR);
    }
    /**
     * Creates a new hash map copying a given type-specific one.
     *
     * @param contextData
     *            a type-specific map to be copied into the new hash map.
     * @param f
     *            the load factor.
     */
    public OpenHashStringMap(final ReadOnlyStringMap contextData, final float f) {
        this(contextData.size(), f);
        if (contextData instanceof OpenHashStringMap) {
            initFrom0((OpenHashStringMap) contextData);
        } else {
            contextData.forEach(PUT_ALL, this);
        }
    }
    private static final TriConsumer<String, Object, StringMap> PUT_ALL =
            (key, value, contextData) -> contextData.putValue(key, value);

    private void assertNotFrozen() {
        if (immutable) {
            throw new UnsupportedOperationException(FROZEN);
        }
    }

    private void assertNoConcurrentModification() {
        if (iterating) {
            throw new ConcurrentModificationException();
        }
    }

    @SuppressWarnings("unchecked")
    private void initFrom0(final OpenHashStringMap other) {
        // this.loadFactor = other.loadFactor; // final field
        this.arraySize = other.arraySize;
        this.size = other.size;
        this.containsNullKey = other.containsNullKey;
        this.mask = other.mask;
        this.maxFill = other.maxFill;
        keys = (K[]) Arrays.copyOf(other.keys, arraySize + 1);
        values = (V[]) Arrays.copyOf(other.values, arraySize + 1);
    }

    private int realSize() {
        return containsNullKey ? size - 1 : size;
    }

    private void ensureCapacity(final int capacity) {
        final int needed = HashCommon.arraySize(capacity, loadFactor);
        if (needed > arraySize) {
            rehash(needed);
        }
    }

    private void tryCapacity(final long capacity) {
        final int needed = Math.min(
                1 << 30, Math.max(2, HashCommon.nextPowerOfTwo((int) Math.ceil(capacity / loadFactor))));
        if (needed > arraySize) {
            rehash(needed);
        }
    }

    @Override
    public Map<String, String> toMap() {
        final Map<String, String> result = new HashMap<>(size);
        forEach(COPY_INTO_MAP, result);
        return result;
    }

    private static final TriConsumer<String, Object, Map<String, String>> COPY_INTO_MAP =
            (k, v, map) -> map.put(k, v == null ? null : v.toString());

    /*
     * Removes all elements from this map.
     *
     * <P>To increase object reuse, this method does not change the table size.
     * If you want to reduce the table size, you must use {@link #trim()}.
     */
    @Override
    public void clear() {
        if (size == 0) {
            return;
        }
        assertNotFrozen();
        assertNoConcurrentModification();

        size = 0;
        containsNullKey = false;
        Arrays.fill(keys, (null));
        Arrays.fill(values, null);
    }

    @Override
    public boolean containsKey(final String key) {
        return containsObjectKey(key);
    }

    @SuppressWarnings("unchecked")
    private boolean containsObjectKey(final Object k) {
        if (k == null) {
            return containsNullKey;
        }
        K curr;
        final K[] key = this.keys;
        int pos;
        // The starting point.
        if ((curr = key[pos = HashCommon.mix(k.hashCode()) & mask]) == null) {
            return false;
        }
        if (k.equals(curr)) {
            return true;
        }
        // There's always an unused entry.
        while (true) {
            if ((curr = key[pos = (pos + 1) & mask]) == null) {
                return false;
            }
            if (k.equals(curr)) {
                return true;
            }
        }
    }

    @Override
	public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof ReadOnlyStringMap)) {
            return false;
        }
        final ReadOnlyStringMap other = (ReadOnlyStringMap) obj;
        if (other.size() != size()) {
            return false;
        }
        int pos = arraySize;
        if (containsNullKey) {
            if (!Objects.equals(getObjectValue(null), other.getValue(null))) {
                return false;
            }
        }
        --pos;
        final K myKeys[] = this.keys;
        for (; pos >= 0; pos--) {
            K k;
            if ((k = myKeys[pos]) != null) {
                if (!Objects.equals(values[pos], other.getValue((String) k))) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <VAL> void forEach(final BiConsumer<String, ? super VAL> action) {
        final int startSize = size;
        final K myKeys[] = this.keys;
        int pos = arraySize;

        iterating = true;
        try {
            if (containsNullKey) {
                action.accept((String) myKeys[pos], (VAL) values[pos]);
                if (size != startSize) {
                    throw new ConcurrentModificationException();
                }
            }
            --pos;
            for (; pos >= 0; pos--) {
                if (myKeys[pos] != null) {
                    action.accept((String) myKeys[pos], (VAL) values[pos]);
                    if (size != startSize) {
                        throw new ConcurrentModificationException();
                    }
                }
            }
        } finally {
            iterating = false;
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <VAL, STATE> void forEach(final TriConsumer<String, ? super VAL, STATE> action, final STATE state) {
        final int startSize = size;
        final K myKeys[] = this.keys;
        int pos = arraySize;

        iterating = true;
        try {
            if (containsNullKey) {
                action.accept((String) myKeys[pos], (VAL) values[pos], state);
                if (size != startSize) {
                    throw new ConcurrentModificationException();
                }
            }
            --pos;
            for (; pos >= 0; pos--) {
                if (myKeys[pos] != null) {
                    action.accept((String) myKeys[pos], (VAL) values[pos], state);
                    if (size != startSize) {
                        throw new ConcurrentModificationException();
                    }
                }
            }
        } finally {
            iterating = false;
        }
    }

    @Override
    public String get(final String key) {
        return (String) getObjectValue(key);
    }

    @SuppressWarnings("unchecked")
    private V getObjectValue(final Object k) {
        if (k == null) {
            return containsNullKey ? values[arraySize] : defRetValue;
        }
        K curr;
        final K[] key = this.keys;
        int pos;
        // The starting point.
        if ((curr = key[pos = HashCommon.mix(k.hashCode()) & mask]) == null) {
            return defRetValue;
        }
        if (k.equals(curr)) {
            return values[pos];
        }
        // There's always an unused entry.
        while (true) {
            if (((curr = key[pos = (pos + 1) & mask]) == null)) {
                return defRetValue;
            }
            if (k.equals(curr)) {
                return values[pos];
            }
        }
    }

    @Override
    public Map<String, String> getCopy() {
        return toMap();
    }

    @Override
    public Map<String, String> getImmutableMapOrNull() {
        return isEmpty() ? null : Collections.unmodifiableMap(toMap());
    }

    @Override
    public <VAL> VAL getValue(final String key) {
        return (VAL) getObjectValue(key);
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void put(final String key, final String value) {
        putObjectValue((K) key, (V) value);
    }

    private int insert(final K k, final V v) {
        int pos;
        if (k == null) {
            if (containsNullKey) {
                return arraySize;
            }
            containsNullKey = true;
            pos = arraySize;
        } else {
            K curr;
            final K[] key = this.keys;
            // The starting point.
            if (!((curr = key[pos = HashCommon.mix(k.hashCode()) & mask]) == null)) {
                if (curr.equals(k)) {
                    return pos;
                }
                while (!((curr = key[pos = (pos + 1) & mask]) == null)) {
                    if (curr.equals(k)) {
                        return pos;
                    }
                }
            }
        }
        keys[pos] = k;
        values[pos] = v;
        if (size++ >= maxFill) {
            rehash(HashCommon.arraySize(size + 1, loadFactor));
        }
        return -1;
    }

    @Override
    public void putAll(final ReadOnlyStringMap source) {
        assertNotFrozen();
        assertNoConcurrentModification();

        if (size() == 0 && source instanceof OpenHashStringMap) {
            initFrom0((OpenHashStringMap) source);
        } else if (source != null) {
            source.forEach(PUT_ALL, this);
        }
    }

    /** {@inheritDoc} */
    public void putAll(final Map<? extends K, ? extends V> map) {
        if (loadFactor <= .5) {
            // The resulting map will be sized for m.size() elements
            ensureCapacity(map.size());
        } else {
            // The resulting map will be tentatively sized for size() +  m.size() elements
            tryCapacity(size() + map.size());
        }
        for (final Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
            putObjectValue(entry.getKey(), entry.getValue());
        }
    }

    private V putObjectValue(final K k, final V v) {
        assertNotFrozen();
        assertNoConcurrentModification();

        final int pos = insert(k, v);
        if (pos < 0) {
            return defRetValue;
        }
        final V oldValue = values[pos];
        values[pos] = v;
        return oldValue;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void putValue(final String key, final Object value) {
        putObjectValue((K) key, (V) value);
    }

    @Override
    public void remove(final String key) {
        removeObjectKey(key);
    }

    @Override
    public void freeze() {
        immutable = true;
    }

    @Override
    public boolean isFrozen() {
        return immutable;
    }

    @SuppressWarnings("unchecked")
    private V removeObjectKey(final Object k) {
        assertNotFrozen();
        assertNoConcurrentModification();

        if (k == null) {
            if (containsNullKey) {
                return removeNullEntry();
            }
            return defRetValue;
        }
        final K[] key = this.keys;
        int pos = HashCommon.mix(k.hashCode()) & mask;
        K curr = key[pos & mask];
        // The starting point.
        if (curr == null) {
            return defRetValue;
        }
        if (k.equals(curr)) {
            return removeEntry(pos);
        }
        while (true) {
            if ((curr = key[pos = (pos + 1) & mask]) == null) {
                return defRetValue;
            }
            if (k.equals(curr)) {
                return removeEntry(pos);
            }
        }
    }
    private V removeEntry(final int pos) {
        final V oldValue = values[pos];
        values[pos] = null;
        size--;
        shiftKeys(pos);
        if (size < maxFill / 4 && arraySize > DEFAULT_INITIAL_SIZE) {
            rehash(arraySize / 2);
        }
        return oldValue;
    }
    private V removeNullEntry() {
        containsNullKey = false;
        keys[arraySize] = null;
        final V oldValue = values[arraySize];
        values[arraySize] = null;
        size--;
        if (size < maxFill / 4 && arraySize > DEFAULT_INITIAL_SIZE) {
            rehash(arraySize / 2);
        }
        return oldValue;
    }
    /**
     * Shifts left entries with the specified hash code, starting at the
     * specified position, and empties the resulting free entry.
     *
     * @param pos
     *            a starting position.
     */
    private void shiftKeys(int pos) {
        // Shift entries with the same hash.
        int last, slot;
        K curr;
        final K[] myKeys = this.keys;
        for (;;) {
            pos = ((last = pos) + 1) & mask;
            for (;;) {
                if (((curr = myKeys[pos]) == null)) {
                    myKeys[last] = (null);
                    values[last] = null;
                    return;
                }
                slot = HashCommon.mix(curr.hashCode()) & mask;
                if (last <= pos ? (last >= slot || slot > pos) : (last >= slot && slot > pos)) {
                    break;
                }
                pos = (pos + 1) & mask;
            }
            myKeys[last] = curr;
            values[last] = values[pos];
        }
    }

    @Override
    public int size() {
        return size;
    }

    /**
     * Rehashes this map if the table is too large.
     *
     * <P>
     * Let <var>N</var> be the smallest table size that can hold
     * <code>max(n,{@link #size()})</code> entries, still satisfying the load
     * factor. If the current table size is smaller than or equal to
     * <var>N</var>, this method does nothing. Otherwise, it rehashes this map
     * in a table of size <var>N</var>.
     *
     * <P>
     * This method is useful when reusing maps. {@linkplain #clear() Clearing a
     * map} leaves the table size untouched. If you are reusing a map many times,
     * you can call this method with a typical size to avoid keeping around a
     * very large table just because of a few large transient maps.
     *
     * @param n
     *            the threshold for the trimming.
     * @return true if there was enough memory to trim the map.
     */
    public boolean trim(final int n) {
        final int l = HashCommon.nextPowerOfTwo((int) Math.ceil(n / loadFactor));
        if (l >= n || size > HashCommon.maxFill(l, loadFactor)) {
			return true;
		}
        try {
            rehash(l);
        } catch (final OutOfMemoryError cantDoIt) { // unusual to catch OOME but in this case appropriate
            return false;
        }
        return true;
    }
    /**
     * Rehashes the map.
     *
     * <P>
     * This method implements the basic rehashing strategy, and may be overriden
     * by subclasses implementing different rehashing strategies (e.g.,
     * disk-based rehashing). However, you should not override this method
     * unless you understand the internal workings of this class.
     *
     * @param newN
     *            the new size
     */
    @SuppressWarnings("unchecked")
    protected void rehash(final int newN) {
        final K myKeys[] = this.keys;
        final V myValues[] = this.values;
        final int mask = newN - 1; // Note that this is used by the hashing
        // macro
        final K newKey[] = (K[]) new Object[newN + 1];
        final V newValue[] = (V[]) new Object[newN + 1];
        int i = arraySize, pos;
        for (int j = realSize(); j-- != 0;) {
            while (myKeys[--i] == null) {
                // advance i until we find an existing key
            }
            if (newKey[pos = HashCommon.mix(myKeys[i].hashCode()) & mask] != null) { // rehash & check slot availability
                while (newKey[pos = (pos + 1) & mask] != null) {
                    // find available slot at (or immediately following) pos
                }
            }
            newKey[pos] = myKeys[i];
            newValue[pos] = myValues[i];
        }
        newValue[newN] = myValues[arraySize];
        arraySize = newN;
        this.mask = mask;
        maxFill = HashCommon.maxFill(arraySize, loadFactor);
        this.keys = newKey;
        this.values = newValue;
    }

    /**
     * Returns a hash code for this map.
     *
     * @return a hash code for this map.
     */
    @Override
	public int hashCode() {
        int result = 0;
        for (int j = realSize(), i = 0, t = 0; j-- != 0;) {
            while (keys[i] == null) {
                i++;
            }
            if (this != keys[i]) {
                t = keys[i].hashCode();
            }
            if (this != values[i]) {
                t ^= (values[i] == null ? 0 : values[i].hashCode());
            }
            result += t;
            i++;
        }
        // Zero / null keys have hash zero.
        if (containsNullKey) {
            result += (values[arraySize] == null ? 0 : values[arraySize].hashCode());
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        arraySize = HashCommon.arraySize(size, loadFactor);
        maxFill = HashCommon.maxFill(arraySize, loadFactor);
        mask = arraySize - 1;
        final K key[] = this.keys = (K[]) new Object[arraySize + 1];
        final V value[] = this.values = (V[]) new Object[arraySize + 1];
        K k;
        V v;
        for (int i = size, pos; i-- != 0;) {
            k = (K) s.readObject();
            v = (V) s.readObject();
            if (k == null) {
                pos = arraySize;
                containsNullKey = true;
            } else {
                pos = HashCommon.mix(k.hashCode()) & mask;
                while (key[pos] != null) {
                    pos = (pos + 1) & mask;
                }
            }
            key[pos] = k;
            value[pos] = v;
        }
    }

    private void writeObject(final ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();
        try {
            forEach(SERIALIZER, s);
        } catch (final RuntimeException runex) {
            if (runex.getCause() instanceof IOException) {
                throw (IOException) runex.getCause();
            }
            throw runex;
        }
    }

    private static final TriConsumer<String, Object, ObjectOutputStream> SERIALIZER =
            (k, v, objectOutputStream) -> {
                try {
                    objectOutputStream.writeObject(k);
                    objectOutputStream.writeObject(v);
                } catch (final IOException ioex) {
                    throw new IllegalStateException(ioex);
                }
            };

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder(256);
        sb.append('{');
        final K myKeys[] = this.keys;
        int pos = arraySize;
        boolean first = true;
        if (containsNullKey) {
            sb.append(myKeys[pos] == this ? "(this map)" : myKeys[pos]);
            sb.append('=');
            sb.append(values[pos] == this ? "(this map)" : values[pos]);
            first = false;
        }
        --pos;
        for (; pos >= 0; pos--) {
            if (myKeys[pos] != null) {
                if (first) {
                    first = false;
                } else {
                    sb.append(", ");
                }
                sb.append(myKeys[pos] == this ? "(this map)" : myKeys[pos]);
                sb.append('=');
                sb.append(values[pos] == this ? "(this map)" : values[pos]);
            }
        }
        sb.append('}');
        return sb.toString();
    }

    private static class HashCommon {
        private HashCommon() {}

        /** 2<sup>32</sup> &middot; &phi;, &phi; = (&#x221A;5 &minus; 1)/2. */
        private static final int INT_PHI = 0x9E3779B9;

        /** The reciprocal of {@link #INT_PHI} modulo 2<sup>32</sup>. */
        private static final int INV_INT_PHI = 0x144cbc89;

        /** Avalanches the bits of an integer by applying the finalisation step of MurmurHash3.
         *
         * <p>This method implements the finalisation step of Austin Appleby's
         * <a href="http://code.google.com/p/smhasher/">MurmurHash3</a>.
         * Its purpose is to avalanche the bits of the argument to within 0.25% bias.
         *
         * @param x an integer.
         * @return a hash value with good avalanching properties.
         */
        public static int murmurHash3(int x) {
            x ^= x >>> 16;
            x *= 0x85ebca6b;
            x ^= x >>> 13;
            x *= 0xc2b2ae35;
            x ^= x >>> 16;
            return x;
        }

        /**
         * Quickly mixes the bits of an integer.
         *
         * <p>This method mixes the bits of the argument by multiplying by the golden ratio and
         * xorshifting the result. It is borrowed from <a href="https://github.com/OpenHFT/Koloboke">Koloboke</a>, and
         * it has slightly worse behaviour than {@link #murmurHash3(int)} (in open-addressing hash tables the average
         * number of probes is slightly larger), but it's much faster.
         *
         * @param x an integer.
         * @return a hash value obtained by mixing the bits of {@code x}.
         * @see #invMix(int)
         */
        public static int mix(final int x) {
            final int h = x * INT_PHI;
            return h ^ (h >>> 16);
        }

        /** The inverse of {@link #mix(int)}. This method is mainly useful to create unit tests.
         *
         * @param x an integer.
         * @return a value that passed through {@link #mix(int)} would give {@code x}.
         */
        public static int invMix(final int x) {
            return (x ^ x >>> 16) * INV_INT_PHI;
        }

        /** Return the least power of two greater than or equal to the specified value.
         *
         * <p>Note that this function will return 1 when the argument is 0.
         *
         * @param x an integer smaller than or equal to 2<sup>30</sup>.
         * @return the least power of two greater than or equal to the specified value.
         */
        public static int nextPowerOfTwo(int x) {
            if (x == 0) {
                return 1;
            }
            x--;
            x |= x >> 1;
            x |= x >> 2;
            x |= x >> 4;
            x |= x >> 8;
            return (x | x >> 16) + 1;
        }

        /** Return the least power of two greater than or equal to the specified value.
         *
         * <p>Note that this function will return 1 when the argument is 0.
         *
         * @param x a long integer smaller than or equal to 2<sup>62</sup>.
         * @return the least power of two greater than or equal to the specified value.
         */
        public static long nextPowerOfTwo(long x) {
            if (x == 0) {
                return 1;
            }
            x--;
            x |= x >> 1;
            x |= x >> 2;
            x |= x >> 4;
            x |= x >> 8;
            x |= x >> 16;
            return (x | x >> 32) + 1;
        }


        /** Returns the maximum number of entries that can be filled before rehashing.
         *
         * @param n the size of the backing array.
         * @param f the load factor.
         * @return the maximum number of entries before rehashing.
         */
        public static int maxFill(final int n, final float f) {
		/* We must guarantee that there is always at least
		 * one free entry (even with pathological load factors). */
            return Math.min((int) Math.ceil(n * f), n - 1);
        }

        /**
         * Returns the least power of two smaller than or equal to 2<sup>30</sup> and larger than or equal to
         * <code>Math.ceil( expected / f )</code>.
         *
         * @param expected the expected number of elements in a hash table.
         * @param f the load factor.
         * @return the minimum possible size for a backing array.
         * @throws IllegalArgumentException if the necessary size is larger than 2<sup>30</sup>.
         */
        public static int arraySize(final int expected, final float f) {
            final long result = Math.max(2, nextPowerOfTwo((long) Math.ceil(expected / f)));
            if (result > (1 << 30)) {
                throw new IllegalArgumentException("Too large (" + expected +
                        " expected elements with load factor " + f + ")");
            }
            return (int) result;
        }
    }
}
