summaryrefslogtreecommitdiff
path: root/boost/math/special_functions/nonfinite_num_facets.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/math/special_functions/nonfinite_num_facets.hpp')
-rw-r--r--boost/math/special_functions/nonfinite_num_facets.hpp153
1 files changed, 101 insertions, 52 deletions
diff --git a/boost/math/special_functions/nonfinite_num_facets.hpp b/boost/math/special_functions/nonfinite_num_facets.hpp
index 9fa61481b5..84d3f1070a 100644
--- a/boost/math/special_functions/nonfinite_num_facets.hpp
+++ b/boost/math/special_functions/nonfinite_num_facets.hpp
@@ -1,8 +1,9 @@
#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)
+// Copyright 2006 Johan Rade
+// Copyright 2012 K R Walker
+// Copyright 2011, 2012 Paul A. Bristow
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
@@ -28,10 +29,9 @@
#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.
+# pragma warning(push)
+# pragma warning(disable : 4127) // conditional expression is constant.
+# pragma warning(disable : 4706) // assignment within conditional expression.
#endif
namespace boost {
@@ -65,16 +65,14 @@ namespace boost {
protected:
virtual OutputIterator do_put(
- OutputIterator it, std::ios_base& iosb,
- CharType fill, double val) const
+ 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
+ OutputIterator it, std::ios_base& iosb, CharType fill, long double val) const
{
put_and_reset_width(it, iosb, fill, val);
return it;
@@ -93,86 +91,136 @@ namespace boost {
OutputIterator& it, std::ios_base& iosb,
CharType fill, ValType val) const
{
- switch((boost::math::fpclassify)(val)) {
+ 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)
+ {
throw std::ios_base::failure("Infinity");
+ }
else if((boost::math::signbit)(val))
- put_num_and_fill(it, iosb, "-", "inf", fill);
+ { // negative infinity.
+ 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, "+", "inf", fill);
+ { // Explicit "+inf" wanted.
+ put_num_and_fill(it, iosb, prefix_plus, body_inf, fill, val);
+ }
else
- put_num_and_fill(it, iosb, "", "inf", fill);
+ { // just "inf" wanted.
+ put_num_and_fill(it, iosb, null_string, body_inf, fill, val);
+ }
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);
+ { // negative so "-nan".
+ 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, "+", "nan", fill);
+ { // explicit "+nan" wanted.
+ put_num_and_fill(it, iosb, prefix_plus, body_nan, fill, val);
+ }
else
- put_num_and_fill(it, iosb, "", "nan", fill);
+ { // Just "nan".
+ put_num_and_fill(it, iosb, null_string, body_nan, fill, val);
+ }
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);
+ if((flags_ & signed_zero) && ((boost::math::signbit)(val)))
+ { // Flag set to distinguish between positive and negative zero.
+ // But string "0" should have stuff after decimal point if setprecision and/or exp format.
+
+ std::basic_ostringstream<CharType> zeros; // Needs to be CharType version.
+
+ // Copy flags, fill, width and precision.
+ zeros.flags(iosb.flags());
+ zeros.unsetf(std::ios::showpos); // Ignore showpos because must be negative.
+ zeros.precision(iosb.precision());
+ //zeros.width is set by put_num_and_fill
+ 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, "", "0", fill);
+ { // Output the platform default for positive and negative zero.
+ 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);
+ default: // Normal non-zero finite value.
+ 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 char* prefix,
- const char* body, CharType fill) const
+ OutputIterator& it, std::ios_base& iosb, const CharType* prefix,
+ const CharType* body, CharType fill, ValType val) const
{
- int width = (int)std::strlen(prefix) + (int)std::strlen(body);
- std::ios_base::fmtflags adjust
- = iosb.flags() & std::ios_base::adjustfield;
+ 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(adjust != std::ios_base::internal && adjust != std::ios_base::left)
- put_fill(it, iosb, fill, width);
+ if(body || prefix)
+ { // adjust == std::ios_base::right, so leading fill needed.
+ if(adjust != std::ios_base::internal && adjust != std::ios_base::left)
+ put_fill(it, iosb, fill, width);
+ }
- while(*prefix)
- *it = ct.widen(*(prefix++));
+ if(prefix)
+ { // Adjust width for prefix.
+ while(*prefix)
+ *it = *(prefix++);
+ iosb.width( iosb.width() - prefix_length );
+ width -= prefix_length;
+ }
- if(adjust == std::ios_base::internal)
- put_fill(it, iosb, fill, width);
+ if(body)
+ { //
+ if(adjust == std::ios_base::internal)
+ { // Put fill between sign and digits.
+ 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(iosb.flags() & std::ios_base::uppercase) {
- while(*body)
- *it = ct.toupper(ct.widen(*(body++)));
+ if(adjust == std::ios_base::left)
+ put_fill(it, iosb, fill, width);
}
- else {
- while(*body)
- *it = ct.widen(*(body++));
+ else
+ {
+ it = std::num_put<CharType, OutputIterator>::do_put(it, iosb, fill, val);
}
-
- 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
- {
+ OutputIterator& it, std::ios_base& iosb, CharType fill, int width) const
+ { // Insert fill chars.
for(std::streamsize i = iosb.width() - static_cast<std::streamsize>(width); i > 0; --i)
*it = fill;
}
@@ -540,4 +588,5 @@ namespace boost {
# pragma warning(pop)
#endif
-#endif
+#endif // BOOST_MATH_NONFINITE_NUM_FACETS_HPP
+