/*
 * 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.solr.util.hll;

/**
 * A collection of utilities to work with numbers.
 */
class NumberUtil {
    // loge(2) (log-base e of 2)
    public static final double LOGE_2 = 0.6931471805599453;

    // ************************************************************************
    /**
     * Computes the <code>log2</code> (log-base-two) of the specified value.
     *
     * @param  value the <code>double</code> for which the <code>log2</code> is
     *         desired.
     * @return the <code>log2</code> of the specified value
     */
    public static double log2(final double value) {
        // REF:  http://en.wikipedia.org/wiki/Logarithmic_scale (conversion of bases)
        return Math.log(value) / LOGE_2;
    }

    // ========================================================================
    // the hex characters
    private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7',
                                        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

    // ------------------------------------------------------------------------
    /**
     * Converts the specified array of <code>byte</code>s into a string of
     * hex characters (low <code>byte</code> first).
     *
     * @param  bytes the array of <code>byte</code>s that are to be converted.
     *         This cannot be <code>null</code> though it may be empty.
     * @param  offset the offset in <code>bytes</code> at which the bytes will
     *         be taken.  This cannot be negative and must be less than
     *         <code>bytes.length - 1</code>.
     * @param  count the number of bytes to be retrieved from the specified array.
     *         This cannot be negative.  If greater than <code>bytes.length - offset</code>
     *         then that value is used.
     * @return a string of at most <code>count</code> characters that represents
     *         the specified byte array in hex.  This will never be <code>null</code>
     *         though it may be empty if <code>bytes</code> is empty or <code>count</code>
     *         is zero.
     * @throws IllegalArgumentException if <code>offset</code> is greater than
     *         or equal to <code>bytes.length</code>.
     * @see #fromHex(String, int, int)
     */
    public static String toHex(final byte[] bytes, final int offset, final int count) {
        if(offset >= bytes.length) throw new IllegalArgumentException("Offset is greater than the length (" + offset + " >= " + bytes.length + ").")/*by contract*/;
        final int byteCount = Math.min( (bytes.length - offset), count);
        final int upperBound = byteCount + offset;

        final char[] chars = new char[byteCount * 2/*two chars per byte*/];
        int charIndex = 0;
        for(int i=offset; i<upperBound; i++) {
            final byte value = bytes[i];
            chars[charIndex++] = HEX[(value >>> 4) & 0x0F];
            chars[charIndex++] = HEX[value & 0x0F];
        }

        return new String(chars);
    }

    /**
     * Converts the specified array of hex characters into an array of <code>byte</code>s
     * (low <code>byte</code> first).
     *
     * @param  string the string of hex characters to be converted into <code>byte</code>s.
     *         This cannot be <code>null</code> though it may be blank.
     * @param  offset the offset in the string at which the characters will be
     *         taken.  This cannot be negative and must be less than <code>string.length() - 1</code>.
     * @param  count the number of characters to be retrieved from the specified
     *         string.  This cannot be negative and must be divisible by two
     *         (since there are two characters per <code>byte</code>).
     * @return the array of <code>byte</code>s that were converted from the
     *         specified string (in the specified range).  This will never be
     *         <code>null</code> though it may be empty if <code>string</code>
     *         is empty or <code>count</code> is zero.
     * @throws IllegalArgumentException if <code>offset</code> is greater than
     *         or equal to <code>string.length()</code> or if <code>count</code>
     *         is not divisible by two.
     * @see #toHex(byte[], int, int)
     */
    public static byte[] fromHex(final String string, final int offset, final int count) {
        if(offset >= string.length()) throw new IllegalArgumentException("Offset is greater than the length (" + offset + " >= " + string.length() + ").")/*by contract*/;
        if( (count & 0x01) != 0) throw new IllegalArgumentException("Count is not divisible by two (" + count + ").")/*by contract*/;
        final int charCount = Math.min((string.length() - offset), count);
        final int upperBound = offset + charCount;

        final byte[] bytes = new byte[charCount >>> 1/*aka /2*/];
        int byteIndex = 0/*beginning*/;
        for(int i=offset; i<upperBound; i+=2) {
            bytes[byteIndex++] = (byte)(( (digit(string.charAt(i)) << 4)
                                         | digit(string.charAt(i + 1))) & 0xFF);
        }

        return bytes;
    }

    // ------------------------------------------------------------------------
    /**
     * @param  character a hex character to be converted to a <code>byte</code>.
     *         This cannot be a character other than [a-fA-F0-9].
     * @return the value of the specified character.  This will be a value <code>0</code>
     *         through <code>15</code>.
     * @throws IllegalArgumentException if the specified character is not in
     *         [a-fA-F0-9]
     */
    private static final int digit(final char character) {
        switch(character) {
            case '0':
                return 0;
            case '1':
                return 1;
            case '2':
                return 2;
            case '3':
                return 3;
            case '4':
                return 4;
            case '5':
                return 5;
            case '6':
                return 6;
            case '7':
                return 7;
            case '8':
                return 8;
            case '9':
                return 9;
            case 'a':
            case 'A':
                return 10;
            case 'b':
            case 'B':
                return 11;
            case 'c':
            case 'C':
                return 12;
            case 'd':
            case 'D':
                return 13;
            case 'e':
            case 'E':
                return 14;
            case 'f':
            case 'F':
                return 15;

            default:
                throw new IllegalArgumentException("Character is not in [a-fA-F0-9] ('" + character + "').");
        }
    }
}