2020-06-18 07:55:56 +02:00
|
|
|
// The Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) The Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2020 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
|
|
|
|
#ifndef __GNUC__
|
|
|
|
#pragma STDC FENV_ACCESS on
|
|
|
|
#endif
|
|
|
|
|
2022-06-14 23:15:53 +02:00
|
|
|
[[gnu::visibility("protected")]]
|
2022-03-05 21:21:01 +01:00
|
|
|
void
|
|
|
|
ircd::fpe::debug_info()
|
|
|
|
{
|
|
|
|
log::logf
|
|
|
|
{
|
|
|
|
log::star, log::DEBUG,
|
|
|
|
"FLT RAD=%d DIG=%-2d MANT=%-3d EPS=%-7lf MIN=%-8lf MAX=%-7lf"
|
|
|
|
" EXPMIN=%-7d EXPMAX=%-6d EXP10MIN=%-6d EXP10MAX=%-5d",
|
|
|
|
FLT_RADIX,
|
|
|
|
FLT_DIG,
|
|
|
|
FLT_MANT_DIG,
|
|
|
|
FLT_EPSILON,
|
|
|
|
FLT_MIN,
|
|
|
|
FLT_MAX,
|
|
|
|
FLT_MIN_EXP,
|
|
|
|
FLT_MAX_EXP,
|
|
|
|
FLT_MIN_10_EXP,
|
|
|
|
FLT_MAX_10_EXP,
|
|
|
|
};
|
|
|
|
|
|
|
|
log::logf
|
|
|
|
{
|
|
|
|
log::star, log::DEBUG,
|
|
|
|
"DBL RAD=%d DIG=%-2d MANT=%-3d EPS=%-7lf MIN=%-8lf MAX=%-7lf"
|
|
|
|
" EXPMIN=%-7d EXPMAX=%-6d EXP10MIN=%-6d EXP10MAX=%-5d",
|
|
|
|
FLT_RADIX,
|
|
|
|
DBL_DIG,
|
|
|
|
DBL_MANT_DIG,
|
|
|
|
DBL_EPSILON,
|
|
|
|
DBL_MIN,
|
|
|
|
DBL_MAX,
|
|
|
|
DBL_MIN_EXP,
|
|
|
|
DBL_MAX_EXP,
|
|
|
|
DBL_MIN_10_EXP,
|
|
|
|
DBL_MAX_10_EXP,
|
|
|
|
};
|
|
|
|
|
|
|
|
log::logf
|
|
|
|
{
|
|
|
|
log::star, log::DEBUG,
|
|
|
|
"LDB RAD=%d DIG=%-2d MANT=%-3d EPS=%-7lf MIN=%-8lf MAX=%-7lf"
|
|
|
|
" EXPMIN=%-7d EXPMAX=%-6d EXP10MIN=%-6d EXP10MAX=%-5d",
|
|
|
|
FLT_RADIX,
|
|
|
|
LDBL_DIG,
|
|
|
|
LDBL_MANT_DIG,
|
|
|
|
LDBL_EPSILON,
|
|
|
|
LDBL_MIN,
|
|
|
|
LDBL_MAX,
|
|
|
|
LDBL_MIN_EXP,
|
|
|
|
LDBL_MAX_EXP,
|
|
|
|
LDBL_MIN_10_EXP,
|
|
|
|
LDBL_MAX_10_EXP,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-05-26 21:00:07 +02:00
|
|
|
[[gnu::cold]]
|
2020-06-18 07:55:56 +02:00
|
|
|
void
|
2020-06-18 10:01:23 +02:00
|
|
|
ircd::fpe::_throw_errors(const ushort &flags)
|
2020-06-18 07:55:56 +02:00
|
|
|
{
|
2020-06-18 10:01:23 +02:00
|
|
|
assert(flags);
|
2020-12-21 15:43:15 +01:00
|
|
|
|
|
|
|
char buf[128];
|
2020-06-18 07:55:56 +02:00
|
|
|
throw std::domain_error
|
|
|
|
{
|
|
|
|
reflect(buf, flags)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::fpe::reflect(const mutable_buffer &buf,
|
|
|
|
const ushort &flags)
|
|
|
|
{
|
2022-05-21 02:39:22 +02:00
|
|
|
window_buffer window{buf};
|
|
|
|
const auto append{[&window](const auto &flag)
|
2020-06-18 07:55:56 +02:00
|
|
|
{
|
2022-05-21 02:39:22 +02:00
|
|
|
window([&flag](const mutable_buffer &buf)
|
2020-06-18 07:55:56 +02:00
|
|
|
{
|
|
|
|
return strlcpy(buf, reflect(flag));
|
|
|
|
});
|
|
|
|
}};
|
|
|
|
|
|
|
|
for(size_t i(0); i < sizeof(flags) * 8; ++i)
|
|
|
|
if(flags & (1 << i))
|
|
|
|
append(1 << i);
|
|
|
|
|
2022-05-21 02:39:22 +02:00
|
|
|
return window.completed();
|
2020-06-18 07:55:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::fpe::reflect(const ushort &flag)
|
2021-03-07 10:34:12 +01:00
|
|
|
noexcept
|
2020-06-18 07:55:56 +02:00
|
|
|
{
|
|
|
|
switch(flag)
|
|
|
|
{
|
|
|
|
case 0: return "";
|
|
|
|
case FE_INVALID: return "INVALID";
|
|
|
|
case FE_DIVBYZERO: return "DIVBYZERO";
|
|
|
|
case FE_UNDERFLOW: return "UNDERFLOW";
|
|
|
|
case FE_OVERFLOW: return "OVERFLOW";
|
|
|
|
case FE_INEXACT: return "INEXACT";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "?????";
|
|
|
|
}
|
|
|
|
|
|
|
|
ircd::string_view
|
|
|
|
ircd::fpe::reflect_sicode(const int &code)
|
2021-03-07 10:34:12 +01:00
|
|
|
noexcept
|
2020-06-18 07:55:56 +02:00
|
|
|
{
|
|
|
|
switch(code)
|
|
|
|
{
|
|
|
|
#if defined(HAVE_SIGNAL_H) && defined(FPE_INTDIV)
|
|
|
|
case FPE_INTDIV: return "INTDIV";
|
|
|
|
case FPE_INTOVF: return "INTOVF";
|
|
|
|
case FPE_FLTDIV: return "FLTDIV";
|
|
|
|
case FPE_FLTOVF: return "FLTOVF";
|
|
|
|
case FPE_FLTUND: return "FLTUND";
|
|
|
|
case FPE_FLTRES: return "FLTRES";
|
|
|
|
case FPE_FLTINV: return "FLTINV";
|
|
|
|
case FPE_FLTSUB: return "FLTSUB";
|
|
|
|
#endif // HAVE_SIGNAL_H
|
|
|
|
}
|
|
|
|
|
|
|
|
return "?????";
|
|
|
|
}
|
2021-03-07 10:34:12 +01:00
|
|
|
|
|
|
|
template<class T>
|
|
|
|
ircd::string_view
|
|
|
|
ircd::fpe::classify(const T &a)
|
|
|
|
noexcept
|
|
|
|
{
|
|
|
|
switch(std::fpclassify(a))
|
|
|
|
{
|
|
|
|
case FP_NAN: return "NAN";
|
|
|
|
case FP_ZERO: return "ZERO";
|
|
|
|
case FP_NORMAL: return "NORMAL";
|
|
|
|
case FP_SUBNORMAL: return "SUBNORMAL";
|
|
|
|
case FP_INFINITE: return "INFINITE";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "????";
|
|
|
|
}
|
|
|
|
template ircd::string_view ircd::fpe::classify(const long double &a) noexcept;
|
|
|
|
template ircd::string_view ircd::fpe::classify(const double &a) noexcept;
|
|
|
|
template ircd::string_view ircd::fpe::classify(const float &a) noexcept;
|