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
224 static const std::vector<triangularToIJ> preMap = []() {
226 constexpr
size_t nn =
n * (
n - 1) / 2;
227 std::vector<triangularToIJ> indexMap(nn);
228 for (int8_t
i = 1;
i <
n; ++
i) {
229 const int indexConst =
offset[
i];
230 for (int8_t j = 0; j <
i; ++j) {
231 indexMap[indexConst + j] = {
i, j };
246 calculateAllDistances(
const Component1D* componentsIn,
251 std::assume_aligned<GSFConstants::alignment>(componentsIn);
253 std::assume_aligned<GSFConstants::alignment>(distancesIn);
254 for (
int i = 1;
i <
n; ++
i) {
255 const int indexConst =
offset[
i];
257 for (
int j = 0; j <
i; ++j) {
259 distances[indexConst + j] = symmetricKL(componentI, componentJ);
276 std::array<int8_t, GSFConstants::maxComponentsAfterConvolution>& mergingIndex,
283 std::assume_aligned<GSFConstants::alignment>(distancesIn);
285 std::assume_aligned<GSFConstants::alignment>(componentsIn);
289 const int last = (
n - 1);
290 const int indexOffsetJ =
offset[minFrom];
291 const int indexOffsetLast =
offset[last];
293 if (minFrom != last) {
295 for (
int i = 0;
i < minFrom; ++
i) {
296 std::swap(distances[indexOffsetJ +
i], distances[indexOffsetLast +
i]);
299 for (
int i = minFrom + 1;
i < last; ++
i) {
304 std::swap(components[minFrom], components[last]);
305 std::swap(mergingIndex[minFrom], mergingIndex[last]);
312 const int indexConst =
offset[minTo];
316 for (
int i = 0;
i < minTo; ++
i) {
318 const int index = indexConst +
i;
319 distances[
index] = symmetricKL(componentI, componentJ);
322 for (
int i = minTo + 1;
i < last; ++
i) {
325 distances[
index] = symmetricKL(componentI, componentJ);
336 const int8_t reducedSize)
340 Component1D* components = std::assume_aligned<GSFConstants::alignment>(
341 copyComponents.components.data());
343 int nn =
n * (
n - 1) / 2;
344 int nnpadded = vAlgs::numPadded<STRIDEForKL>(nn);
348 calculateAllDistances(components, distances.buffer(),
n);
350 std::array<int8_t, GSFConstants::maxComponentsAfterConvolution>
352 std::iota(mergingIndex.begin(), mergingIndex.end(), 0);
355 int numberOfComponentsLeft =
n;
357 while (numberOfComponentsLeft > reducedSize) {
360 const triangularToIJ conversion =
convert(minIndex);
361 int8_t minTo = conversion.I;
362 int8_t minFrom = conversion.J;
364 if (mergingIndex[minTo] < mergingIndex[minFrom]) {
368 const int8_t miniToreturn = mergingIndex[minTo];
369 const int8_t minjToreturn = mergingIndex[minFrom];
370 result.merges[
result.numMerges] = { miniToreturn, minjToreturn };
373 combine(components[minTo], components[minFrom]);
375 numberOfComponentsLeft = updateDistances(components,
380 numberOfComponentsLeft);
383 nn =
offset[numberOfComponentsLeft];
384 nnpadded = numDistances(nn, distances.buffer());
398 throw std::runtime_error(
"findMerges :Invalid InputSize or reducedSize");
400 return findMergesImpl(componentsIn,
n, reducedSize);