File numeric.h
Go to the documentation of this file
// Copyright (c) 2012-2013, IGN France.
// Copyright (c) 2012-2022, Oslandia.
// SPDX-License-Identifier: LGPL-2.0-or-later
#ifndef _SFCGAL_NUMERIC_H_
#define _SFCGAL_NUMERIC_H_
#include <cmath>
#include <limits>
#include "SFCGAL/export.h"
#include "SFCGAL/Kernel.h"
namespace SFCGAL {
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
#elif defined(__GCC__)
#pragma gcc diagnostic push
#pragma gcc diagnostic ignored "-Wfloat-equal"
#endif
inline auto
almostEqual(const double a, const double b, const double epsilon) -> bool
{
// shortcut and handles inf values
if (a == b) {
return true;
}
if (std::isnan(a) || std::isnan(b)) {
return std::isnan(a) && std::isnan(b);
}
const double absA = std::fabs(a);
const double absB = std::fabs(b);
const double diff = std::fabs(a - b);
// fixed epsilon
if (diff <= epsilon) {
return true;
}
return diff <= epsilon * std::max(absA, absB); // adaptative epsilon
}
inline auto
almostEqual(const Kernel::FT &a, const Kernel::FT &b, const Kernel::FT &epsilon)
-> bool
{
// shortcut and handles inf values
if (a == b) {
return true;
}
const Kernel::FT absA = abs(a);
const Kernel::FT absB = abs(b);
const Kernel::FT diff = abs(a - b);
// fixed epsilon
if (diff <= epsilon) {
return true;
}
return diff <= epsilon * std::max(absA, absB); // adaptative epsilon
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GCC__)
#pragma gcc diagnostic pop
#endif
inline double
NaN()
{
return std::numeric_limits<double>::quiet_NaN();
}
inline double
round(const double &v)
{
if (v < 0.0) {
return ::ceil(v - 0.5);
} else {
return ::floor(v + 0.5);
}
}
#ifdef CGAL_USE_GMPXX
SFCGAL_API ::mpz_class
floor(const ::mpq_class &v);
SFCGAL_API ::mpz_class
ceil(const ::mpq_class &v);
SFCGAL_API ::mpz_class
round(const ::mpq_class &v);
#endif
SFCGAL_API CGAL::Gmpz
floor(const CGAL::Gmpq &v);
SFCGAL_API CGAL::Gmpz
ceil(const CGAL::Gmpq &v);
SFCGAL_API CGAL::Gmpz
round(const CGAL::Gmpq &v);
inline Kernel::Vector_3
normalizeVector(const Kernel::Vector_3 &vec)
{
Kernel::FT length = CGAL::sqrt(CGAL::to_double(vec.squared_length()));
return (length > 0) ? vec / length : vec;
}
} // namespace SFCGAL
#endif