/* This file is part of libcoding, a library handling (re-)coding of
* datatypes with arithmetic, huffman and various other coders
* Copyright (C) 2004-2011 Niels Fröhling
*
* Interval.hpp: interval class for probability intervals
* Copyright 2004-2011 Niels Fröhling
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef INTERVAL_HPP
#define INTERVAL_HPP
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#pragma warning(disable : 4005)
alignto(16)
struct Interval {
public:
/* low <= target < high <= total */
prob low, target, high, total;
public:
forceinline prob getLow() const {return low;}
forceinline prob getTarget() const {return target;}
forceinline prob getRange() const {return high - low;}
forceinline prob getHigh() const {return high;}
forceinline prob getTotal() const {return total;}
/* do we code an interval absolute greater than 0.5 in [0.0, 1.0) */
forceinline bool isMPS () const {return (low != 0);}
forceinline bool isMPSDominating() const {return ((high - low) > (total - (high - low)));}
forceinline void expandRange(const prob range) {
// assert(range >= total);
low = 1 + (prob)(((int64)(low - 1) * (range - 2)) / (total - 2));
high = 1 + (prob)(((int64)(high - 1) * (range - 2)) / (total - 2));
total = 1 + (prob)(((int64)(total - 1) * (range - 2)) / (total - 2));
}
forceinline void expandTarget(const prob range) {
// assert(range >= total);
target = (prob)(((int64)target * total) / range);
total = (prob)(((int64)total * total) / range);
}
forceinline void invert() {
prob l = low;
low = total - high;
high = total - l;
target = total - (target + 1);
}
};
#include "Interval/Bit.hpp"
struct Performance {
long int codes; // number of symbols coded
double bits; // number of bits coded by this coder
double error; // amount of error
long int binary[2];
forceinline void clear() {codes = 0; bits = 0.0; error = 0.0; binary[0] = binary[1] = 0;}
forceinline double averageBits() {return bits / codes;}
forceinline double averageError() {return error / codes;}
forceinline void update(struct BitInterval *ivl) {
/* high & low may not be set */
ivl->setBit(ivl->isBit());
update((struct Interval *)ivl);
}
forceinline void update(struct Interval *ivl) {
if (ivl->getTotal()) {
double prb;
prb = ivl->getHigh();
prb -= ivl->getLow();
prb /= ivl->getTotal();
assert((prb > 0.0) && (prb <= 1.0));
codes++;
bits -= log2(prb);
error += 1.0 - prb;
}
}
forceinline void update(const double decision) {
assert((decision > 0.0) && (decision <= 1.0));
codes++;
bits -= log2(decision);
error += 1.0 - decision;
}
forceinline void log(const bool decision) {
binary[decision ? 1 : 0]++;
}
forceinline void add(struct Performance *a) {
codes += a->codes;
bits += a->bits;
error += a->error;
binary[0] += a->binary[0];
binary[1] += a->binary[1];
}
};
#endif //INTERVAL_HPP