/*
 * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
 *
 * This source code and/or documentation ("Licensed Deliverables") are
 * subject to NVIDIA intellectual property rights under U.S. and
 * international Copyright laws.
 */

#pragma once

#include <algorithm>
#include <cmath>

namespace cugraph::ops::catch2 {

/**
 * @brief Compare to floating point numbers approximately
 *
 * @tparam DataT data type
 */
template <typename DataT>
struct compare_approx {
  explicit compare_approx(DataT _eps) : eps_(_eps) {}

  bool operator()(const DataT& a, const DataT& b) const
  {
    if (std::isnan(a) && std::isnan(b)) return true;
    if (a == b) return true;
    DataT diff = std::abs(a - b);
    if (diff < eps_) return true;
    DataT m = std::max(std::abs(a), std::abs(b));
    return diff / m <= eps_;
  }

  [[nodiscard]] DataT tolerance() const { return eps_; }

 private:
  DataT eps_;
};  // struct compare_approx

}  // namespace cugraph::ops::catch2
