123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 |
- #ifndef BOOST_MATH_NONFINITE_NUM_FACETS_HPP
- #define BOOST_MATH_NONFINITE_NUM_FACETS_HPP
- #include <cstring>
- #include <ios>
- #include <limits>
- #include <locale>
- #include <boost/math/tools/throw_exception.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)
- # pragma warning(disable : 4706)
- #endif
- namespace boost {
- namespace math {
-
- const int legacy = 0x1;
- const int signed_zero = 0x2;
- const int trap_infinity = 0x4;
- const int trap_nan = 0x8;
-
- 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
- {
- static const CharType prefix_plus[2] = { '+', '\0' };
- static const CharType prefix_minus[2] = { '-', '\0' };
- static const CharType body_inf[4] = { 'i', 'n', 'f', '\0' };
- static const CharType body_nan[4] = { 'n', 'a', 'n', '\0' };
- static const CharType* null_string = 0;
- switch((boost::math::fpclassify)(val))
- {
- case FP_INFINITE:
- if(flags_ & trap_infinity)
- {
- BOOST_MATH_THROW_EXCEPTION(std::ios_base::failure("Infinity"));
- }
- else if((boost::math::signbit)(val))
- {
- put_num_and_fill(it, iosb, prefix_minus, body_inf, fill, val);
- }
- else if(iosb.flags() & std::ios_base::showpos)
- {
- put_num_and_fill(it, iosb, prefix_plus, body_inf, fill, val);
- }
- else
- {
- put_num_and_fill(it, iosb, null_string, body_inf, fill, val);
- }
- break;
- case FP_NAN:
- if(flags_ & trap_nan)
- {
- BOOST_MATH_THROW_EXCEPTION(std::ios_base::failure("NaN"));
- }
- else if((boost::math::signbit)(val))
- {
- put_num_and_fill(it, iosb, prefix_minus, body_nan, fill, val);
- }
- else if(iosb.flags() & std::ios_base::showpos)
- {
- put_num_and_fill(it, iosb, prefix_plus, body_nan, fill, val);
- }
- else
- {
- put_num_and_fill(it, iosb, null_string, body_nan, fill, val);
- }
- break;
- case FP_ZERO:
- if((flags_ & signed_zero) && ((boost::math::signbit)(val)))
- {
-
- std::basic_ostringstream<CharType> zeros;
-
- zeros.flags(iosb.flags());
- zeros.unsetf(std::ios::showpos);
- zeros.precision(iosb.precision());
-
- zeros.fill(static_cast<char>(fill));
- zeros << ValType(0);
- put_num_and_fill(it, iosb, prefix_minus, zeros.str().c_str(), fill, val);
- }
- else
- {
- put_num_and_fill(it, iosb, null_string, null_string, fill, val);
- }
- break;
- default:
- it = std::num_put<CharType, OutputIterator>::do_put(it, iosb, fill, val);
- break;
- }
- }
- template<class ValType>
- void put_num_and_fill(
- OutputIterator& it, std::ios_base& iosb, const CharType* prefix,
- const CharType* body, CharType fill, ValType val) const
- {
- int prefix_length = prefix ? (int)std::char_traits<CharType>::length(prefix) : 0;
- int body_length = body ? (int)std::char_traits<CharType>::length(body) : 0;
- int width = prefix_length + body_length;
- 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(body || prefix)
- {
- if(adjust != std::ios_base::internal && adjust != std::ios_base::left)
- put_fill(it, iosb, fill, width);
- }
- if(prefix)
- {
- while(*prefix)
- *it = *(prefix++);
- iosb.width( iosb.width() - prefix_length );
- width -= prefix_length;
- }
- if(body)
- {
- if(adjust == std::ios_base::internal)
- {
- put_fill(it, iosb, fill, width);
- }
- if(iosb.flags() & std::ios_base::uppercase)
- {
- while(*body)
- *it = ct.toupper(*(body++));
- }
- else
- {
- while(*body)
- *it = *(body++);
- }
- if(adjust == std::ios_base::left)
- put_fill(it, iosb, fill, width);
- }
- else
- {
- it = std::num_put<CharType, OutputIterator>::do_put(it, iosb, fill, val);
- }
- }
- 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;
- }
- const int flags_;
- };
-
- 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:
- 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()
- {
-
- return (boost::math::copysign)(
- std::numeric_limits<ValType>::quiet_NaN(), static_cast<ValType>(1)
- );
-
- }
- 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 == '+')
- {
- state |= std::ios_base::failbit;
- return;
- }
- }
- get_unsigned(it, end, iosb, ct, state, val);
- if(negative)
- {
- val = (boost::math::changesign)(val);
- }
- }
- template<class ValType> void get_unsigned
- (
-
- 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:
- 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;
- }
- }
-
- template<class ValType> void get_i
- (
- 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();
- return;
- }
- ++it;
- if(!match_string(it, end, ct, "nity"))
- {
- state |= std::ios_base::failbit;
- return;
- }
- val = std::numeric_limits<ValType>::infinity();
- }
- template<class ValType> void get_n
- (
- 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;
- case '(':
- {
- ++it;
- char c;
- while((c = peek_char(it, end, ct))
- && c != ')' && c != ' ' && c != '\n' && c != '\t')
- ++it;
- if(c != ')')
- {
- state |= std::ios_base::failbit;
- return;
- }
- ++it;
- break;
- }
- default:
- break;
- }
- val = positive_nan<ValType>();
- }
- template<class ValType> void get_q
- (
- 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>();
- }
- template<class ValType> void get_one_hash
- (
- 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':
- get_one_hash_i(it, end, ct, state, val);
- return;
- case 'q':
- case 's':
- if(std::numeric_limits<ValType>::has_quiet_NaN
- && !(flags_ & trap_nan))
- {
- ++it;
- if(match_string(it, end, ct, "nan"))
- {
-
- val = positive_nan<ValType>();
- return;
- }
- }
- break;
- default:
- break;
- }
- state |= std::ios_base::failbit;
- }
- template<class ValType> void get_one_hash_i
- (
- 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':
- if(std::numeric_limits<ValType>::has_infinity
- && !(flags_ & trap_infinity))
- {
- ++it;
- val = std::numeric_limits<ValType>::infinity();
- return;
- }
- break;
- case 'd':
- 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;
- }
-
- char peek_char
- (
- InputIterator& it, InputIterator end,
- const std::ctype<CharType>& ct
- ) const
- {
- if(it == end) return 0;
- return ct.narrow(ct.tolower(*it), 0);
- }
- bool match_string
- (
-
-
- 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;
- }
- const int flags_;
- };
-
- }
- }
- #ifdef _MSC_VER
- # pragma warning(pop)
- #endif
- #endif
|