188 lines
6.6 KiB
C++
188 lines
6.6 KiB
C++
/* Copyright 2018 Dirk Steinke
|
|
|
|
Licensed 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. */
|
|
|
|
#include "pch.h"
|
|
#include <algorithm>
|
|
#include <string.h>
|
|
#include "preflate_statistical_codec.h"
|
|
#include "preflate_statistical_model.h"
|
|
#include "support/array_helper.h"
|
|
#include "support/bit_helper.h"
|
|
#include <stdint.h>
|
|
|
|
template <unsigned N>
|
|
bool PreflateSubModel<N>::isEqualTo(const PreflateSubModel<N>& m) const {
|
|
if (N == 0 || m.bounds[N] == 0) {
|
|
return true;
|
|
}
|
|
for (unsigned i = 0; i < N; ++i) {
|
|
if (bounds[i] != m.bounds[i]) {
|
|
return false;
|
|
}
|
|
if (bounds[i + 1] > 0 && ids[i] != m.ids[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
if (bounds[N] != m.bounds[N]) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <unsigned NEG, unsigned POS>
|
|
bool PreflateCorrectionSubModel<NEG, POS>::isEqualTo(const PreflateCorrectionSubModel<NEG, POS>& m) const {
|
|
return sign.isEqualTo(m.sign)
|
|
&& pos.isEqualTo(m.pos)
|
|
&& neg.isEqualTo(m.neg);
|
|
}
|
|
|
|
|
|
bool PreflateBlockPredictionModel::isEqualTo(const PreflateBlockPredictionModel& m) const {
|
|
return blockType.isEqualTo(m.blockType)
|
|
&& EOBMisprediction.isEqualTo(m.EOBMisprediction)
|
|
&& nonZeroPadding.isEqualTo(m.nonZeroPadding);
|
|
}
|
|
bool PreflateTreeCodePredictionModel::isEqualTo(const PreflateTreeCodePredictionModel& m) const {
|
|
return TCBitlengthCorrection.isEqualTo(m.TCBitlengthCorrection)
|
|
&& TCCountMisprediction.isEqualTo(m.TCCountMisprediction)
|
|
&& LCountMisprediction.isEqualTo(m.LCountMisprediction)
|
|
&& DCountMisprediction.isEqualTo(m.DCountMisprediction)
|
|
&& LDTypeMisprediction[0].isEqualTo(m.LDTypeMisprediction[0])
|
|
&& LDTypeMisprediction[1].isEqualTo(m.LDTypeMisprediction[1])
|
|
&& LDTypeMisprediction[2].isEqualTo(m.LDTypeMisprediction[2])
|
|
&& LDTypeMisprediction[3].isEqualTo(m.LDTypeMisprediction[3])
|
|
&& LDTypeReplacementBase.isEqualTo(m.LDTypeReplacementBase)
|
|
&& LDRepeatCountCorrection.isEqualTo(m.LDRepeatCountCorrection)
|
|
&& LDBitlengthCorrection.isEqualTo(m.LDBitlengthCorrection);
|
|
}
|
|
bool PreflateTokenPredictionModel::isEqualTo(const PreflateTokenPredictionModel& m) const {
|
|
return LITMisprediction.isEqualTo(m.LITMisprediction)
|
|
&& REFMisprediction.isEqualTo(m.REFMisprediction)
|
|
&& LENCorrection.isEqualTo(m.LENCorrection)
|
|
&& DISTAfterLenCorrection.isEqualTo(m.DISTAfterLenCorrection)
|
|
&& DISTOnlyCorrection.isEqualTo(m.DISTOnlyCorrection)
|
|
&& IrregularLen258Encoding.isEqualTo(m.IrregularLen258Encoding);
|
|
}
|
|
|
|
bool PreflatePredictionModel::isEqualTo(const PreflatePredictionModel& m) const {
|
|
return block.isEqualTo(m.block)
|
|
&& treecode.isEqualTo(m.treecode)
|
|
&& token.isEqualTo(m.token);
|
|
}
|
|
|
|
bool isEqual(const PreflatePredictionModel& m1, const PreflatePredictionModel& m2) {
|
|
return m1.isEqualTo(m2);
|
|
}
|
|
|
|
// ----------------------------
|
|
|
|
void printFlagStatistics(const char *txt, unsigned(&flag)[2]) {
|
|
if (flag[1]) {
|
|
printf("%s %g%% (%d)", txt, flag[1] * 100.0 / (flag[0] + flag[1]), flag[0] + flag[1]);
|
|
}
|
|
}
|
|
void printCorrectionStatistics(const char *txt,
|
|
unsigned data[], unsigned size, unsigned sum, unsigned offset) {
|
|
if (data[offset] == sum) {
|
|
return;
|
|
}
|
|
bool on = false;
|
|
for (unsigned i = 0; i < size; ++i) {
|
|
if (data[i]) {
|
|
if (!on) {
|
|
printf("%s:", txt);
|
|
}
|
|
on = true;
|
|
if (i != offset && (i == 0 || i + 1 == size)) {
|
|
printf(" %sx %g%%", i == 0 ? "-" : "+", data[i] * 100.0 / sum);
|
|
} else {
|
|
printf(" %s%d %g%%", i == offset ? "" : (i < offset ? "-" : "+"), (int)labs((int)(i - offset)), data[i] * 100.0 / sum);
|
|
}
|
|
}
|
|
}
|
|
if (on) {
|
|
printf(" (%d)", sum);
|
|
}
|
|
}
|
|
template <unsigned N>
|
|
void printCorrectionStatistics(const char *txt, unsigned (&data)[N], unsigned sum, int offset) {
|
|
printCorrectionStatistics(txt, data, N, sum, offset);
|
|
}
|
|
|
|
// ----------------------------
|
|
|
|
void PreflateStatisticsCounter::BlockPrediction::print() {
|
|
unsigned sum = sumArray(blockType);
|
|
if (blockType[0]) {
|
|
printf(" ->STORE %g%%", blockType[0] * 100.0 / sum);
|
|
}
|
|
if (blockType[1] && blockType[1] != sum) {
|
|
printf(" ->DYNHUF %g%%", blockType[1] * 100.0 / sum);
|
|
}
|
|
if (blockType[2]) {
|
|
printf(" ->STATHUF %g%%", blockType[2] * 100.0 / sum);
|
|
}
|
|
printFlagStatistics(", EOB MP", EOBMisprediction);
|
|
printFlagStatistics(", PAD!=0", nonZeroPadding);
|
|
}
|
|
|
|
void PreflateStatisticsCounter::TreeCodePrediction::print() {
|
|
printFlagStatistics(", !CT SZ MP", TCCountMisprediction);
|
|
printFlagStatistics(", !L SZ MP", LCountMisprediction);
|
|
printFlagStatistics(", !D SZ MP", DCountMisprediction);
|
|
printFlagStatistics(", !T B MP", LDTypeMisprediction[0]);
|
|
printFlagStatistics(", !T R MP", LDTypeMisprediction[1]);
|
|
printFlagStatistics(", !T 0s MP", LDTypeMisprediction[2]);
|
|
printFlagStatistics(", !T 0l MP", LDTypeMisprediction[3]);
|
|
unsigned sum = sumArray(LDTypeReplacement);
|
|
if (LDTypeReplacement[0]) {
|
|
printf(" ->T B %g", LDTypeReplacement[0] * 100.0 / sum);
|
|
}
|
|
if (LDTypeReplacement[1]) {
|
|
printf(" ->T R %g", LDTypeReplacement[1] * 100.0 / sum);
|
|
}
|
|
if (LDTypeReplacement[2]) {
|
|
printf(" ->T 0s %g", LDTypeReplacement[2] * 100.0 / sum);
|
|
}
|
|
if (LDTypeReplacement[3]) {
|
|
printf(" ->T 0l %g", LDTypeReplacement[3] * 100.0 / sum);
|
|
}
|
|
sum = sumArray(TCBitlengthCorrection);
|
|
printCorrectionStatistics(", C BL", TCBitlengthCorrection, sum, 3);
|
|
sum = sumArray(LDRepeatCountCorrection);
|
|
printCorrectionStatistics(" LD RP", LDRepeatCountCorrection, sum, 1);
|
|
sum = sumArray(LDBitlengthCorrection);
|
|
printCorrectionStatistics(", LD BL", LDBitlengthCorrection, sum, 4);
|
|
}
|
|
|
|
void PreflateStatisticsCounter::TokenPrediction::print() {
|
|
printFlagStatistics(", !LIT MP", LITMisprediction);
|
|
printFlagStatistics(", !REF MP", REFMisprediction);
|
|
unsigned sum = sumArray(LENCorrection);
|
|
printCorrectionStatistics(" L", LENCorrection, sum, 6);
|
|
sum = sumArray(DISTAfterLenCorrection);
|
|
printCorrectionStatistics(" L->D+", DISTAfterLenCorrection, sum, 0);
|
|
sum = sumArray(DISTOnlyCorrection);
|
|
printCorrectionStatistics(" ->D+", DISTOnlyCorrection, sum, 0);
|
|
printFlagStatistics(", !L258 MP", LEN258IrregularEncoding);
|
|
}
|
|
|
|
|
|
void PreflateStatisticsCounter::print() {
|
|
block.print();
|
|
treecode.print();
|
|
token.print();
|
|
printf("\n");
|
|
}
|