Added boost header
This commit is contained in:
543
test/external/boost/math/special_functions/nonfinite_num_facets.hpp
vendored
Normal file
543
test/external/boost/math/special_functions/nonfinite_num_facets.hpp
vendored
Normal file
@@ -0,0 +1,543 @@
|
||||
#ifndef BOOST_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
#define BOOST_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
|
||||
// Copyright (c) 2006 Johan Rade
|
||||
// Copyright 2011 Paul A. Bristow (comments)
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
\file
|
||||
|
||||
\brief non_finite_num facets for C99 standard output of infinity and NaN.
|
||||
|
||||
\details See fuller documentation at Boost.Math Facets
|
||||
for Floating-Point Infinities and NaNs.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4127) // conditional expression is constant.
|
||||
# pragma warning(disable : 4706) // assignment within conditional expression.
|
||||
# pragma warning(disable : 4224) // formal parameter 'version' was previously defined as a type.
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace math {
|
||||
|
||||
// flags (enums can be ORed together) -----------------------------------
|
||||
|
||||
const int legacy = 0x1; //!< get facet will recognize most string representations of infinity and NaN.
|
||||
const int signed_zero = 0x2; //!< put facet will distinguish between positive and negative zero.
|
||||
const int trap_infinity = 0x4; /*!< put facet will throw an exception of type std::ios_base::failure
|
||||
when an attempt is made to format positive or negative infinity.
|
||||
get will set the fail bit of the stream when an attempt is made
|
||||
to parse a string that represents positive or negative sign infinity.
|
||||
*/
|
||||
const int trap_nan = 0x8; /*!< put facet will throw an exception of type std::ios_base::failure
|
||||
when an attempt is made to format positive or negative NaN.
|
||||
get will set the fail bit of the stream when an attempt is made
|
||||
to parse a string that represents positive or negative sign infinity.
|
||||
*/
|
||||
|
||||
// class nonfinite_num_put -----------------------------------------------------
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class OutputIterator = std::ostreambuf_iterator<CharType>
|
||||
>
|
||||
class nonfinite_num_put : public std::num_put<CharType, OutputIterator>
|
||||
{
|
||||
public:
|
||||
explicit nonfinite_num_put(int flags = 0) : flags_(flags) {}
|
||||
|
||||
protected:
|
||||
virtual OutputIterator do_put(
|
||||
OutputIterator it, std::ios_base& iosb,
|
||||
CharType fill, double val) const
|
||||
{
|
||||
put_and_reset_width(it, iosb, fill, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual OutputIterator do_put(
|
||||
OutputIterator it, std::ios_base& iosb,
|
||||
CharType fill, long double val) const
|
||||
{
|
||||
put_and_reset_width(it, iosb, fill, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
template<class ValType> void put_and_reset_width(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, ValType val) const
|
||||
{
|
||||
put_impl(it, iosb, fill, val);
|
||||
iosb.width(0);
|
||||
}
|
||||
|
||||
template<class ValType> void put_impl(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, ValType val) const
|
||||
{
|
||||
switch((boost::math::fpclassify)(val)) {
|
||||
|
||||
case FP_INFINITE:
|
||||
if(flags_ & trap_infinity)
|
||||
throw std::ios_base::failure("Infinity");
|
||||
else if((boost::math::signbit)(val))
|
||||
put_num_and_fill(it, iosb, "-", "inf", fill);
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
put_num_and_fill(it, iosb, "+", "inf", fill);
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "inf", fill);
|
||||
break;
|
||||
|
||||
case FP_NAN:
|
||||
if(flags_ & trap_nan)
|
||||
throw std::ios_base::failure("NaN");
|
||||
else if((boost::math::signbit)(val))
|
||||
put_num_and_fill(it, iosb, "-", "nan", fill);
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
put_num_and_fill(it, iosb, "+", "nan", fill);
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "nan", fill);
|
||||
break;
|
||||
|
||||
case FP_ZERO:
|
||||
if(flags_ & signed_zero) {
|
||||
if((boost::math::signbit)(val))
|
||||
put_num_and_fill(it, iosb, "-", "0", fill);
|
||||
else if(iosb.flags() & std::ios_base::showpos)
|
||||
put_num_and_fill(it, iosb, "+", "0", fill);
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "0", fill);
|
||||
}
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "0", fill);
|
||||
break;
|
||||
|
||||
default:
|
||||
it = std::num_put<CharType, OutputIterator>::do_put(
|
||||
it, iosb, fill, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void put_num_and_fill(
|
||||
OutputIterator& it, std::ios_base& iosb, const char* prefix,
|
||||
const char* body, CharType fill) const
|
||||
{
|
||||
int width = (int)std::strlen(prefix) + (int)std::strlen(body);
|
||||
std::ios_base::fmtflags adjust
|
||||
= iosb.flags() & std::ios_base::adjustfield;
|
||||
const std::ctype<CharType>& ct
|
||||
= std::use_facet<std::ctype<CharType> >(iosb.getloc());
|
||||
|
||||
if(adjust != std::ios_base::internal && adjust != std::ios_base::left)
|
||||
put_fill(it, iosb, fill, width);
|
||||
|
||||
while(*prefix)
|
||||
*it = ct.widen(*(prefix++));
|
||||
|
||||
if(adjust == std::ios_base::internal)
|
||||
put_fill(it, iosb, fill, width);
|
||||
|
||||
if(iosb.flags() & std::ios_base::uppercase) {
|
||||
while(*body)
|
||||
*it = ct.toupper(ct.widen(*(body++)));
|
||||
}
|
||||
else {
|
||||
while(*body)
|
||||
*it = ct.widen(*(body++));
|
||||
}
|
||||
|
||||
if(adjust == std::ios_base::left)
|
||||
put_fill(it, iosb, fill, width);
|
||||
}
|
||||
|
||||
void put_fill(
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, int width) const
|
||||
{
|
||||
for(std::streamsize i = iosb.width() - static_cast<std::streamsize>(width); i > 0; --i)
|
||||
*it = fill;
|
||||
}
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
};
|
||||
|
||||
|
||||
// class nonfinite_num_get ------------------------------------------------------
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class InputIterator = std::istreambuf_iterator<CharType>
|
||||
>
|
||||
class nonfinite_num_get : public std::num_get<CharType, InputIterator>
|
||||
{
|
||||
|
||||
public:
|
||||
explicit nonfinite_num_get(int flags = 0) : flags_(flags)
|
||||
{}
|
||||
|
||||
protected: // float, double and long double versions of do_get.
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, float& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, double& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
virtual InputIterator do_get(
|
||||
InputIterator it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, long double& val) const
|
||||
{
|
||||
get_and_check_eof(it, end, iosb, state, val);
|
||||
return it;
|
||||
}
|
||||
|
||||
//..............................................................................
|
||||
|
||||
private:
|
||||
template<class ValType> static ValType positive_nan()
|
||||
{
|
||||
// On some platforms quiet_NaN() may be negative.
|
||||
return (boost::math::copysign)(
|
||||
std::numeric_limits<ValType>::quiet_NaN(), static_cast<ValType>(1)
|
||||
);
|
||||
// static_cast<ValType>(1) added Paul A. Bristow 5 Apr 11
|
||||
}
|
||||
|
||||
template<class ValType> void get_and_check_eof
|
||||
(
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
get_signed(it, end, iosb, state, val);
|
||||
if(it == end)
|
||||
state |= std::ios_base::eofbit;
|
||||
}
|
||||
|
||||
template<class ValType> void get_signed
|
||||
(
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
const std::ctype<CharType>& ct
|
||||
= std::use_facet<std::ctype<CharType> >(iosb.getloc());
|
||||
|
||||
char c = peek_char(it, end, ct);
|
||||
|
||||
bool negative = (c == '-');
|
||||
|
||||
if(negative || c == '+')
|
||||
{
|
||||
++it;
|
||||
c = peek_char(it, end, ct);
|
||||
if(c == '-' || c == '+')
|
||||
{ // Without this check, "++5" etc would be accepted.
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
get_unsigned(it, end, iosb, ct, state, val);
|
||||
|
||||
if(negative)
|
||||
{
|
||||
val = (boost::math::changesign)(val);
|
||||
}
|
||||
} // void get_signed
|
||||
|
||||
template<class ValType> void get_unsigned
|
||||
( //! Get an unsigned floating-point value into val,
|
||||
//! but checking for letters indicating non-finites.
|
||||
InputIterator& it, InputIterator end, std::ios_base& iosb,
|
||||
const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
switch(peek_char(it, end, ct))
|
||||
{
|
||||
case 'i':
|
||||
get_i(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
get_n(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
case 's':
|
||||
get_q(it, end, ct, state, val);
|
||||
break;
|
||||
|
||||
default: // Got a normal floating-point value into val.
|
||||
it = std::num_get<CharType, InputIterator>::do_get(
|
||||
it, end, iosb, state, val);
|
||||
if((flags_ & legacy) && val == static_cast<ValType>(1)
|
||||
&& peek_char(it, end, ct) == '#')
|
||||
get_one_hash(it, end, ct, state, val);
|
||||
break;
|
||||
}
|
||||
} // get_unsigned
|
||||
|
||||
//..........................................................................
|
||||
|
||||
template<class ValType> void get_i
|
||||
( // Get the rest of all strings starting with 'i', expect "inf", "infinity".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_infinity
|
||||
|| (flags_ & trap_infinity))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "nf"))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
if(peek_char(it, end, ct) != 'i')
|
||||
{
|
||||
val = std::numeric_limits<ValType>::infinity(); // "inf"
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "nity"))
|
||||
{ // Expected "infinity"
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
val = std::numeric_limits<ValType>::infinity(); // "infinity"
|
||||
} // void get_i
|
||||
|
||||
template<class ValType> void get_n
|
||||
( // Get expected strings after 'n', "nan", "nanq", "nans", "nan(...)"
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_quiet_NaN
|
||||
|| (flags_ & trap_nan)) {
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "an"))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(peek_char(it, end, ct)) {
|
||||
case 'q':
|
||||
case 's':
|
||||
if(flags_ && legacy)
|
||||
++it;
|
||||
break; // "nanq", "nans"
|
||||
|
||||
case '(': // Optional payload field in (...) follows.
|
||||
{
|
||||
++it;
|
||||
char c;
|
||||
while((c = peek_char(it, end, ct))
|
||||
&& c != ')' && c != ' ' && c != '\n' && c != '\t')
|
||||
++it;
|
||||
if(c != ')')
|
||||
{ // Optional payload field terminator missing!
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
break; // "nan(...)"
|
||||
}
|
||||
|
||||
default:
|
||||
break; // "nan"
|
||||
}
|
||||
|
||||
val = positive_nan<ValType>();
|
||||
} // void get_n
|
||||
|
||||
template<class ValType> void get_q
|
||||
( // Get expected rest of string starting with 'q': "qnan".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
if(!std::numeric_limits<ValType>::has_quiet_NaN
|
||||
|| (flags_ & trap_nan) || !(flags_ & legacy))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
if(!match_string(it, end, ct, "nan"))
|
||||
{
|
||||
state |= std::ios_base::failbit;
|
||||
return;
|
||||
}
|
||||
|
||||
val = positive_nan<ValType>(); // "QNAN"
|
||||
} // void get_q
|
||||
|
||||
template<class ValType> void get_one_hash
|
||||
( // Get expected string after having read "1.#": "1.#IND", "1.#QNAN", "1.#SNAN".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
|
||||
++it;
|
||||
switch(peek_char(it, end, ct))
|
||||
{
|
||||
case 'i': // from IND (indeterminate), considered same a QNAN.
|
||||
get_one_hash_i(it, end, ct, state, val); // "1.#IND"
|
||||
return;
|
||||
|
||||
case 'q': // from QNAN
|
||||
case 's': // from SNAN - treated the same as QNAN.
|
||||
if(std::numeric_limits<ValType>::has_quiet_NaN
|
||||
&& !(flags_ & trap_nan))
|
||||
{
|
||||
++it;
|
||||
if(match_string(it, end, ct, "nan"))
|
||||
{ // "1.#QNAN", "1.#SNAN"
|
||||
// ++it; // removed as caused assert() cannot increment iterator).
|
||||
// (match_string consumes string, so not needed?).
|
||||
// https://svn.boost.org/trac/boost/ticket/5467
|
||||
// Change in nonfinite_num_facet.hpp Paul A. Bristow 11 Apr 11 makes legacy_test.cpp work OK.
|
||||
val = positive_nan<ValType>(); // "1.#QNAN"
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
state |= std::ios_base::failbit;
|
||||
} // void get_one_hash
|
||||
|
||||
template<class ValType> void get_one_hash_i
|
||||
( // Get expected strings after 'i', "1.#INF", 1.#IND".
|
||||
InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
|
||||
std::ios_base::iostate& state, ValType& val
|
||||
) const
|
||||
{
|
||||
++it;
|
||||
|
||||
if(peek_char(it, end, ct) == 'n')
|
||||
{
|
||||
++it;
|
||||
switch(peek_char(it, end, ct))
|
||||
{
|
||||
case 'f': // "1.#INF"
|
||||
if(std::numeric_limits<ValType>::has_infinity
|
||||
&& !(flags_ & trap_infinity))
|
||||
{
|
||||
++it;
|
||||
val = std::numeric_limits<ValType>::infinity();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': // 1.#IND"
|
||||
if(std::numeric_limits<ValType>::has_quiet_NaN
|
||||
&& !(flags_ & trap_nan))
|
||||
{
|
||||
++it;
|
||||
val = positive_nan<ValType>();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state |= std::ios_base::failbit;
|
||||
} // void get_one_hash_i
|
||||
|
||||
//..........................................................................
|
||||
|
||||
char peek_char
|
||||
( //! \return next char in the input buffer, ensuring lowercase (but do not 'consume' char).
|
||||
InputIterator& it, InputIterator end,
|
||||
const std::ctype<CharType>& ct
|
||||
) const
|
||||
{
|
||||
if(it == end) return 0;
|
||||
return ct.narrow(ct.tolower(*it), 0); // Always tolower to ensure case insensitive.
|
||||
}
|
||||
|
||||
bool match_string
|
||||
( //! Match remaining chars to expected string (case insensitive),
|
||||
//! consuming chars that match OK.
|
||||
//! \return true if matched expected string, else false.
|
||||
InputIterator& it, InputIterator end,
|
||||
const std::ctype<CharType>& ct,
|
||||
const char* s
|
||||
) const
|
||||
{
|
||||
while(it != end && *s && *s == ct.narrow(ct.tolower(*it), 0))
|
||||
{
|
||||
++s;
|
||||
++it; //
|
||||
}
|
||||
return !*s;
|
||||
} // bool match_string
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
}; //
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user