annotate DEPENDENCIES/generic/include/boost/math/special_functions/nonfinite_num_facets.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 #ifndef BOOST_MATH_NONFINITE_NUM_FACETS_HPP
Chris@16 2 #define BOOST_MATH_NONFINITE_NUM_FACETS_HPP
Chris@16 3
Chris@16 4 // Copyright 2006 Johan Rade
Chris@16 5 // Copyright 2012 K R Walker
Chris@16 6 // Copyright 2011, 2012 Paul A. Bristow
Chris@16 7
Chris@16 8 // Distributed under the Boost Software License, Version 1.0.
Chris@16 9 // (See accompanying file LICENSE_1_0.txt
Chris@16 10 // or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 11
Chris@16 12 /*
Chris@16 13 \file
Chris@16 14
Chris@16 15 \brief non_finite_num facets for C99 standard output of infinity and NaN.
Chris@16 16
Chris@16 17 \details See fuller documentation at Boost.Math Facets
Chris@16 18 for Floating-Point Infinities and NaNs.
Chris@16 19 */
Chris@16 20
Chris@16 21 #include <cstring>
Chris@16 22 #include <ios>
Chris@16 23 #include <limits>
Chris@16 24 #include <locale>
Chris@16 25
Chris@16 26 #include <boost/version.hpp>
Chris@16 27
Chris@16 28 #include <boost/math/special_functions/fpclassify.hpp>
Chris@16 29 #include <boost/math/special_functions/sign.hpp>
Chris@16 30
Chris@16 31 #ifdef _MSC_VER
Chris@16 32 # pragma warning(push)
Chris@16 33 # pragma warning(disable : 4127) // conditional expression is constant.
Chris@16 34 # pragma warning(disable : 4706) // assignment within conditional expression.
Chris@16 35 #endif
Chris@16 36
Chris@16 37 namespace boost {
Chris@16 38 namespace math {
Chris@16 39
Chris@16 40 // flags (enums can be ORed together) -----------------------------------
Chris@16 41
Chris@16 42 const int legacy = 0x1; //!< get facet will recognize most string representations of infinity and NaN.
Chris@16 43 const int signed_zero = 0x2; //!< put facet will distinguish between positive and negative zero.
Chris@16 44 const int trap_infinity = 0x4; /*!< put facet will throw an exception of type std::ios_base::failure
Chris@16 45 when an attempt is made to format positive or negative infinity.
Chris@16 46 get will set the fail bit of the stream when an attempt is made
Chris@16 47 to parse a string that represents positive or negative sign infinity.
Chris@16 48 */
Chris@16 49 const int trap_nan = 0x8; /*!< put facet will throw an exception of type std::ios_base::failure
Chris@16 50 when an attempt is made to format positive or negative NaN.
Chris@16 51 get will set the fail bit of the stream when an attempt is made
Chris@16 52 to parse a string that represents positive or negative sign infinity.
Chris@16 53 */
Chris@16 54
Chris@16 55 // class nonfinite_num_put -----------------------------------------------------
Chris@16 56
Chris@16 57 template<
Chris@16 58 class CharType,
Chris@16 59 class OutputIterator = std::ostreambuf_iterator<CharType>
Chris@16 60 >
Chris@16 61 class nonfinite_num_put : public std::num_put<CharType, OutputIterator>
Chris@16 62 {
Chris@16 63 public:
Chris@16 64 explicit nonfinite_num_put(int flags = 0) : flags_(flags) {}
Chris@16 65
Chris@16 66 protected:
Chris@16 67 virtual OutputIterator do_put(
Chris@16 68 OutputIterator it, std::ios_base& iosb, CharType fill, double val) const
Chris@16 69 {
Chris@16 70 put_and_reset_width(it, iosb, fill, val);
Chris@16 71 return it;
Chris@16 72 }
Chris@16 73
Chris@16 74 virtual OutputIterator do_put(
Chris@16 75 OutputIterator it, std::ios_base& iosb, CharType fill, long double val) const
Chris@16 76 {
Chris@16 77 put_and_reset_width(it, iosb, fill, val);
Chris@16 78 return it;
Chris@16 79 }
Chris@16 80
Chris@16 81 private:
Chris@16 82 template<class ValType> void put_and_reset_width(
Chris@16 83 OutputIterator& it, std::ios_base& iosb,
Chris@16 84 CharType fill, ValType val) const
Chris@16 85 {
Chris@16 86 put_impl(it, iosb, fill, val);
Chris@16 87 iosb.width(0);
Chris@16 88 }
Chris@16 89
Chris@16 90 template<class ValType> void put_impl(
Chris@16 91 OutputIterator& it, std::ios_base& iosb,
Chris@16 92 CharType fill, ValType val) const
Chris@16 93 {
Chris@16 94 static const CharType prefix_plus[2] = { '+', '\0' };
Chris@16 95 static const CharType prefix_minus[2] = { '-', '\0' };
Chris@16 96 static const CharType body_inf[4] = { 'i', 'n', 'f', '\0' };
Chris@16 97 static const CharType body_nan[4] = { 'n', 'a', 'n', '\0' };
Chris@16 98 static const CharType* null_string = 0;
Chris@16 99
Chris@16 100 switch((boost::math::fpclassify)(val))
Chris@16 101 {
Chris@16 102
Chris@16 103 case FP_INFINITE:
Chris@16 104 if(flags_ & trap_infinity)
Chris@16 105 {
Chris@16 106 throw std::ios_base::failure("Infinity");
Chris@16 107 }
Chris@16 108 else if((boost::math::signbit)(val))
Chris@16 109 { // negative infinity.
Chris@16 110 put_num_and_fill(it, iosb, prefix_minus, body_inf, fill, val);
Chris@16 111 }
Chris@16 112 else if(iosb.flags() & std::ios_base::showpos)
Chris@16 113 { // Explicit "+inf" wanted.
Chris@16 114 put_num_and_fill(it, iosb, prefix_plus, body_inf, fill, val);
Chris@16 115 }
Chris@16 116 else
Chris@16 117 { // just "inf" wanted.
Chris@16 118 put_num_and_fill(it, iosb, null_string, body_inf, fill, val);
Chris@16 119 }
Chris@16 120 break;
Chris@16 121
Chris@16 122 case FP_NAN:
Chris@16 123 if(flags_ & trap_nan)
Chris@16 124 {
Chris@16 125 throw std::ios_base::failure("NaN");
Chris@16 126 }
Chris@16 127 else if((boost::math::signbit)(val))
Chris@16 128 { // negative so "-nan".
Chris@16 129 put_num_and_fill(it, iosb, prefix_minus, body_nan, fill, val);
Chris@16 130 }
Chris@16 131 else if(iosb.flags() & std::ios_base::showpos)
Chris@16 132 { // explicit "+nan" wanted.
Chris@16 133 put_num_and_fill(it, iosb, prefix_plus, body_nan, fill, val);
Chris@16 134 }
Chris@16 135 else
Chris@16 136 { // Just "nan".
Chris@16 137 put_num_and_fill(it, iosb, null_string, body_nan, fill, val);
Chris@16 138 }
Chris@16 139 break;
Chris@16 140
Chris@16 141 case FP_ZERO:
Chris@16 142 if((flags_ & signed_zero) && ((boost::math::signbit)(val)))
Chris@16 143 { // Flag set to distinguish between positive and negative zero.
Chris@16 144 // But string "0" should have stuff after decimal point if setprecision and/or exp format.
Chris@16 145
Chris@16 146 std::basic_ostringstream<CharType> zeros; // Needs to be CharType version.
Chris@16 147
Chris@16 148 // Copy flags, fill, width and precision.
Chris@16 149 zeros.flags(iosb.flags());
Chris@16 150 zeros.unsetf(std::ios::showpos); // Ignore showpos because must be negative.
Chris@16 151 zeros.precision(iosb.precision());
Chris@16 152 //zeros.width is set by put_num_and_fill
Chris@16 153 zeros.fill(static_cast<char>(fill));
Chris@16 154 zeros << ValType(0);
Chris@16 155 put_num_and_fill(it, iosb, prefix_minus, zeros.str().c_str(), fill, val);
Chris@16 156 }
Chris@16 157 else
Chris@16 158 { // Output the platform default for positive and negative zero.
Chris@16 159 put_num_and_fill(it, iosb, null_string, null_string, fill, val);
Chris@16 160 }
Chris@16 161 break;
Chris@16 162
Chris@16 163 default: // Normal non-zero finite value.
Chris@16 164 it = std::num_put<CharType, OutputIterator>::do_put(it, iosb, fill, val);
Chris@16 165 break;
Chris@16 166 }
Chris@16 167 }
Chris@16 168
Chris@16 169 template<class ValType>
Chris@16 170 void put_num_and_fill(
Chris@16 171 OutputIterator& it, std::ios_base& iosb, const CharType* prefix,
Chris@16 172 const CharType* body, CharType fill, ValType val) const
Chris@16 173 {
Chris@16 174 int prefix_length = prefix ? (int)std::char_traits<CharType>::length(prefix) : 0;
Chris@16 175 int body_length = body ? (int)std::char_traits<CharType>::length(body) : 0;
Chris@16 176 int width = prefix_length + body_length;
Chris@16 177 std::ios_base::fmtflags adjust = iosb.flags() & std::ios_base::adjustfield;
Chris@16 178 const std::ctype<CharType>& ct
Chris@16 179 = std::use_facet<std::ctype<CharType> >(iosb.getloc());
Chris@16 180
Chris@16 181 if(body || prefix)
Chris@16 182 { // adjust == std::ios_base::right, so leading fill needed.
Chris@16 183 if(adjust != std::ios_base::internal && adjust != std::ios_base::left)
Chris@16 184 put_fill(it, iosb, fill, width);
Chris@16 185 }
Chris@16 186
Chris@16 187 if(prefix)
Chris@16 188 { // Adjust width for prefix.
Chris@16 189 while(*prefix)
Chris@16 190 *it = *(prefix++);
Chris@16 191 iosb.width( iosb.width() - prefix_length );
Chris@16 192 width -= prefix_length;
Chris@16 193 }
Chris@16 194
Chris@16 195 if(body)
Chris@16 196 { //
Chris@16 197 if(adjust == std::ios_base::internal)
Chris@16 198 { // Put fill between sign and digits.
Chris@16 199 put_fill(it, iosb, fill, width);
Chris@16 200 }
Chris@16 201 if(iosb.flags() & std::ios_base::uppercase)
Chris@16 202 {
Chris@16 203 while(*body)
Chris@16 204 *it = ct.toupper(*(body++));
Chris@16 205 }
Chris@16 206 else
Chris@16 207 {
Chris@16 208 while(*body)
Chris@16 209 *it = *(body++);
Chris@16 210 }
Chris@16 211
Chris@16 212 if(adjust == std::ios_base::left)
Chris@16 213 put_fill(it, iosb, fill, width);
Chris@16 214 }
Chris@16 215 else
Chris@16 216 {
Chris@16 217 it = std::num_put<CharType, OutputIterator>::do_put(it, iosb, fill, val);
Chris@16 218 }
Chris@16 219 }
Chris@16 220
Chris@16 221 void put_fill(
Chris@16 222 OutputIterator& it, std::ios_base& iosb, CharType fill, int width) const
Chris@16 223 { // Insert fill chars.
Chris@16 224 for(std::streamsize i = iosb.width() - static_cast<std::streamsize>(width); i > 0; --i)
Chris@16 225 *it = fill;
Chris@16 226 }
Chris@16 227
Chris@16 228 private:
Chris@16 229 const int flags_;
Chris@16 230 };
Chris@16 231
Chris@16 232
Chris@16 233 // class nonfinite_num_get ------------------------------------------------------
Chris@16 234
Chris@16 235 template<
Chris@16 236 class CharType,
Chris@16 237 class InputIterator = std::istreambuf_iterator<CharType>
Chris@16 238 >
Chris@16 239 class nonfinite_num_get : public std::num_get<CharType, InputIterator>
Chris@16 240 {
Chris@16 241
Chris@16 242 public:
Chris@16 243 explicit nonfinite_num_get(int flags = 0) : flags_(flags)
Chris@16 244 {}
Chris@16 245
Chris@16 246 protected: // float, double and long double versions of do_get.
Chris@16 247 virtual InputIterator do_get(
Chris@16 248 InputIterator it, InputIterator end, std::ios_base& iosb,
Chris@16 249 std::ios_base::iostate& state, float& val) const
Chris@16 250 {
Chris@16 251 get_and_check_eof(it, end, iosb, state, val);
Chris@16 252 return it;
Chris@16 253 }
Chris@16 254
Chris@16 255 virtual InputIterator do_get(
Chris@16 256 InputIterator it, InputIterator end, std::ios_base& iosb,
Chris@16 257 std::ios_base::iostate& state, double& val) const
Chris@16 258 {
Chris@16 259 get_and_check_eof(it, end, iosb, state, val);
Chris@16 260 return it;
Chris@16 261 }
Chris@16 262
Chris@16 263 virtual InputIterator do_get(
Chris@16 264 InputIterator it, InputIterator end, std::ios_base& iosb,
Chris@16 265 std::ios_base::iostate& state, long double& val) const
Chris@16 266 {
Chris@16 267 get_and_check_eof(it, end, iosb, state, val);
Chris@16 268 return it;
Chris@16 269 }
Chris@16 270
Chris@16 271 //..............................................................................
Chris@16 272
Chris@16 273 private:
Chris@16 274 template<class ValType> static ValType positive_nan()
Chris@16 275 {
Chris@16 276 // On some platforms quiet_NaN() may be negative.
Chris@16 277 return (boost::math::copysign)(
Chris@16 278 std::numeric_limits<ValType>::quiet_NaN(), static_cast<ValType>(1)
Chris@16 279 );
Chris@16 280 // static_cast<ValType>(1) added Paul A. Bristow 5 Apr 11
Chris@16 281 }
Chris@16 282
Chris@16 283 template<class ValType> void get_and_check_eof
Chris@16 284 (
Chris@16 285 InputIterator& it, InputIterator end, std::ios_base& iosb,
Chris@16 286 std::ios_base::iostate& state, ValType& val
Chris@16 287 ) const
Chris@16 288 {
Chris@16 289 get_signed(it, end, iosb, state, val);
Chris@16 290 if(it == end)
Chris@16 291 state |= std::ios_base::eofbit;
Chris@16 292 }
Chris@16 293
Chris@16 294 template<class ValType> void get_signed
Chris@16 295 (
Chris@16 296 InputIterator& it, InputIterator end, std::ios_base& iosb,
Chris@16 297 std::ios_base::iostate& state, ValType& val
Chris@16 298 ) const
Chris@16 299 {
Chris@16 300 const std::ctype<CharType>& ct
Chris@16 301 = std::use_facet<std::ctype<CharType> >(iosb.getloc());
Chris@16 302
Chris@16 303 char c = peek_char(it, end, ct);
Chris@16 304
Chris@16 305 bool negative = (c == '-');
Chris@16 306
Chris@16 307 if(negative || c == '+')
Chris@16 308 {
Chris@16 309 ++it;
Chris@16 310 c = peek_char(it, end, ct);
Chris@16 311 if(c == '-' || c == '+')
Chris@16 312 { // Without this check, "++5" etc would be accepted.
Chris@16 313 state |= std::ios_base::failbit;
Chris@16 314 return;
Chris@16 315 }
Chris@16 316 }
Chris@16 317
Chris@16 318 get_unsigned(it, end, iosb, ct, state, val);
Chris@16 319
Chris@16 320 if(negative)
Chris@16 321 {
Chris@16 322 val = (boost::math::changesign)(val);
Chris@16 323 }
Chris@16 324 } // void get_signed
Chris@16 325
Chris@16 326 template<class ValType> void get_unsigned
Chris@16 327 ( //! Get an unsigned floating-point value into val,
Chris@16 328 //! but checking for letters indicating non-finites.
Chris@16 329 InputIterator& it, InputIterator end, std::ios_base& iosb,
Chris@16 330 const std::ctype<CharType>& ct,
Chris@16 331 std::ios_base::iostate& state, ValType& val
Chris@16 332 ) const
Chris@16 333 {
Chris@16 334 switch(peek_char(it, end, ct))
Chris@16 335 {
Chris@16 336 case 'i':
Chris@16 337 get_i(it, end, ct, state, val);
Chris@16 338 break;
Chris@16 339
Chris@16 340 case 'n':
Chris@16 341 get_n(it, end, ct, state, val);
Chris@16 342 break;
Chris@16 343
Chris@16 344 case 'q':
Chris@16 345 case 's':
Chris@16 346 get_q(it, end, ct, state, val);
Chris@16 347 break;
Chris@16 348
Chris@16 349 default: // Got a normal floating-point value into val.
Chris@16 350 it = std::num_get<CharType, InputIterator>::do_get(
Chris@16 351 it, end, iosb, state, val);
Chris@16 352 if((flags_ & legacy) && val == static_cast<ValType>(1)
Chris@16 353 && peek_char(it, end, ct) == '#')
Chris@16 354 get_one_hash(it, end, ct, state, val);
Chris@16 355 break;
Chris@16 356 }
Chris@16 357 } // get_unsigned
Chris@16 358
Chris@16 359 //..........................................................................
Chris@16 360
Chris@16 361 template<class ValType> void get_i
Chris@16 362 ( // Get the rest of all strings starting with 'i', expect "inf", "infinity".
Chris@16 363 InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
Chris@16 364 std::ios_base::iostate& state, ValType& val
Chris@16 365 ) const
Chris@16 366 {
Chris@16 367 if(!std::numeric_limits<ValType>::has_infinity
Chris@16 368 || (flags_ & trap_infinity))
Chris@16 369 {
Chris@16 370 state |= std::ios_base::failbit;
Chris@16 371 return;
Chris@16 372 }
Chris@16 373
Chris@16 374 ++it;
Chris@16 375 if(!match_string(it, end, ct, "nf"))
Chris@16 376 {
Chris@16 377 state |= std::ios_base::failbit;
Chris@16 378 return;
Chris@16 379 }
Chris@16 380
Chris@16 381 if(peek_char(it, end, ct) != 'i')
Chris@16 382 {
Chris@16 383 val = std::numeric_limits<ValType>::infinity(); // "inf"
Chris@16 384 return;
Chris@16 385 }
Chris@16 386
Chris@16 387 ++it;
Chris@16 388 if(!match_string(it, end, ct, "nity"))
Chris@16 389 { // Expected "infinity"
Chris@16 390 state |= std::ios_base::failbit;
Chris@16 391 return;
Chris@16 392 }
Chris@16 393
Chris@16 394 val = std::numeric_limits<ValType>::infinity(); // "infinity"
Chris@16 395 } // void get_i
Chris@16 396
Chris@16 397 template<class ValType> void get_n
Chris@16 398 ( // Get expected strings after 'n', "nan", "nanq", "nans", "nan(...)"
Chris@16 399 InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
Chris@16 400 std::ios_base::iostate& state, ValType& val
Chris@16 401 ) const
Chris@16 402 {
Chris@16 403 if(!std::numeric_limits<ValType>::has_quiet_NaN
Chris@16 404 || (flags_ & trap_nan)) {
Chris@16 405 state |= std::ios_base::failbit;
Chris@16 406 return;
Chris@16 407 }
Chris@16 408
Chris@16 409 ++it;
Chris@16 410 if(!match_string(it, end, ct, "an"))
Chris@16 411 {
Chris@16 412 state |= std::ios_base::failbit;
Chris@16 413 return;
Chris@16 414 }
Chris@16 415
Chris@16 416 switch(peek_char(it, end, ct)) {
Chris@16 417 case 'q':
Chris@16 418 case 's':
Chris@16 419 if(flags_ && legacy)
Chris@16 420 ++it;
Chris@16 421 break; // "nanq", "nans"
Chris@16 422
Chris@16 423 case '(': // Optional payload field in (...) follows.
Chris@16 424 {
Chris@16 425 ++it;
Chris@16 426 char c;
Chris@16 427 while((c = peek_char(it, end, ct))
Chris@16 428 && c != ')' && c != ' ' && c != '\n' && c != '\t')
Chris@16 429 ++it;
Chris@16 430 if(c != ')')
Chris@16 431 { // Optional payload field terminator missing!
Chris@16 432 state |= std::ios_base::failbit;
Chris@16 433 return;
Chris@16 434 }
Chris@16 435 ++it;
Chris@16 436 break; // "nan(...)"
Chris@16 437 }
Chris@16 438
Chris@16 439 default:
Chris@16 440 break; // "nan"
Chris@16 441 }
Chris@16 442
Chris@16 443 val = positive_nan<ValType>();
Chris@16 444 } // void get_n
Chris@16 445
Chris@16 446 template<class ValType> void get_q
Chris@16 447 ( // Get expected rest of string starting with 'q': "qnan".
Chris@16 448 InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
Chris@16 449 std::ios_base::iostate& state, ValType& val
Chris@16 450 ) const
Chris@16 451 {
Chris@16 452 if(!std::numeric_limits<ValType>::has_quiet_NaN
Chris@16 453 || (flags_ & trap_nan) || !(flags_ & legacy))
Chris@16 454 {
Chris@16 455 state |= std::ios_base::failbit;
Chris@16 456 return;
Chris@16 457 }
Chris@16 458
Chris@16 459 ++it;
Chris@16 460 if(!match_string(it, end, ct, "nan"))
Chris@16 461 {
Chris@16 462 state |= std::ios_base::failbit;
Chris@16 463 return;
Chris@16 464 }
Chris@16 465
Chris@16 466 val = positive_nan<ValType>(); // "QNAN"
Chris@16 467 } // void get_q
Chris@16 468
Chris@16 469 template<class ValType> void get_one_hash
Chris@16 470 ( // Get expected string after having read "1.#": "1.#IND", "1.#QNAN", "1.#SNAN".
Chris@16 471 InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
Chris@16 472 std::ios_base::iostate& state, ValType& val
Chris@16 473 ) const
Chris@16 474 {
Chris@16 475
Chris@16 476 ++it;
Chris@16 477 switch(peek_char(it, end, ct))
Chris@16 478 {
Chris@16 479 case 'i': // from IND (indeterminate), considered same a QNAN.
Chris@16 480 get_one_hash_i(it, end, ct, state, val); // "1.#IND"
Chris@16 481 return;
Chris@16 482
Chris@16 483 case 'q': // from QNAN
Chris@16 484 case 's': // from SNAN - treated the same as QNAN.
Chris@16 485 if(std::numeric_limits<ValType>::has_quiet_NaN
Chris@16 486 && !(flags_ & trap_nan))
Chris@16 487 {
Chris@16 488 ++it;
Chris@16 489 if(match_string(it, end, ct, "nan"))
Chris@16 490 { // "1.#QNAN", "1.#SNAN"
Chris@16 491 // ++it; // removed as caused assert() cannot increment iterator).
Chris@16 492 // (match_string consumes string, so not needed?).
Chris@16 493 // https://svn.boost.org/trac/boost/ticket/5467
Chris@16 494 // Change in nonfinite_num_facet.hpp Paul A. Bristow 11 Apr 11 makes legacy_test.cpp work OK.
Chris@16 495 val = positive_nan<ValType>(); // "1.#QNAN"
Chris@16 496 return;
Chris@16 497 }
Chris@16 498 }
Chris@16 499 break;
Chris@16 500
Chris@16 501 default:
Chris@16 502 break;
Chris@16 503 }
Chris@16 504
Chris@16 505 state |= std::ios_base::failbit;
Chris@16 506 } // void get_one_hash
Chris@16 507
Chris@16 508 template<class ValType> void get_one_hash_i
Chris@16 509 ( // Get expected strings after 'i', "1.#INF", 1.#IND".
Chris@16 510 InputIterator& it, InputIterator end, const std::ctype<CharType>& ct,
Chris@16 511 std::ios_base::iostate& state, ValType& val
Chris@16 512 ) const
Chris@16 513 {
Chris@16 514 ++it;
Chris@16 515
Chris@16 516 if(peek_char(it, end, ct) == 'n')
Chris@16 517 {
Chris@16 518 ++it;
Chris@16 519 switch(peek_char(it, end, ct))
Chris@16 520 {
Chris@16 521 case 'f': // "1.#INF"
Chris@16 522 if(std::numeric_limits<ValType>::has_infinity
Chris@16 523 && !(flags_ & trap_infinity))
Chris@16 524 {
Chris@16 525 ++it;
Chris@16 526 val = std::numeric_limits<ValType>::infinity();
Chris@16 527 return;
Chris@16 528 }
Chris@16 529 break;
Chris@16 530
Chris@16 531 case 'd': // 1.#IND"
Chris@16 532 if(std::numeric_limits<ValType>::has_quiet_NaN
Chris@16 533 && !(flags_ & trap_nan))
Chris@16 534 {
Chris@16 535 ++it;
Chris@16 536 val = positive_nan<ValType>();
Chris@16 537 return;
Chris@16 538 }
Chris@16 539 break;
Chris@16 540
Chris@16 541 default:
Chris@16 542 break;
Chris@16 543 }
Chris@16 544 }
Chris@16 545
Chris@16 546 state |= std::ios_base::failbit;
Chris@16 547 } // void get_one_hash_i
Chris@16 548
Chris@16 549 //..........................................................................
Chris@16 550
Chris@16 551 char peek_char
Chris@16 552 ( //! \return next char in the input buffer, ensuring lowercase (but do not 'consume' char).
Chris@16 553 InputIterator& it, InputIterator end,
Chris@16 554 const std::ctype<CharType>& ct
Chris@16 555 ) const
Chris@16 556 {
Chris@16 557 if(it == end) return 0;
Chris@16 558 return ct.narrow(ct.tolower(*it), 0); // Always tolower to ensure case insensitive.
Chris@16 559 }
Chris@16 560
Chris@16 561 bool match_string
Chris@16 562 ( //! Match remaining chars to expected string (case insensitive),
Chris@16 563 //! consuming chars that match OK.
Chris@16 564 //! \return true if matched expected string, else false.
Chris@16 565 InputIterator& it, InputIterator end,
Chris@16 566 const std::ctype<CharType>& ct,
Chris@16 567 const char* s
Chris@16 568 ) const
Chris@16 569 {
Chris@16 570 while(it != end && *s && *s == ct.narrow(ct.tolower(*it), 0))
Chris@16 571 {
Chris@16 572 ++s;
Chris@16 573 ++it; //
Chris@16 574 }
Chris@16 575 return !*s;
Chris@16 576 } // bool match_string
Chris@16 577
Chris@16 578 private:
Chris@16 579 const int flags_;
Chris@16 580 }; //
Chris@16 581
Chris@16 582 //------------------------------------------------------------------------------
Chris@16 583
Chris@16 584 } // namespace math
Chris@16 585 } // namespace boost
Chris@16 586
Chris@16 587 #ifdef _MSC_VER
Chris@16 588 # pragma warning(pop)
Chris@16 589 #endif
Chris@16 590
Chris@16 591 #endif // BOOST_MATH_NONFINITE_NUM_FACETS_HPP
Chris@16 592