#6700 closed task (fixed)
ABS -> std::abs for C++
Reported by: | Kurt Schwehr | Owned by: | Kurt Schwehr |
---|---|---|---|
Priority: | normal | Milestone: | |
Component: | default | Version: | unspecified |
Severity: | minor | Keywords: | |
Cc: |
Description (last modified by )
Unless some compiler strangeness crops up, I'm going to try to convert all of the uses of the ABS macro in C++ to std::abs.
std::abs should help with possible better type checking and possibly better optimization compared to the existing macro. Worst case, there should be no difference. We do need to keep an eye out for issues with NaN and Inf behavior changes.
#ifndef ABS # define ABS(x) ((x<0) ? (-1*(x)) : x) #endif
e.g. r35943
The one quirk is that the float/double ones are in <cmath> and the integral type ones are in <cstdlib>
Change History (6)
comment:1 by , 8 years ago
Description: | modified (diff) |
---|---|
Owner: | changed from | to
Status: | new → assigned |
comment:2 by , 8 years ago
comment:3 by , 8 years ago
A lot of the uses of ABS are related to doing float/double almost equal. We need a proper templated CPLAlmostEqual(T v1, T v2, delta=1e-9) for C++. Same goes for float comparisons in autotest python code to match what self.assertAlmostEqual does in unittest.
This isn't great for C++. The delta is fixed and it always uses fabs. std::abs in <cmath> will do match the float or double type.
// From cpl_port.h /* -------------------------------------------------------------------- */ /* Macro to test equality of two floating point values. */ /* We use fabs() function instead of ABS() macro to avoid side */ /* effects. */ /* -------------------------------------------------------------------- */ /*! @cond Doxygen_Suppress */ #ifndef CPLIsEqual # define CPLIsEqual(x,y) (fabs((x) - (y)) < 0.0000000000001) #endif
Something like this is possibly borked in some cases.
#ifdef __cplusplus #include <cmath> #include <cstdlib> template<typename T> inline bool CPLAlmostEqual( T x, T y, T delta ) { if (is_nan(x) || is_nan(y)) return false; return std::abs(x - y) < delta; } #endif
We'd want to look carefully at
// Returns true iff this number is at most kMaxUlps ULP's away from // rhs. In particular, this function: // // - returns false if either number is (or both are) NAN. // - treats really large numbers as almost equal to infinity. // - thinks +0.0 and -0.0 are 0 DLP's apart. bool AlmostEquals(const FloatingPoint& rhs) const { // The IEEE standard says that any comparison operation involving // a NAN must return false. if (is_nan() || rhs.is_nan()) return false; return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <= kMaxUlps; }
and http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison
comment:4 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
In r35947: Fix compilation with ancient mingw32 (refs #6700)