Commit d85098de authored by Valery Valentin's avatar Valery Valentin Committed by David Flynn
Browse files

attr/m44900: convert pred/lift to fixed-point

parent 1d95e5fa
...@@ -525,26 +525,28 @@ AttributeDecoder::decodeColorsLift( ...@@ -525,26 +525,28 @@ AttributeDecoder::decodeColorsLift(
++predictorIndex) { ++predictorIndex) {
predictors[predictorIndex].computeWeights(); predictors[predictorIndex].computeWeights();
} }
std::vector<double> weights; std::vector<uint64_t> weights;
PCCComputeQuantizationWeights(predictors, weights); PCCComputeQuantizationWeights(predictors, weights);
const size_t lodCount = numberOfPointsPerLOD.size(); const size_t lodCount = numberOfPointsPerLOD.size();
std::vector<Vec3<double>> colors; std::vector<Vec3<int64_t>> colors;
colors.resize(pointCount); colors.resize(pointCount);
// decompress // decompress
for (size_t predictorIndex = 0; predictorIndex < pointCount; for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) { ++predictorIndex) {
uint32_t values[3]; uint32_t values[3];
decoder.decode(values); decoder.decode(values);
const int64_t qs = aps.quant_step_size_luma; const int64_t qs = aps.quant_step_size_luma
const int64_t qs2 = aps.quant_step_size_chroma; << (kFixedPointWeightShift / 2 + kFixedPointAttributeShift);
const double quantWeight = sqrt(weights[predictorIndex]); const int64_t qs2 = aps.quant_step_size_chroma
<< (kFixedPointWeightShift / 2 + kFixedPointAttributeShift);
const int64_t quantWeight = weights[predictorIndex];
auto& color = colors[predictorIndex]; auto& color = colors[predictorIndex];
const int64_t delta = UIntToInt(values[0]); const int64_t delta = UIntToInt(values[0]);
const double reconstructedDelta = PCCInverseQuantization(delta, qs); const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs);
color[0] = reconstructedDelta / quantWeight; color[0] = reconstructedDelta / quantWeight;
for (size_t d = 1; d < 3; ++d) { for (size_t d = 1; d < 3; ++d) {
const int64_t delta = UIntToInt(values[d]); const int64_t delta = UIntToInt(values[d]);
const double reconstructedDelta = PCCInverseQuantization(delta, qs2); const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs2);
color[d] = reconstructedDelta / quantWeight; color[d] = reconstructedDelta / quantWeight;
} }
} }
...@@ -557,11 +559,13 @@ AttributeDecoder::decodeColorsLift( ...@@ -557,11 +559,13 @@ AttributeDecoder::decodeColorsLift(
PCCLiftPredict(predictors, startIndex, endIndex, false, colors); PCCLiftPredict(predictors, startIndex, endIndex, false, colors);
} }
const double clipMax = (1 << desc.attr_bitdepth) - 1; const int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
for (size_t f = 0; f < pointCount; ++f) { for (size_t f = 0; f < pointCount; ++f) {
const auto color0 =
divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift);
Vec3<uint8_t> color; Vec3<uint8_t> color;
for (size_t d = 0; d < 3; ++d) { for (size_t d = 0; d < 3; ++d) {
color[d] = uint8_t(PCCClip(std::round(colors[f][d]), 0.0, clipMax)); color[d] = uint8_t(PCCClip(color0[d], int64_t(0), clipMax));
} }
pointCloud.setColor(indexesLOD[f], color); pointCloud.setColor(indexesLOD[f], color);
} }
...@@ -597,21 +601,22 @@ AttributeDecoder::decodeReflectancesLift( ...@@ -597,21 +601,22 @@ AttributeDecoder::decodeReflectancesLift(
++predictorIndex) { ++predictorIndex) {
predictors[predictorIndex].computeWeights(); predictors[predictorIndex].computeWeights();
} }
std::vector<double> weights; std::vector<uint64_t> weights;
PCCComputeQuantizationWeights(predictors, weights); PCCComputeQuantizationWeights(predictors, weights);
const size_t lodCount = numberOfPointsPerLOD.size(); const size_t lodCount = numberOfPointsPerLOD.size();
std::vector<double> reflectances; std::vector<int64_t> reflectances;
reflectances.resize(pointCount); reflectances.resize(pointCount);
// decompress // decompress
for (size_t predictorIndex = 0; predictorIndex < pointCount; for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) { ++predictorIndex) {
const int64_t detail = decoder.decode(); const int64_t detail = decoder.decode();
const int64_t qs = aps.quant_step_size_luma; const int64_t qs = aps.quant_step_size_luma
const double quantWeight = sqrt(weights[predictorIndex]); << (kFixedPointWeightShift / 2 + kFixedPointAttributeShift);
const int64_t quantWeight = weights[predictorIndex];
auto& reflectance = reflectances[predictorIndex]; auto& reflectance = reflectances[predictorIndex];
const int64_t delta = UIntToInt(detail); const int64_t delta = UIntToInt(detail);
const double reconstructedDelta = PCCInverseQuantization(delta, qs); const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs);
reflectance = reconstructedDelta / quantWeight; reflectance = reconstructedDelta / quantWeight;
} }
...@@ -623,11 +628,12 @@ AttributeDecoder::decodeReflectancesLift( ...@@ -623,11 +628,12 @@ AttributeDecoder::decodeReflectancesLift(
predictors, weights, startIndex, endIndex, false, reflectances); predictors, weights, startIndex, endIndex, false, reflectances);
PCCLiftPredict(predictors, startIndex, endIndex, false, reflectances); PCCLiftPredict(predictors, startIndex, endIndex, false, reflectances);
} }
const double maxReflectance = (1 << desc.attr_bitdepth) - 1; const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
for (size_t f = 0; f < pointCount; ++f) { for (size_t f = 0; f < pointCount; ++f) {
const auto refl =
divExp2RoundHalfInf(reflectances[f], kFixedPointAttributeShift);
pointCloud.setReflectance( pointCloud.setReflectance(
indexesLOD[f], indexesLOD[f], uint16_t(PCCClip(refl, int64_t(0), maxReflectance)));
uint16_t(PCCClip(std::round(reflectances[f]), 0.0, maxReflectance)));
} }
} }
......
...@@ -43,8 +43,8 @@ ...@@ -43,8 +43,8 @@
#include "FixedPoint.h" #include "FixedPoint.h"
// todo(df): promote to per-attribute encoder parameter // todo(df): promote to per-attribute encoder parameter
static const float kAttrPredLambdaR = 0.01; static const double kAttrPredLambdaR = 0.01;
static const float kAttrPredLambdaC = 0.01; static const double kAttrPredLambdaC = 0.01;
namespace pcc { namespace pcc {
//============================================================================ //============================================================================
...@@ -367,7 +367,7 @@ AttributeEncoder::computeReflectancePredictionWeights( ...@@ -367,7 +367,7 @@ AttributeEncoder::computeReflectancePredictionWeights(
int64_t minValue = 0; int64_t minValue = 0;
int64_t maxValue = 0; int64_t maxValue = 0;
for (size_t i = 0; i < predictor.neighborCount; ++i) { for (size_t i = 0; i < predictor.neighborCount; ++i) {
const uint16_t reflectanceNeighbor = pointCloud.getReflectance( const uint64_t reflectanceNeighbor = pointCloud.getReflectance(
indexesLOD[predictor.neighbors[i].predictorIndex]); indexesLOD[predictor.neighbors[i].predictorIndex]);
if (i == 0 || reflectanceNeighbor < minValue) { if (i == 0 || reflectanceNeighbor < minValue) {
minValue = reflectanceNeighbor; minValue = reflectanceNeighbor;
...@@ -379,16 +379,16 @@ AttributeEncoder::computeReflectancePredictionWeights( ...@@ -379,16 +379,16 @@ AttributeEncoder::computeReflectancePredictionWeights(
const int64_t maxDiff = maxValue - minValue; const int64_t maxDiff = maxValue - minValue;
if (maxDiff > aps.adaptive_prediction_threshold) { if (maxDiff > aps.adaptive_prediction_threshold) {
const int qs = aps.quant_step_size_luma; const int qs = aps.quant_step_size_luma;
uint16_t attrValue = uint64_t attrValue =
pointCloud.getReflectance(indexesLOD[predictorIndex]); pointCloud.getReflectance(indexesLOD[predictorIndex]);
// base case: weighted average of n neighbours // base case: weighted average of n neighbours
predictor.predMode = 0; predictor.predMode = 0;
uint16_t attrPred = predictor.predictReflectance(pointCloud, indexesLOD); uint64_t attrPred = predictor.predictReflectance(pointCloud, indexesLOD);
int64_t attrResidualQuant = int64_t attrResidualQuant =
computeReflectanceResidual(attrValue, attrPred, qs); computeReflectanceResidual(attrValue, attrPred, qs);
double best_score = attrResidualQuant + kAttrPredLambdaR * (double)qs; double best_score = attrResidualQuant + kAttrPredLambdaR * qs;
for (int i = 0; i < predictor.neighborCount; i++) { for (int i = 0; i < predictor.neighborCount; i++) {
if (i == aps.max_num_direct_predictors) if (i == aps.max_num_direct_predictors)
...@@ -458,7 +458,7 @@ AttributeEncoder::encodeReflectancesPred( ...@@ -458,7 +458,7 @@ AttributeEncoder::encodeReflectancesPred(
aps, pointCloud, indexesLOD, predictorIndex, predictor, encoder, aps, pointCloud, indexesLOD, predictorIndex, predictor, encoder,
context); context);
const uint32_t pointIndex = indexesLOD[predictorIndex]; const uint32_t pointIndex = indexesLOD[predictorIndex];
const uint16_t reflectance = pointCloud.getReflectance(pointIndex); const uint64_t reflectance = pointCloud.getReflectance(pointIndex);
const uint16_t predictedReflectance = const uint16_t predictedReflectance =
predictor.predictReflectance(pointCloud, indexesLOD); predictor.predictReflectance(pointCloud, indexesLOD);
const int64_t quantAttValue = reflectance; const int64_t quantAttValue = reflectance;
...@@ -837,16 +837,16 @@ AttributeEncoder::encodeColorsLift( ...@@ -837,16 +837,16 @@ AttributeEncoder::encodeColorsLift(
++predictorIndex) { ++predictorIndex) {
predictors[predictorIndex].computeWeights(); predictors[predictorIndex].computeWeights();
} }
std::vector<double> weights; std::vector<uint64_t> weights;
PCCComputeQuantizationWeights(predictors, weights); PCCComputeQuantizationWeights(predictors, weights);
const size_t lodCount = numberOfPointsPerLOD.size(); const size_t lodCount = numberOfPointsPerLOD.size();
std::vector<Vec3<double>> colors; std::vector<Vec3<int64_t>> colors;
colors.resize(pointCount); colors.resize(pointCount);
for (size_t index = 0; index < pointCount; ++index) { for (size_t index = 0; index < pointCount; ++index) {
const auto& color = pointCloud.getColor(indexesLOD[index]); const auto& color = pointCloud.getColor(indexesLOD[index]);
for (size_t d = 0; d < 3; ++d) { for (size_t d = 0; d < 3; ++d) {
colors[index][d] = color[d]; colors[index][d] = int32_t(color[d]) << kFixedPointAttributeShift;
} }
} }
...@@ -859,16 +859,18 @@ AttributeEncoder::encodeColorsLift( ...@@ -859,16 +859,18 @@ AttributeEncoder::encodeColorsLift(
} }
// compress // compress
const int64_t qs = aps.quant_step_size_luma; const int64_t qs = aps.quant_step_size_luma
const size_t qs2 = aps.quant_step_size_chroma; << (kFixedPointWeightShift / 2 + kFixedPointAttributeShift);
const size_t qs2 = aps.quant_step_size_chroma
<< (kFixedPointWeightShift / 2 + kFixedPointAttributeShift);
for (size_t predictorIndex = 0; predictorIndex < pointCount; for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) { ++predictorIndex) {
const double quantWeight = sqrt(weights[predictorIndex]); const int64_t quantWeight = weights[predictorIndex];
auto& color = colors[predictorIndex]; auto& color = colors[predictorIndex];
const int64_t delta = PCCQuantization(color[0] * quantWeight, qs); const int64_t delta = PCCQuantization(color[0] * quantWeight, qs);
const int64_t detail = IntToUInt(delta); const int64_t detail = IntToUInt(delta);
assert(detail < std::numeric_limits<uint32_t>::max()); assert(detail < std::numeric_limits<uint32_t>::max());
const double reconstructedDelta = PCCInverseQuantization(delta, qs); const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs);
color[0] = reconstructedDelta / quantWeight; color[0] = reconstructedDelta / quantWeight;
uint32_t values[3]; uint32_t values[3];
values[0] = uint32_t(detail); values[0] = uint32_t(detail);
...@@ -876,7 +878,7 @@ AttributeEncoder::encodeColorsLift( ...@@ -876,7 +878,7 @@ AttributeEncoder::encodeColorsLift(
const int64_t delta = PCCQuantization(color[d] * quantWeight, qs2); const int64_t delta = PCCQuantization(color[d] * quantWeight, qs2);
const int64_t detail = IntToUInt(delta); const int64_t detail = IntToUInt(delta);
assert(detail < std::numeric_limits<uint32_t>::max()); assert(detail < std::numeric_limits<uint32_t>::max());
const double reconstructedDelta = PCCInverseQuantization(delta, qs2); const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs2);
color[d] = reconstructedDelta / quantWeight; color[d] = reconstructedDelta / quantWeight;
values[d] = uint32_t(detail); values[d] = uint32_t(detail);
} }
...@@ -891,11 +893,13 @@ AttributeEncoder::encodeColorsLift( ...@@ -891,11 +893,13 @@ AttributeEncoder::encodeColorsLift(
PCCLiftPredict(predictors, startIndex, endIndex, false, colors); PCCLiftPredict(predictors, startIndex, endIndex, false, colors);
} }
const double clipMax = (1 << desc.attr_bitdepth) - 1; const int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
for (size_t f = 0; f < pointCount; ++f) { for (size_t f = 0; f < pointCount; ++f) {
const auto color0 =
divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift);
Vec3<uint8_t> color; Vec3<uint8_t> color;
for (size_t d = 0; d < 3; ++d) { for (size_t d = 0; d < 3; ++d) {
color[d] = uint8_t(PCCClip(std::round(colors[f][d]), 0.0, clipMax)); color[d] = uint8_t(PCCClip(color0[d], 0.0, clipMax));
} }
pointCloud.setColor(indexesLOD[f], color); pointCloud.setColor(indexesLOD[f], color);
} }
...@@ -931,15 +935,16 @@ AttributeEncoder::encodeReflectancesLift( ...@@ -931,15 +935,16 @@ AttributeEncoder::encodeReflectancesLift(
++predictorIndex) { ++predictorIndex) {
predictors[predictorIndex].computeWeights(); predictors[predictorIndex].computeWeights();
} }
std::vector<double> weights; std::vector<uint64_t> weights;
PCCComputeQuantizationWeights(predictors, weights); PCCComputeQuantizationWeights(predictors, weights);
const size_t lodCount = numberOfPointsPerLOD.size(); const size_t lodCount = numberOfPointsPerLOD.size();
std::vector<double> reflectances; std::vector<int64_t> reflectances;
reflectances.resize(pointCount); reflectances.resize(pointCount);
for (size_t index = 0; index < pointCount; ++index) { for (size_t index = 0; index < pointCount; ++index) {
reflectances[index] = pointCloud.getReflectance(indexesLOD[index]); reflectances[index] = int32_t(pointCloud.getReflectance(indexesLOD[index]))
<< kFixedPointAttributeShift;
} }
for (size_t i = 0; (i + 1) < lodCount; ++i) { for (size_t i = 0; (i + 1) < lodCount; ++i) {
...@@ -954,13 +959,14 @@ AttributeEncoder::encodeReflectancesLift( ...@@ -954,13 +959,14 @@ AttributeEncoder::encodeReflectancesLift(
// compress // compress
for (size_t predictorIndex = 0; predictorIndex < pointCount; for (size_t predictorIndex = 0; predictorIndex < pointCount;
++predictorIndex) { ++predictorIndex) {
const int64_t qs = aps.quant_step_size_luma; const int64_t qs = aps.quant_step_size_luma
const double quantWeight = sqrt(weights[predictorIndex]); << (kFixedPointWeightShift / 2 + kFixedPointAttributeShift);
const int64_t quantWeight = weights[predictorIndex];
auto& reflectance = reflectances[predictorIndex]; auto& reflectance = reflectances[predictorIndex];
const int64_t delta = PCCQuantization(reflectance * quantWeight, qs); const int64_t delta = PCCQuantization(reflectance * quantWeight, qs);
const int64_t detail = IntToUInt(delta); const int64_t detail = IntToUInt(delta);
assert(detail < std::numeric_limits<uint32_t>::max()); assert(detail < std::numeric_limits<uint32_t>::max());
const double reconstructedDelta = PCCInverseQuantization(delta, qs); const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs);
reflectance = reconstructedDelta / quantWeight; reflectance = reconstructedDelta / quantWeight;
encoder.encode(detail); encoder.encode(detail);
} }
...@@ -973,11 +979,12 @@ AttributeEncoder::encodeReflectancesLift( ...@@ -973,11 +979,12 @@ AttributeEncoder::encodeReflectancesLift(
predictors, weights, startIndex, endIndex, false, reflectances); predictors, weights, startIndex, endIndex, false, reflectances);
PCCLiftPredict(predictors, startIndex, endIndex, false, reflectances); PCCLiftPredict(predictors, startIndex, endIndex, false, reflectances);
} }
const double maxReflectance = (1 << desc.attr_bitdepth) - 1; const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
for (size_t f = 0; f < pointCount; ++f) { for (size_t f = 0; f < pointCount; ++f) {
const int64_t refl =
divExp2RoundHalfInf(reflectances[f], kFixedPointAttributeShift);
pointCloud.setReflectance( pointCloud.setReflectance(
indexesLOD[f], indexesLOD[f], uint16_t(PCCClip(refl, int64_t(0), maxReflectance)));
uint16_t(PCCClip(std::round(reflectances[f]), 0.0, maxReflectance)));
} }
} }
......
...@@ -387,6 +387,55 @@ mortonAddr(const Vec3<T>& vec, int depth) ...@@ -387,6 +387,55 @@ mortonAddr(const Vec3<T>& vec, int depth)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
inline int64_t
PCCClip(const int64_t& n, const int64_t& lower, const int64_t& upper)
{
return std::max(lower, std::min(n, upper));
}
//---------------------------------------------------------------------------
// Integer division of @scalar by 2^shift, rounding intermediate half values
// away from zero.
inline int64_t
divExp2RoundHalfInf(int64_t scalar, int shift)
{
if (!shift)
return scalar;
int64_t s0 = 1 << (shift - 1);
return scalar >= 0 ? (s0 + scalar) >> shift : -((s0 - scalar) >> shift);
}
//---------------------------------------------------------------------------
// Integer division of @scalar by 2^shift, rounding intermediate half values
// away from zero.
inline uint64_t
divExp2RoundHalfInf(uint64_t scalar, int shift)
{
if (!shift)
return scalar;
return ((1 << (shift - 1)) + scalar) >> shift;
}
//---------------------------------------------------------------------------
// Component-wise integer division of @vec by 2^shift, rounding intermediate
// half values away from zero.
template<typename T>
inline Vec3<T>
divExp2RoundHalfInf(Vec3<T> vec, int shift)
{
for (int k = 0; k < 3; ++k)
vec[k] = divExp2RoundHalfInf(vec[k], shift);
return vec;
}
//---------------------------------------------------------------------------
} /* namespace pcc */ } /* namespace pcc */
#endif /* PCCMath_h */ #endif /* PCCMath_h */
...@@ -86,7 +86,7 @@ struct MortonCodeWithIndex { ...@@ -86,7 +86,7 @@ struct MortonCodeWithIndex {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
struct PCCNeighborInfo { struct PCCNeighborInfo {
double weight; uint64_t weight;
uint32_t predictorIndex; uint32_t predictorIndex;
bool operator<(const PCCNeighborInfo& rhs) const bool operator<(const PCCNeighborInfo& rhs) const
{ {
...@@ -105,7 +105,7 @@ struct PCCPredictor { ...@@ -105,7 +105,7 @@ struct PCCPredictor {
Vec3<uint8_t> predictColor( Vec3<uint8_t> predictColor(
const PCCPointSet3& pointCloud, const std::vector<uint32_t>& indexes) const const PCCPointSet3& pointCloud, const std::vector<uint32_t>& indexes) const
{ {
Vec3<double> predicted(0.0); Vec3<int64_t> predicted(0);
if (predMode > neighborCount) { if (predMode > neighborCount) {
/* nop */ /* nop */
} else if (predMode > 0) { } else if (predMode > 0) {
...@@ -118,21 +118,23 @@ struct PCCPredictor { ...@@ -118,21 +118,23 @@ struct PCCPredictor {
for (size_t i = 0; i < neighborCount; ++i) { for (size_t i = 0; i < neighborCount; ++i) {
const Vec3<uint8_t> color = const Vec3<uint8_t> color =
pointCloud.getColor(indexes[neighbors[i].predictorIndex]); pointCloud.getColor(indexes[neighbors[i].predictorIndex]);
const double w = neighbors[i].weight; const uint32_t w = neighbors[i].weight;
for (size_t k = 0; k < 3; ++k) { for (size_t k = 0; k < 3; ++k) {
predicted[k] += w * color[k]; predicted[k] += w * color[k];
} }
} }
for (uint32_t k = 0; k < 3; ++k) {
predicted[k] =
divExp2RoundHalfInf(predicted[k], kFixedPointWeightShift);
}
} }
return Vec3<uint8_t>( return Vec3<uint8_t>(predicted[0], predicted[1], predicted[2]);
uint8_t(std::round(predicted[0])), uint8_t(std::round(predicted[1])),
uint8_t(std::round(predicted[2])));
} }
uint16_t predictReflectance( int64_t predictReflectance(
const PCCPointSet3& pointCloud, const std::vector<uint32_t>& indexes) const const PCCPointSet3& pointCloud, const std::vector<uint32_t>& indexes) const
{ {
double predicted(0.0); int64_t predicted(0);
if (predMode > neighborCount) { if (predMode > neighborCount) {
/* nop */ /* nop */
} else if (predMode > 0) { } else if (predMode > 0) {
...@@ -143,23 +145,54 @@ struct PCCPredictor { ...@@ -143,23 +145,54 @@ struct PCCPredictor {
predicted += neighbors[i].weight predicted += neighbors[i].weight
* pointCloud.getReflectance(indexes[neighbors[i].predictorIndex]); * pointCloud.getReflectance(indexes[neighbors[i].predictorIndex]);
} }
predicted = divExp2RoundHalfInf(predicted, kFixedPointWeightShift);
} }
return uint16_t(std::round(predicted)); return predicted;
} }
void computeWeights() void computeWeights()
{ {
if (neighborCount <= 1) { const uint32_t shift = (1 << kFixedPointWeightShift);
neighbors[0].weight = 1.0; int32_t n = 0;
return; while ((neighbors[0].weight >> n) >= shift) {
++n;
}
if (n > 0) {
for (size_t i = 0; i < neighborCount; ++i) {
neighbors[i].weight = (neighbors[i].weight + (1 << (n - 1))) >> n;
}
} }
double sum = 0.0; while (neighborCount > 1) {
for (uint32_t n = 0; n < neighborCount; ++n) { if (
sum += neighbors[n].weight; neighbors[neighborCount - 1].weight
>= (neighbors[neighborCount - 2].weight << kFixedPointWeightShift)) {
--neighborCount;
} else {
break;
}
} }
assert(sum > 0.0); if (neighborCount <= 1) {
for (uint32_t n = 0; n < neighborCount; ++n) { neighbors[0].weight = shift;
neighbors[n].weight /= sum; } else if (neighborCount == 2) {
const uint64_t d0 = neighbors[0].weight;
const uint64_t d1 = neighbors[1].weight;
const uint64_t sum = d1 + d0;
const uint64_t w1 = (d0 << kFixedPointWeightShift) / sum;
const uint64_t w0 = shift - w1;
neighbors[0].weight = uint32_t(w0);
neighbors[1].weight = uint32_t(w1);
} else {
neighborCount = 3;
const uint64_t d0 = neighbors[0].weight;
const uint64_t d1 = neighbors[1].weight;
const uint64_t d2 = neighbors[2].weight;
const uint64_t sum = d1 * d2 + d0 * d2 + d0 * d1;
const uint64_t w2 = ((d0 * d1) << kFixedPointWeightShift) / sum;
const uint64_t w1 = ((d0 * d2) << kFixedPointWeightShift) / sum;
const uint64_t w0 = shift - (w1 + w2);
neighbors[0].weight = uint32_t(w0);
neighbors[1].weight = uint32_t(w1);
neighbors[2].weight = uint32_t(w2);
} }
} }
...@@ -167,7 +200,7 @@ struct PCCPredictor { ...@@ -167,7 +200,7 @@ struct PCCPredictor {
{ {
neighborCount = (predictorIndex != PCC_UNDEFINED_INDEX) ? 1 : 0; neighborCount = (predictorIndex != PCC_UNDEFINED_INDEX) ? 1 : 0;
neighbors[0].predictorIndex = predictorIndex; neighbors[0].predictorIndex = predictorIndex;
neighbors[0].weight = 1.0; neighbors[0].weight = 1;
predMode = 0; predMode = 0;
} }