30 #if HAVE_FUNCTION_MULTIVERSIONING
34 return vAlgs::vIdxOfMin<128>(distancesIn,
n);
36 #if HAVE_FUNCTION_MULTIVERSIONING
38 int vIdxOfMin(
const float* distancesIn,
int n) {
39 return vAlgs::vIdxOfMin<256>(distancesIn,
n);
48 constexpr
size_t STRIDEForKL = vAlgs::strideOfNumSIMDVec<256,float>(4);
49 constexpr
size_t ALIGNMENTForKL = vAlgs::alignmentForArray<256>();
68 const double meanDifference = componentI.mean - componentJ.mean;
69 const double inverCovSum = componentI.invCov + componentJ.invCov;
70 const double term1 = componentI.invCov * componentJ.cov;
71 const double term2 = componentJ.invCov * componentI.cov;
72 const double term3 = meanDifference * inverCovSum * meanDifference;
73 return term1 + term2 + term3;
87 const double sumWeight = updated.weight + removed.weight;
89 const double invSumWeight = 1. / sumWeight;
90 const double weightI_IJ = updated.weight * invSumWeight;
91 const double weightJ_IJ = removed.weight * invSumWeight;
92 const double meanDiff = (updated.mean - removed.mean);
94 const double sumMean = weightI_IJ * updated.mean + weightJ_IJ * removed.mean;
96 const double sumVariance = weightI_IJ * updated.cov +
97 weightJ_IJ * removed.cov +
98 weightI_IJ * weightJ_IJ * meanDiff * meanDiff;
99 updated.mean = sumMean;
100 updated.cov = sumVariance;
101 updated.invCov = 1. / sumVariance;
102 updated.weight = sumWeight;
106 numDistances(
const int n,
float* distancesIn)
108 const int npadded = vAlgs::numPadded<STRIDEForKL>(
n);
191 constexpr std::array<int, GSFConstants::maxComponentsAfterConvolution>
194 std::array<int, n>
tmp = {};
195 for (
int i = 0;
i <
n; ++
i) {
205 struct triangularToIJ
215 inline triangularToIJ
219 throw std::out_of_range(
"KLGaussianMixtureReduction.cxx::convert : idx is negative");
227 static const std::vector<triangularToIJ> preMap = []() {
229 constexpr
size_t nn =
n * (
n - 1) / 2;
230 std::vector<triangularToIJ> indexMap(nn);
231 for (int8_t
i = 1;
i <
n; ++
i) {
232 const int indexConst =
offset[
i];
233 for (int8_t j = 0; j <
i; ++j) {
234 indexMap[indexConst + j] = {
i, j };
249 calculateAllDistances(
const Component1D* componentsIn,
254 std::assume_aligned<GSFConstants::alignment>(componentsIn);
256 std::assume_aligned<GSFConstants::alignment>(distancesIn);
257 for (
int i = 1;
i <
n; ++
i) {
258 const int indexConst =
offset[
i];
260 for (
int j = 0; j <
i; ++j) {
262 distances[indexConst + j] = symmetricKL(componentI, componentJ);
279 std::array<int8_t, GSFConstants::maxComponentsAfterConvolution>& mergingIndex,
286 std::assume_aligned<GSFConstants::alignment>(distancesIn);
288 std::assume_aligned<GSFConstants::alignment>(componentsIn);
292 const int last = (
n - 1);
293 const int indexOffsetJ =
offset[minFrom];
294 const int indexOffsetLast =
offset[last];
296 if (minFrom != last) {
298 for (
int i = 0;
i < minFrom; ++
i) {
299 std::swap(distances[indexOffsetJ +
i], distances[indexOffsetLast +
i]);
302 for (
int i = minFrom + 1;
i < last; ++
i) {
307 std::swap(components[minFrom], components[last]);
308 std::swap(mergingIndex[minFrom], mergingIndex[last]);
315 const int indexConst =
offset[minTo];
319 for (
int i = 0;
i < minTo; ++
i) {
321 const int index = indexConst +
i;
322 distances[
index] = symmetricKL(componentI, componentJ);
325 for (
int i = minTo + 1;
i < last; ++
i) {
328 distances[
index] = symmetricKL(componentI, componentJ);
339 const int8_t reducedSize)
343 Component1D* components = std::assume_aligned<GSFConstants::alignment>(
344 copyComponents.components.data());
346 int nn =
n * (
n - 1) / 2;
347 int nnpadded = vAlgs::numPadded<STRIDEForKL>(nn);
351 calculateAllDistances(components, distances.buffer(),
n);
353 std::array<int8_t, GSFConstants::maxComponentsAfterConvolution>
355 std::iota(mergingIndex.begin(), mergingIndex.end(), 0);
358 int numberOfComponentsLeft =
n;
360 while (numberOfComponentsLeft > reducedSize) {
363 const triangularToIJ conversion =
convert(minIndex);
364 int8_t minTo = conversion.I;
365 int8_t minFrom = conversion.J;
367 if (mergingIndex[minTo] < mergingIndex[minFrom]) {
371 const int8_t miniToreturn = mergingIndex[minTo];
372 const int8_t minjToreturn = mergingIndex[minFrom];
373 result.merges[
result.numMerges] = { miniToreturn, minjToreturn };
376 combine(components[minTo], components[minFrom]);
378 numberOfComponentsLeft = updateDistances(components,
383 numberOfComponentsLeft);
386 nn =
offset[numberOfComponentsLeft];
387 nnpadded = numDistances(nn, distances.buffer());
401 throw std::runtime_error(
"findMerges :Invalid InputSize or reducedSize");
403 return findMergesImpl(componentsIn,
n, reducedSize);