📄 quanti.cpp
字号:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream.h>
#include <iomanip.h>
#include "global.h"
#include "quanti.h"
/*---------------------------------------------------------------------------*/
Quantizer::Quantizer (ErrorMetric *err) : err (err)
{
data = NULL;
nData = 0;
max = min = sum = sumSq = mean = var = 0;
initialDist = 0;
}
/*---------------------------------------------------------------------------*/
void Quantizer::getStats ()
{
max = -MaxReal;
min = MaxReal;
sum = sumSq = 0;
for (int i = 0; i < nData; i++) {
if (data[i] < min)
min = data[i];
if (data[i] > max)
max = data[i];
sum += data[i];
sumSq += square(data[i]);
}
mean = sum / (Real)nData;
var = sumSq / (Real)nData - square (mean);
}
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
UniformQuant::UniformQuant (MonoLayerCoder *entropy, int paramPrecision,
int zeroCenter, ErrorMetric *err) :
Quantizer (err), entropy (entropy), paramPrecision (paramPrecision),
zeroCenter (zeroCenter)
{
}
/*---------------------------------------------------------------------------*/
void UniformQuant::setDataEncode (Real *newData, int newNData)
{
data = newData;
nData = newNData;
getStats ();
if (zeroCenter) {
max = fabs(max) > fabs(min) ? fabs(max) : fabs(min);
min = -max;
}
imax = realToInt (max, paramPrecision);
qmax = intToReal (imax, paramPrecision);
// Make sure qmax >= max and -qmax <= min
while (qmax < max)
qmax = intToReal (++imax, paramPrecision);
if (zeroCenter) {
imin = -imax;
qmin = -qmax;
} else {
imin = realToInt (min, paramPrecision);
qmin = intToReal (imin, paramPrecision);
// Make sure qmin <= min
while (qmin > min)
qmin = intToReal (--imin, paramPrecision);
}
imean = realToInt (mean, paramPrecision);
qmean = intToReal (imean, paramPrecision);
initialDist = 0;
if (zeroCenter)
for (int i = 0; i < nData; i++)
initialDist += (*err)(data[i]);
else
for (int i = 0; i < nData; i++)
initialDist += (*err)(data[i] - qmean);
}
/*---------------------------------------------------------------------------*/
void UniformQuant::setDataDecode (Real *newData, int newNData,
int imax, int imin, int imean)
{
data = newData;
nData = newNData;
if (imin < imax) {
qmax = intToReal (imin, paramPrecision);
if (zeroCenter) {
qmin = -qmax;
} else {
qmin = intToReal (imin, paramPrecision);
}
qmean = intToReal (imean, paramPrecision);
}
}
/*---------------------------------------------------------------------------*/
void UniformQuant::getRateDist (int precision, Real minStepSize,
Real &rate, Real &dist)
{
if (precision > 0) {
const int nSteps = (1<<precision)-1;
const Real stepSize = (qmax-qmin)/(Real)nSteps;
const Real recipStepSize = 1.0/stepSize;
if (stepSize < minStepSize) {
rate = MaxReal;
dist = MaxReal;
return;
}
entropy->setNSym (nSteps);
rate = dist = 0;
for (int i = 0; i < nData; i++) {
int symbol = (int)((data[i]-qmin)*recipStepSize);
assert (symbol < nSteps && symbol >= 0);
rate += entropy->cost (symbol, TRUE);
Real reconstruct = qmin + ((Real)symbol + 0.5) * stepSize;
dist += (*err) (data[i]-reconstruct);
}
} else {
rate = dist = 0;
if (zeroCenter) {
for (int i = 0; i < nData; i++) {
dist += (*err) (data[i]);
}
} else {
for (int i = 0; i < nData; i++) {
dist += (*err) (data[i] - qmean);
}
}
}
}
/*---------------------------------------------------------------------------*/
void UniformQuant::quantize (Encoder *encoder, int precision)
{
if (precision > 0) {
const int nSteps = (1<<precision)-1;
const Real stepSize = (qmax-qmin)/(Real)nSteps;
const Real recipStepSize = 1.0/stepSize;
entropy->setNSym (nSteps);
for (int i = 0; i < nData; i++) {
int symbol = (int)((data[i]-qmin)*recipStepSize);
assert (symbol < nSteps && symbol >= 0);
entropy->write (encoder, symbol, TRUE);
}
}
}
/*---------------------------------------------------------------------------*/
void UniformQuant::dequantize (Decoder *decoder, int precision)
{
if (precision > 0) {
const int nSteps = (1<<precision)-1;
const Real stepSize = (qmax-qmin)/(Real)nSteps;
int symbol;
entropy->setNSym (nSteps);
for (int i = 0; i < nData; i++) {
symbol = entropy->read (decoder, TRUE);
assert (symbol < nSteps && symbol >= 0);
data[i] = qmin + ((Real)symbol + 0.5) * stepSize;
}
} else {
for (int i = 0; i < nData; i++) {
data[i] = qmean;
}
}
}
/*---------------------------------------------------------------------------*/
void UniformQuant::writeHeader (Encoder *encoder, int precision)
{
encoder->writeNonneg (precision);
if (precision > 0) {
encoder->writeInt (imax);
if (!zeroCenter)
encoder->writeInt (imin);
} else {
if (!zeroCenter)
encoder->writeInt (imean);
}
}
/*---------------------------------------------------------------------------*/
void UniformQuant::readHeader (Decoder *decoder, int &precision)
{
precision = decoder->readNonneg ();
if (precision > 0) {
imax = decoder->readInt ();
qmax = intToReal (imax, paramPrecision);
if (zeroCenter) {
qmin = -qmax;
} else {
imin = decoder->readInt ();
qmin = intToReal (imin, paramPrecision);
}
qmean = 0;
} else {
if (!zeroCenter) {
imean = decoder->readInt ();
qmean = intToReal (imean, paramPrecision);
} else {
qmean = 0;
imean = realToInt (qmean, paramPrecision);
}
qmax = qmin = qmean;
}
}
/*---------------------------------------------------------------------------*/
void UniformQuant::setParams (int newParamPrecision, Real newMax,
Real newMin, Real newMean)
{
paramPrecision = newParamPrecision;
qmax = newMax;
qmin = newMin;
qmean = newMean;
}
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
LayerQuant::LayerQuant (MultiLayerCoder *entropy, int paramPrecision,
int signedSym, int nLayers, ErrorMetric *err) :
Quantizer (err), entropy (entropy), paramPrecision (paramPrecision),
signedSym (signedSym), nLayers (nLayers)
{
currentLayer = -1;
layerRate = new Real [nLayers];
layerDist = new Real [nLayers];
context = NULL;
residual = NULL;
}
/*---------------------------------------------------------------------------*/
LayerQuant::~LayerQuant ()
{
delete [] layerRate;
delete [] layerDist;
if (context != NULL)
delete [] context;
if (residual != NULL)
delete [] residual;
}
/*---------------------------------------------------------------------------*/
void LayerQuant::setDataEncode (Real *newData, int newNData)
{
data = newData;
nData = newNData;
getStats ();
if (signedSym) {
max = fabs(max) > fabs(min) ? fabs(max) : fabs(min);
min = -max;
}
imax = realToInt (max, paramPrecision);
qmax = intToReal (imax, paramPrecision);
// Make sure qmax >= max and -qmax <= min
while (qmax < max)
qmax = intToReal (++imax, paramPrecision);
if (signedSym) {
imin = -imax;
qmin = -qmax;
} else {
imin = realToInt (min, paramPrecision);
qmin = intToReal (imin, paramPrecision);
// Make sure qmin <= min
while (qmin > min)
qmin = intToReal (--imin, paramPrecision);
}
if (signedSym)
threshold = qmax/2.0;
else
threshold = (qmax - qmin)/2.0;
currentLayer = -1;
if (context != NULL)
delete [] context;
if (residual != NULL)
delete [] residual;
context = new int [nData];
residual = new Real [nData];
resetLayer ();
initialDist = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -