add new comparator logic
This commit is contained in:
@@ -44,11 +44,11 @@ namespace hack::comparators
|
|||||||
std::vector<std::size_t> m_mismatch_indices; // Индексы несовпадений
|
std::vector<std::size_t> m_mismatch_indices; // Индексы несовпадений
|
||||||
};
|
};
|
||||||
|
|
||||||
// epsilon - допустимая погрешность для float
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
comp_result compare_array_with_file(const std::vector<T>& in, const std::filesystem::path& path, float epsilon = 1e-6f)
|
comp_result compare_array_with_file(const std::vector<T>& in, const std::filesystem::path& path, float relative_epsilon = 1e-6f, /* 0.0001% */ float absolute_epsilon = 1e-12f) /* для чисел близких к нулю */
|
||||||
{
|
{
|
||||||
comp_result res{};
|
comp_result res{};
|
||||||
|
|
||||||
// Открываем файл для чтения в бинарном режиме
|
// Открываем файл для чтения в бинарном режиме
|
||||||
std::ifstream file(path, std::ios::binary);
|
std::ifstream file(path, std::ios::binary);
|
||||||
if (!file.is_open()) throw std::runtime_error("Cannot open file for reading: " + path.string());
|
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())
|
if (target_size != in.size())
|
||||||
{
|
{
|
||||||
|
hack::log()("Size mismatch: file has", target_size, "elements, input has", in.size(), "elements");
|
||||||
res.m_is_equal = false;
|
res.m_is_equal = false;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -74,29 +75,68 @@ namespace hack::comparators
|
|||||||
// Читаем данные из файла
|
// Читаем данные из файла
|
||||||
if (target_size > 0)
|
if (target_size > 0)
|
||||||
{
|
{
|
||||||
file.read(reinterpret_cast<char*>(target.data()), target_size * sizeof(float));
|
file.read(reinterpret_cast<char*>(target.data()), target_size * sizeof(T));
|
||||||
if (!file) throw std::runtime_error("Failed to read data from file: " + path.string());
|
if (!file) throw std::runtime_error("Failed to read data from file: " + path.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сравниваем элементы с учётом погрешности
|
// Сравниваем элементы с учётом погрешностей
|
||||||
res.m_mismatch_count = 0;
|
res.m_mismatch_count = 0;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < target_size; ++i)
|
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<float>(target[i]) - static_cast<float>(in[i]));
|
||||||
|
|
||||||
|
// Максимальное абсолютное значение из двух чисел
|
||||||
|
float max_abs = std::max(std::fabs(static_cast<float>(target[i])),
|
||||||
|
std::fabs(static_cast<float>(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_count;
|
||||||
res.m_mismatch_indices.push_back(i);
|
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);
|
res.m_is_equal = (res.m_mismatch_count == 0);
|
||||||
|
|
||||||
if (!res.m_is_equal)
|
// Финальный отчет
|
||||||
|
if (res.m_is_equal)
|
||||||
{
|
{
|
||||||
log()(in);
|
hack::log()("TRUE");
|
||||||
log()(target);
|
}
|
||||||
|
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;
|
return res;
|
||||||
|
|||||||
Reference in New Issue
Block a user