%% options copyright owner = Dirk Krause copyright year = 2017-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file dk4math.h Functions and macros not available on all platforms. If some of the functions or macros rint(), isgreater(), isgreaterequal(), isless() and islessequal() - typically defined in math.h - are missing, this header file defines either macros or static inline functions calling the provided fallback functions dk4ma_rint(), dk4ma_isgreater(), dk4ma_isgreaterequal(), dk4ma_isless() or dk4ma_islessequal(). Inline functions are used if both DK4_HAVE_INLINE and DK4_USE_INLINE are enabled, macros are used otherwise. Although the CERT C coding standard prefers use of inline functions over macros, I prefer macros as the static inline functions (a) create slightly larger object modules, (b) create warnings for those static inline functions not used in the module and (c) might create warnings if the compiler decides to use real functions instead of generating inline code. The dk4ma_rint() function in the module is always compiled to avoid ``empty compilation unit'' warnings. The other functions in this module are only compiled if necessary. */ #ifndef DK4CONF_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4conf.h" #else #include #endif #endif #if DK4_HAVE_MATH_H #ifndef MATH_H_INCLUDED #if DK4_ON_WINDOWS #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES 1 #endif #endif #include #define MATH_H_INCLUDED 1 #endif #endif #if DK4_HAVE_FLOAT_H #ifndef FLOAT_H_INCLUDED #include #define FLOAT_H_INCLUDED 1 #endif #endif #ifdef __cplusplus extern "C" { #endif #if (!(DK4_HAVE_RINT)) /** Round value to next integer. @param x floating point valued. @return Floating point value rounded to next integer. */ double dk4ma_rint(double x); #endif #if (!(DK4_HAVE_ISGREATER)) /** Check whether a is greater than b. @param a Floating point value. @param b Floating point value. @return Comparison result. */ int dk4ma_isgreater(double a, double b); #endif #if (!(DK4_HAVE_ISGREATEREQUAL)) /** Check whether a is greater than or equal to b. @param a Floating point value. @param b Floating point value. @return Comparison result. */ int dk4ma_isgreaterequal(double a, double b); #endif #if (!(DK4_HAVE_ISLESS)) /** Check whether a is less than b. @param a Floating point value. @param b Floating point value. @return Comparison result. */ int dk4ma_isless(double a, double b); #endif #if (!(DK4_HAVE_ISLESSEQUAL)) /** Check whether a is less than or equal to b. @param a Floating point value. @param b Floating point value. @return Comparison result. */ int dk4ma_islessequal(double a, double b); #endif /** Check whether or not a double value is finite. @param d Value to check. @return Nonzero for finite value, zero for infinite value or NaN. */ int dk4ma_is_finite(double d); /** Check whether double value is in normalized representation. @param d Value to check. @return Nonzero for normalized value, zero for non-normalized value. */ int dk4ma_is_normal(double d); #ifdef __cplusplus } #endif #if (!(DK4_HAVE_RINT)) #if DK4_HAVE_INLINE && DK4_USE_INLINE static inline double rint(double x) { return (dk4ma_rint(x)); } #else /** The rint() function rounds to next integer. */ #define rint(x) dk4ma_rint(x) #endif #endif #if (!(DK4_HAVE_ISGREATER)) #if DK4_HAVE_INLINE && DK4_USE_INLINE /** Compare two double values, check if left value is greater than right value. @param a Left value. @param b Right value. @return Comparison result. */ static inline int isgreater(double a, double b) { return (dk4ma_isgreater(a,b)); } #else /** Compare to values. */ #define isgreater(a,b) dk4ma_isgreater(a,b) #endif #endif #if (!(DK4_HAVE_ISGREATEREQUAL)) #if DK4_HAVE_INLINE && DK4_USE_INLINE /** Compare two double values, check if left value is greater than or equal to right value. @param a Left value. @param b Right value. @return Comparison result. */ static inline int isgreaterequal(double a, double b) { return (dk4ma_isgreaterequal(a,b)); } #else /** Compare to values. */ #define isgreaterequal(a,b) dk4ma_isgreaterequal(a,b) #endif #endif #if (!(DK4_HAVE_ISLESS)) #if DK4_HAVE_INLINE && DK4_USE_INLINE /** Compare two double values, check if left value is less than right value. @param a Left value. @param b Right value. @return Comparison result. */ static inline int isless(double a, double b) { return (dk4ma_isless(a,b)); } #else /** Compare to values. */ #define isless(a,b) dk4ma_isless(a,b) #endif #endif #if (!(DK4_HAVE_ISLESSEQUAL)) #if DK4_HAVE_INLINE && DK4_USE_INLINE /** Compare two double values, check if left value is less than or equal to right value. @param a Left value. @param b Right value. @return Comparison result. */ static inline int islessequal(double a, double b) { return (dk4ma_islessequal(a,b)); } #else /** Compare to values. */ #define islessequal(a,b) dk4ma_islessequal(a,b) #endif #endif %% module #include "dk4conf.h" #include "dk4math.h" #if (!(DK4_HAVE_RINT)) double dk4ma_rint(double x) { return (floor(x+0.5)); } #endif #if (!(DK4_HAVE_ISGREATER)) int dk4ma_isgreater(double a, double b) { int back = 0; #if DK4_HAVE_ISFINITE if ((isfinite(a)) && (isfinite(b))) { #else #if DK4_HAVE__FINITE if ((_finite(a)) && (_finite(b))) { #endif #endif if (a > b) { back = 1; } #if DK4_HAVE_ISFINITE } #else #if DK4_HAVE__FINITE } #endif #endif return back; } #endif #if (!(DK4_HAVE_ISGREATEREQUAL)) int dk4ma_isgreaterequal(double a, double b) { int back = 0; #if DK4_HAVE_ISFINITE if ((isfinite(a)) && (isfinite(b))) { #else #if DK4_HAVE__FINITE if ((_finite(a)) && (_finite(b))) { #endif #endif if (a >= b) { back = 1; } #if DK4_HAVE_ISFINITE } #else #if DK4_HAVE__FINITE } #endif #endif return back; } #endif #if (!(DK4_HAVE_ISLESS)) int dk4ma_isless(double a, double b) { int back = 0; #if DK4_HAVE_ISFINITE if ((isfinite(a)) && (isfinite(b))) { #else #if DK4_HAVE__FINITE if ((_finite(a)) && (_finite(b))) { #endif #endif if (a < b) { back = 1; } #if DK4_HAVE_ISFINITE } #else #if DK4_HAVE__FINITE } #endif #endif return back; } #endif #if (!(DK4_HAVE_ISLESSEQUAL)) int dk4ma_islessequal(double a, double b) { int back = 0; #if DK4_HAVE_ISFINITE if ((isfinite(a)) && (isfinite(b))) { #else #if DK4_HAVE__FINITE if ((_finite(a)) && (_finite(b))) { #endif #endif if (a <= b) { back = 1; } #if DK4_HAVE_ISFINITE } #else #if DK4_HAVE__FINITE } #endif #endif return back; } #endif int dk4ma_is_finite(double d) { int back = 0; #if _WIN32 back = ((0 != _finite(d)) ? 1 : 0); #else back = ((0 != isfinite(d)) ? 1 : 0); #endif return back; } int dk4ma_is_normal(double d) { int back = 0; #if _WIN32 switch (_fpclass(d)) { case _FPCLASS_NN : case _FPCLASS_NZ : case _FPCLASS_PZ : case _FPCLASS_PN : { back = 1; } break; } #else back = ((0 != isnormal(d)) ? 1 : 0); #endif return back; } /* vim: set ai sw=4 ts=4 : */