From 7cb97ff8d9515f85f85c31645cf49e58537ecd2b Mon Sep 17 00:00:00 2001 From: chatlanin Date: Fri, 26 Dec 2025 19:48:25 +0300 Subject: [PATCH] add new comparator logic --- src/hack/comparators/comparators.hpp | 62 +++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/hack/comparators/comparators.hpp b/src/hack/comparators/comparators.hpp index d65b0d6..fe6d06f 100644 --- a/src/hack/comparators/comparators.hpp +++ b/src/hack/comparators/comparators.hpp @@ -44,11 +44,11 @@ namespace hack::comparators std::vector m_mismatch_indices; // Индексы несовпадений }; - // epsilon - допустимая погрешность для float template - comp_result compare_array_with_file(const std::vector& in, const std::filesystem::path& path, float epsilon = 1e-6f) + comp_result compare_array_with_file(const std::vector& in, const std::filesystem::path& path, float relative_epsilon = 1e-6f, /* 0.0001% */ float absolute_epsilon = 1e-12f) /* для чисел близких к нулю */ { comp_result res{}; + // Открываем файл для чтения в бинарном режиме std::ifstream file(path, std::ios::binary); if (!file.is_open()) throw std::runtime_error("Cannot open file for reading: " + path.string()); @@ -64,6 +64,7 @@ namespace hack::comparators // Сравниваем размеры if (target_size != in.size()) { + hack::log()("Size mismatch: file has", target_size, "elements, input has", in.size(), "elements"); res.m_is_equal = false; return res; } @@ -74,29 +75,68 @@ namespace hack::comparators // Читаем данные из файла if (target_size > 0) { - file.read(reinterpret_cast(target.data()), target_size * sizeof(float)); + file.read(reinterpret_cast(target.data()), target_size * sizeof(T)); if (!file) throw std::runtime_error("Failed to read data from file: " + path.string()); } - // Сравниваем элементы с учётом погрешности + // Сравниваем элементы с учётом погрешностей res.m_mismatch_count = 0; + for (std::size_t i = 0; i < target_size; ++i) { - auto def = std::fabs(target[i]) - std::fabs(in[i]); - if (std::fabs(def) > epsilon) + // Вычисляем абсолютную разность + float diff = std::fabs(static_cast(target[i]) - static_cast(in[i])); + + // Максимальное абсолютное значение из двух чисел + float max_abs = std::max(std::fabs(static_cast(target[i])), + std::fabs(static_cast(in[i]))); + + bool is_equal = false; + + // Выбираем стратегию сравнения + if (max_abs < absolute_epsilon) + { + // Оба числа очень маленькие (близки к нулю) + // Используем абсолютную погрешность + is_equal = (diff <= absolute_epsilon); + } + else + { + // Используем относительную погрешность + float relative_diff = diff / max_abs; + is_equal = (relative_diff <= relative_epsilon); + } + + if (!is_equal) { - hack::log()(def, target[i], in[i]); ++res.m_mismatch_count; res.m_mismatch_indices.push_back(i); + + // Ограничиваем вывод для слишком большого количества несовпадений + if (res.m_mismatch_count >= 100 && res.m_mismatch_count % 1000 == 0) + hack::log()("Mismatch count reached", res.m_mismatch_count, "at index", i); } } res.m_is_equal = (res.m_mismatch_count == 0); - - if (!res.m_is_equal) + + // Финальный отчет + if (res.m_is_equal) { - log()(in); - log()(target); + hack::log()("TRUE"); + } + else + { + hack::log()("FALSE:", res.m_mismatch_count, "mismatches out of", target_size, "elements (", (100.0f * res.m_mismatch_count / target_size), "%)"); + + // Показываем первые 10 индексов несовпадений + size_t examples_to_show = std::min(size_t(10), res.m_mismatch_indices.size()); + hack::log()("First", examples_to_show, "mismatch indices:"); + for (size_t j = 0; j < examples_to_show; ++j) + { + size_t idx = res.m_mismatch_indices[j]; + hack::log()(" [", idx, "] file:", target[idx], "vs input:", in[idx], "diff:", std::fabs(target[idx] - in[idx])); + } } return res;