mirror of
https://github.com/boostorg/math.git
synced 2026-01-28 07:22:12 +00:00
Version that passes new tests for both default and signed_zero flag set based on modifications by KR Walker.
BUT had to suppress MSVC warning "C4244 conversion wchar_t* to char* may cause data loss." [SVN r77268]
This commit is contained in:
@@ -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,10 @@
|
||||
#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.
|
||||
# pragma warning(disable : 4244) // TODO? // Needs to be CharType version.
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
@@ -65,16 +66,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 +92,138 @@ namespace boost {
|
||||
OutputIterator& it, std::ios_base& iosb,
|
||||
CharType fill, ValType val) const
|
||||
{
|
||||
switch((boost::math::fpclassify)(val)) {
|
||||
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, "-", "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, "+", "inf", fill, val);
|
||||
}
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "inf", fill);
|
||||
{ // just "inf" wanted.
|
||||
put_num_and_fill(it, iosb, "", "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, "-", "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, "+", "nan", fill, val);
|
||||
}
|
||||
else
|
||||
put_num_and_fill(it, iosb, "", "nan", fill);
|
||||
{ // Just "nan".
|
||||
put_num_and_fill(it, iosb, "", "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.
|
||||
|
||||
std::ostringstream zeros;
|
||||
|
||||
//std::cout << "iosb.flags() = " << std::hex << iosb.flags() << std::endl;
|
||||
//std::cout << "iosb.precision() = " << std::hex << iosb.precision() << std::endl;
|
||||
//std::cout << "iosb.width() = " << std::hex << iosb.width() << std::endl;
|
||||
// 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(fill);
|
||||
zeros << ValType(0);
|
||||
// std::cout << "zeros.str() = "<< zeros.str() << std::endl;
|
||||
// put_num_and_fill(it, iosb, "-", zeros.str().c_str(), fill, val);
|
||||
|
||||
put_num_and_fill(it, iosb, "-", 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, 0, 0, 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
|
||||
const char* 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::strlen(prefix) : 0;
|
||||
int body_length = body ? (int)std::strlen(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);
|
||||
|
||||
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(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);
|
||||
}
|
||||
|
||||
if(adjust == std::ios_base::left)
|
||||
put_fill(it, iosb, fill, width);
|
||||
if(prefix)
|
||||
{ // Adjust width for prefix.
|
||||
while(*prefix)
|
||||
*it = ct.widen(*(prefix++));
|
||||
iosb.width( iosb.width() - prefix_length );
|
||||
width -= prefix_length;
|
||||
}
|
||||
|
||||
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(ct.widen(*(body++)));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*body)
|
||||
*it = ct.widen(*(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
|
||||
{
|
||||
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 +591,5 @@ namespace boost {
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // BOOST_MATH_NONFINITE_NUM_FACETS_HPP
|
||||
|
||||
|
||||
Reference in New Issue
Block a user