diff --git a/src/ailego/algorithm/kmeans.h b/src/ailego/algorithm/kmeans.h index 1fa5b2f..16b2efc 100644 --- a/src/ailego/algorithm/kmeans.h +++ b/src/ailego/algorithm/kmeans.h @@ -492,16 +492,15 @@ class NumericalKmeansContext { MatrixHelper::ReverseTranspose(src, dim >> 2, dst); } - //! Compute Norm2 - template ::value>::type> + //! Normalize with L2 norm for floating-point values, otherwise do nothing static void Norm2(ValueType *data, size_t dim, float *norm) { - Normalizer::L2(data, dim, norm); - } - - //! Compute Norm2, for non-float do nothing - static void Norm2(ValueType * /*data*/, size_t /*dim*/, float *norm) { - *norm = 0.0f; + if constexpr (IsFloatingPoint::value) { + Normalizer::L2(data, dim, norm); + } else { + (void)data; + (void)dim; + *norm = 0.0f; + } } private: @@ -843,16 +842,15 @@ class NumericalInnerProductKmeansContext { MatrixHelper::ReverseTranspose(src, dim >> 2, dst); } - //! Compute Norm2 - template ::value>::type> + //! Normalize with L2 norm for floating-point values, otherwise do nothing static void Norm2(ValueType *data, size_t dim, float *norm) { - Normalizer::L2(data, dim, norm); - } - - //! Compute Norm2, for non-float do nothing - static void Norm2(ValueType * /*data*/, size_t /*dim*/, float *norm) { - *norm = 0.0f; + if constexpr (IsFloatingPoint::value) { + Normalizer::L2(data, dim, norm); + } else { + (void)data; + (void)dim; + *norm = 0.0f; + } } private: diff --git a/src/ailego/algorithm/lloyd_cluster.h b/src/ailego/algorithm/lloyd_cluster.h index b130b52..2bebd0b 100644 --- a/src/ailego/algorithm/lloyd_cluster.h +++ b/src/ailego/algorithm/lloyd_cluster.h @@ -202,7 +202,7 @@ class LloydCluster { if (spherical_) { for (size_t i = 0, n = centroids_.count(); i != n; ++i) { - float norm; + float norm = 0.0f; ContextType::Norm2(centroids_[i], centroids_.dimension(), &norm); } } diff --git a/tests/ailego/algorithm/kmeans_test.cc b/tests/ailego/algorithm/kmeans_test.cc index b2feb63..2290423 100644 --- a/tests/ailego/algorithm/kmeans_test.cc +++ b/tests/ailego/algorithm/kmeans_test.cc @@ -239,6 +239,39 @@ TEST(NumericalKmeans, FP32_General_InnerProduct) { } } +TEST(NumericalInnerProductKmeansContext, NormalizeFloatingPointCentroid) { + float centroid[] = {3.0f, 4.0f}; + float norm = 0.0f; + + ailego::NumericalInnerProductKmeansContext::Norm2(centroid, 2, &norm); + + EXPECT_FLOAT_EQ(norm, 5.0f); + EXPECT_FLOAT_EQ(centroid[0], 0.6f); + EXPECT_FLOAT_EQ(centroid[1], 0.8f); +} + +TEST(NumericalKmeansContext, NormalizeFloatingPointCentroid) { + float centroid[] = {3.0f, 4.0f}; + float norm = 0.0f; + + ailego::NumericalKmeansContext::Norm2(centroid, 2, &norm); + + EXPECT_FLOAT_EQ(norm, 5.0f); + EXPECT_FLOAT_EQ(centroid[0], 0.6f); + EXPECT_FLOAT_EQ(centroid[1], 0.8f); +} + +TEST(NumericalKmeansContext, KeepIntegerCentroidUnchanged) { + int8_t centroid[] = {3, 4}; + float norm = 1.0f; + + ailego::NumericalKmeansContext::Norm2(centroid, 2, &norm); + + EXPECT_FLOAT_EQ(norm, 0.0f); + EXPECT_EQ(centroid[0], 3); + EXPECT_EQ(centroid[1], 4); +} + TEST(NumericalKmeans, FP16_General_InnerProduct) { const size_t DIMENSION = 20; const size_t K_VALUE = 20;