mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 02:37:36 +02:00
Improve detection of signbit
This commit is contained in:
54
format.h
54
format.h
@ -579,18 +579,45 @@ class FixedBuffer : public fmt::Buffer<Char> {
|
|||||||
void grow(std::size_t size);
|
void grow(std::size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
template <typename T = void>
|
||||||
|
struct Null {};
|
||||||
|
|
||||||
|
// Dummy implementations of signbit and _ecvt_s called if corresponding system
|
||||||
|
// functions are not available.
|
||||||
|
inline Null<> signbit(...) { return Null<>(); }
|
||||||
|
inline Null<> _ecvt_s(...) { return Null<>(); }
|
||||||
|
|
||||||
// Portable version of signbit.
|
// Portable version of signbit.
|
||||||
inline int getsign(double x) {
|
inline int getsign(double x) {
|
||||||
// When compiled in C++11 mode signbit is no longer a macro but a function
|
class SignBit {
|
||||||
// defined in namespace std and the macro is undefined.
|
private:
|
||||||
# ifdef signbit
|
double value_;
|
||||||
return signbit(x);
|
|
||||||
# else
|
int handle(int result) { return result; }
|
||||||
return std::signbit(x);
|
|
||||||
# endif
|
int handle(fmt::internal::Null<>) {
|
||||||
|
if (value_ < 0) return 1;
|
||||||
|
if (value_ == value_) return 0;
|
||||||
|
int dec = 0, sign = 0;
|
||||||
|
char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
|
||||||
|
_ecvt_s(buffer, sizeof(buffer), value_, 0, &dec, &sign);
|
||||||
|
return sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SignBit(double value) : value_(value) {}
|
||||||
|
|
||||||
|
int call() {
|
||||||
|
// When compiled in C++11 mode signbit is no longer a macro but a
|
||||||
|
// function defined in namespace std and the macro is undefined.
|
||||||
|
using namespace std;
|
||||||
|
return handle(signbit(value_));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return SignBit(x).call();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
// Portable version of isinf.
|
// Portable version of isinf.
|
||||||
# ifdef isinf
|
# ifdef isinf
|
||||||
inline int isinfinity(double x) { return isinf(x); }
|
inline int isinfinity(double x) { return isinf(x); }
|
||||||
@ -609,14 +636,6 @@ inline int isnotanumber(double x) { return std::isnan(x); }
|
|||||||
inline int isnotanumber(long double x) { return std::isnan(x); }
|
inline int isnotanumber(long double x) { return std::isnan(x); }
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
inline int getsign(double value) {
|
|
||||||
if (value < 0) return 1;
|
|
||||||
if (value == value) return 0;
|
|
||||||
int dec = 0, sign = 0;
|
|
||||||
char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
|
|
||||||
_ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
|
|
||||||
return sign;
|
|
||||||
}
|
|
||||||
inline int isinfinity(double x) { return !_finite(x); }
|
inline int isinfinity(double x) { return !_finite(x); }
|
||||||
inline int isinfinity(long double x) {
|
inline int isinfinity(long double x) {
|
||||||
return !_finite(static_cast<double>(x));
|
return !_finite(static_cast<double>(x));
|
||||||
@ -895,9 +914,6 @@ struct Arg : Value {
|
|||||||
template <typename Char>
|
template <typename Char>
|
||||||
struct NamedArg;
|
struct NamedArg;
|
||||||
|
|
||||||
template <typename T = void>
|
|
||||||
struct Null {};
|
|
||||||
|
|
||||||
// A helper class template to enable or disable overloads taking wide
|
// A helper class template to enable or disable overloads taking wide
|
||||||
// characters and strings in MakeValue.
|
// characters and strings in MakeValue.
|
||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
|
Reference in New Issue
Block a user