/*
 * Copyright © 2018, VideoLAN and dav1d authors
 * Copyright © 2018, Two Orioles, LLC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include <limits.h>

#include "common/intops.h"

#include "src/msac.h"

#define EC_PROB_SHIFT 6
#define EC_MIN_PROB 4  // must be <= (1<<EC_PROB_SHIFT)/16

#define EC_WIN_SIZE (sizeof(ec_win) << 3)

static inline void ctx_refill(MsacContext *const s) {
    const uint8_t *buf_pos = s->buf_pos;
    const uint8_t *buf_end = s->buf_end;
    int c = EC_WIN_SIZE - s->cnt - 24;
    ec_win dif = s->dif;
    while (c >= 0 && buf_pos < buf_end) {
        dif ^= ((ec_win)*buf_pos++) << c;
        c -= 8;
    }
    s->dif = dif;
    s->cnt = EC_WIN_SIZE - c - 24;
    s->buf_pos = buf_pos;
}

/* Takes updated dif and range values, renormalizes them so that
 * 32768 <= rng < 65536 (reading more bytes from the stream into dif if
 * necessary), and stores them back in the decoder context.
 * dif: The new value of dif.
 * rng: The new value of the range. */
static inline void ctx_norm(MsacContext *const s, const ec_win dif,
                            const unsigned rng)
{
    const int d = 15 ^ (31 ^ clz(rng));
    assert(rng <= 65535U);
    s->cnt -= d;
    s->dif = ((dif + 1) << d) - 1; /* Shift in 1s in the LSBs */
    s->rng = rng << d;
    if (s->cnt < 0)
        ctx_refill(s);
}

unsigned dav1d_msac_decode_bool_equi_c(MsacContext *const s) {
    const unsigned r = s->rng;
    ec_win dif = s->dif;
    assert((dif >> (EC_WIN_SIZE - 16)) < r);
    // When the probability is 1/2, f = 16384 >> EC_PROB_SHIFT = 256 and we can
    // replace the multiply with a simple shift.
    unsigned v = ((r >> 8) << 7) + EC_MIN_PROB;
    const ec_win vw = (ec_win)v << (EC_WIN_SIZE - 16);
    const unsigned ret = dif >= vw;
    dif -= ret * vw;
    v += ret * (r - 2 * v);
    ctx_norm(s, dif, v);
    return !ret;
}

/* Decode a single binary value.
 * f: The probability that the bit is one
 * Return: The value decoded (0 or 1). */
unsigned dav1d_msac_decode_bool_c(MsacContext *const s, const unsigned f) {
    const unsigned r = s->rng;
    ec_win dif = s->dif;
    assert((dif >> (EC_WIN_SIZE - 16)) < r);
    unsigned v = ((r >> 8) * (f >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + EC_MIN_PROB;
    const ec_win vw = (ec_win)v << (EC_WIN_SIZE - 16);
    const unsigned ret = dif >= vw;
    dif -= ret * vw;
    v += ret * (r - 2 * v);
    ctx_norm(s, dif, v);
    return !ret;
}

int dav1d_msac_decode_subexp(MsacContext *const s, const int ref,
                             const int n, unsigned k)
{
    assert(n >> k == 8);

    unsigned a = 0;
    if (dav1d_msac_decode_bool_equi(s)) {
        if (dav1d_msac_decode_bool_equi(s))
            k += dav1d_msac_decode_bool_equi(s) + 1;
        a = 1 << k;
    }
    const unsigned v = dav1d_msac_decode_bools(s, k) + a;
    return ref * 2 <= n ? inv_recenter(ref, v) :
                          n - 1 - inv_recenter(n - 1 - ref, v);
}

/* Decodes a symbol given an inverse cumulative distribution function (CDF)
 * table in Q15. */
unsigned dav1d_msac_decode_symbol_adapt_c(MsacContext *const s,
                                          uint16_t *const cdf,
                                          const size_t n_symbols)
{
    const unsigned c = s->dif >> (EC_WIN_SIZE - 16), r = s->rng >> 8;
    unsigned u, v = s->rng, val = -1;

    assert(n_symbols <= 15);
    assert(cdf[n_symbols] <= 32);

    do {
        val++;
        u = v;
        v = r * (cdf[val] >> EC_PROB_SHIFT);
        v >>= 7 - EC_PROB_SHIFT;
        v += EC_MIN_PROB * ((unsigned)n_symbols - val);
    } while (c < v);

    assert(u <= s->rng);

    ctx_norm(s, s->dif - ((ec_win)v << (EC_WIN_SIZE - 16)), u - v);

    if (s->allow_update_cdf) {
        const unsigned count = cdf[n_symbols];
        const unsigned rate = 4 + (count >> 4) + (n_symbols > 2);
        unsigned i;
        for (i = 0; i < val; i++)
            cdf[i] += (32768 - cdf[i]) >> rate;
        for (; i < n_symbols; i++)
            cdf[i] -= cdf[i] >> rate;
        cdf[n_symbols] = count + (count < 32);
    }

    return val;
}

unsigned dav1d_msac_decode_bool_adapt_c(MsacContext *const s,
                                        uint16_t *const cdf)
{
    const unsigned bit = dav1d_msac_decode_bool(s, *cdf);

    if (s->allow_update_cdf) {
        // update_cdf() specialized for boolean CDFs
        const unsigned count = cdf[1];
        const int rate = 4 + (count >> 4);
        if (bit)
            cdf[0] += (32768 - cdf[0]) >> rate;
        else
            cdf[0] -= cdf[0] >> rate;
        cdf[1] = count + (count < 32);
    }

    return bit;
}

unsigned dav1d_msac_decode_hi_tok_c(MsacContext *const s, uint16_t *const cdf) {
    unsigned tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
    unsigned tok = 3 + tok_br;
    if (tok_br == 3) {
        tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
        tok = 6 + tok_br;
        if (tok_br == 3) {
            tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
            tok = 9 + tok_br;
            if (tok_br == 3)
                tok = 12 + dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
        }
    }
    return tok;
}

void dav1d_msac_init(MsacContext *const s, const uint8_t *const data,
                     const size_t sz, const int disable_cdf_update_flag)
{
    s->buf_pos = data;
    s->buf_end = data + sz;
    s->dif = ((ec_win)1 << (EC_WIN_SIZE - 1)) - 1;
    s->rng = 0x8000;
    s->cnt = -15;
    s->allow_update_cdf = !disable_cdf_update_flag;
    ctx_refill(s);

#if ARCH_X86_64 && HAVE_ASM
    s->symbol_adapt16 = dav1d_msac_decode_symbol_adapt_c;

    msac_init_x86(s);
#endif
}
