Skip to content

Commit

Permalink
Merge pull request #795 from cppalliance/develop
Browse files Browse the repository at this point in the history
Merge to Master for 3.0.1
  • Loading branch information
mborland authored Jan 20, 2025
2 parents 7b272ee + 394daf2 commit 1a300d3
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 47 deletions.
1 change: 1 addition & 0 deletions doc/decimal.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ https://www.boost.org/LICENSE_1_0.txt
Matt Borland and Chris Kormanyos

include::decimal/overview.adoc[]
include::decimal/basics.adoc[]
include::decimal/api_reference.adoc[]
include::decimal/generic_decimal.adoc[]
include::decimal/decimal32.adoc[]
Expand Down
85 changes: 85 additions & 0 deletions doc/decimal/basics.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
////
Copyright 2025 Matt Borland
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////

[#basics]
= Basic Usage
:idprefix: basics_

== Construction of Decimal Types

Every decimal type can be constructed in a few ways:

1) The parameters to the constructor are like so:

[source, c++]
----
template <typename T, typename T2>
constexpr decimal32(T coeff, T2 exp, bool sign = false) noexcept;
----

Where types `T` and `T2` are integral types (signed and unsigned are both allowed).
Lastly the sign follows the convention of `signbit` where `false` is positive and `true` is negative.
If both a negative coefficient and a sign are passed then the resulting decimal number will be negative.
The final number constructed is in the form (sign || coeff < 0 ? -1 : 1) x abs(coeff) x 10^exp.

[souce, c++]
----
boost::decimal::decimal32 a {1, 0}; // constructs 1
boost::decimal::decimal32 b {-2, 0}; // constructs -2
boost::decimal::decimal32 c {2, 0, true}; // Also constructs -2
boost::decimal::decimal32 d {-2, 0, true}; // Also constructs -2
boost::decimal::decimal32 e {5, 5}; // constructs 5x10^5
boost::decimal::decimal32 f {1234, -3} // constructs 1.234 or 1234x10^-3
----

2) A decimal number can be explicitly or implicitly constructed from an integer.
For example:

[source, c++]
----
boost::decimal::decimal64 g = 1;
boost::decimal::decimal32 h {-4};
----

3) A decimal number can only be explicitly constructed from a floating point type.
For example:

[source, c++]
----
boost::decimal::decimal128 pi {3.14};
----

NOTE: Due to the differences in decimal and binary floating point numbers there may be a difference in the resulting representation in decimal format, and thus it is not recommended to construct from binary floating point numbers

== Using the Library

The entire library should be accessed using the convenience header `<boost/decimal.hpp>`.
A short example of the basic usage:

[source, c++]
----
#include <boost/decimal.hpp>
#include <iostream>
#include <iomanip>
int main()
{
using namespace boost::decimal;
// Outputs 0.30000000000000004
std::cout << std::setprecision(17) << 0.1 + 0.2 << std::endl;
// Construct the two decimal values
constexpr decimal64 a {1, -1}; // 1e-1 or 0.1
constexpr decimal64 b {2, -1}; // 2e-1 or 0.2
// Outputs 0.30000000000000000
std::cout << a + b << std::endl;
return 0;
}
----
2 changes: 2 additions & 0 deletions doc/decimal/charconv.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ BOOST_DECIMAL_CONSTEXPR std::to_chars_result to_chars(char* first, char* last, D
} //namespace boost
----

All `to_chars` functions ignore the effects of cohorts, and instead output normalized values.

NOTE: `BOOST_DECIMAL_CONSTEXPR` is defined if:

- `_MSC_FULL_VER` >= 192528326
Expand Down
2 changes: 1 addition & 1 deletion doc/decimal/cmath.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ constexpr int quantexp128(decimal128 x) noexcept;

Effects: if x is finite, returns its quantum exponent.

Otherwise, a domain error occurs and `INT_MIN` is returned.
Otherwise, `INT_MIN` is returned.

=== quantized

Expand Down
4 changes: 4 additions & 0 deletions doc/decimal/decimal128.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ The encoding of Decimal128 is in the <<conversions, BID format>>.
namespace boost {
namespace decimal {
class decimal128 {
// Paragraph numbers are from ISO/IEC DTR 24733
// 3.2.4.1 construct/copy/destroy
Expand Down Expand Up @@ -85,6 +87,8 @@ explicit constexpr operator std::bfloat16_t() const noexcept;
explicit constexpr operator decimal32() const noexcept;
explicit constexpr operator decimal64() const noexcept;
}; // class decimal128
} //namespace decimal
} //namespace boost
Expand Down
4 changes: 4 additions & 0 deletions doc/decimal/decimal128_fast.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ As is often the case this trades space for time by having greater storage width
namespace boost {
namespace decimal {
class decimal128_fast {
// Paragraph numbers are from ISO/IEC DTR 24733
// 3.2.4.1 construct/copy/destroy
Expand Down Expand Up @@ -85,6 +87,8 @@ explicit constexpr operator std::bfloat16_t() const noexcept;
explicit constexpr operator decimal32() const noexcept;
explicit constexpr operator decimal64() const noexcept;
}; // class decimal128_fast
} //namespace decimal
} //namespace boost
Expand Down
4 changes: 4 additions & 0 deletions doc/decimal/decimal32.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ The encoding of Decimal32 is in the <<conversions, BID format>>.
namespace boost {
namespace decimal {
class decimal32 {
// Paragraph numbers are from ISO/IEC DTR 24733
// 3.2.2.1 construct/copy/destroy
Expand Down Expand Up @@ -85,6 +87,8 @@ explicit constexpr operator std::bfloat16_t() const noexcept;
explicit constexpr operator decimal64() const noexcept;
explicit constexpr operator decimal128() const noexcept;
}; // class decimal32
} //namespace decimal
} //namespace boost
Expand Down
4 changes: 4 additions & 0 deletions doc/decimal/decimal32_fast.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ As is often the case this trades space for time by having greater storage width
namespace boost {
namespace decimal {
class decimal32_fast {
// Paragraph numbers are from ISO/IEC DTR 24733
// 3.2.2.1 construct/copy/destroy
Expand Down Expand Up @@ -85,6 +87,8 @@ explicit constexpr operator std::bfloat16_t() const noexcept;
explicit constexpr operator decimal64() const noexcept;
explicit constexpr operator decimal128() const noexcept;
}; // class decimal32_fast
} //namespace decimal
} //namespace boost
Expand Down
4 changes: 4 additions & 0 deletions doc/decimal/decimal64.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ The encoding of Decimal64 is in the <<conversions, BID format>>.
namespace boost {
namespace decimal {
class decimal64 {
// Paragraph numbers are from ISO/IEC DTR 24733
// 3.2.3.1 construct/copy/destroy
Expand Down Expand Up @@ -85,6 +87,8 @@ explicit constexpr operator std::bfloat16_t() const noexcept;
explicit constexpr operator decimal32() const noexcept;
explicit constexpr operator decimal128() const noexcept;
}; // class decimal64
} //namespace decimal
} //namespace boost
Expand Down
4 changes: 4 additions & 0 deletions doc/decimal/decimal64_fast.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ As is often the case this trades space for time by having greater storage width
namespace boost {
namespace decimal {
class decimal64_fast {
// Paragraph numbers are from ISO/IEC DTR 24733
// 3.2.3.1 construct/copy/destroy
Expand Down Expand Up @@ -85,6 +87,8 @@ explicit constexpr operator std::bfloat16_t() const noexcept;
explicit constexpr operator decimal32() const noexcept;
explicit constexpr operator decimal128() const noexcept;
}; // class decimal64_fast
} //namespace decimal
} //namespace boost
Expand Down
31 changes: 0 additions & 31 deletions doc/decimal/overview.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,34 +40,3 @@ as well as emulated PPC64LE and STM32 using QEMU with the following compilers:

Tested on https://github.com/cppalliance/decimal/actions[Github Actions] and https://drone.cpp.al/cppalliance/decimal[Drone].
Coverage can be found on https://app.codecov.io/gh/cppalliance/decimal[Codecov].

== Basic Usage

The entire library should be accessed using the convince header `<boost/decimal.hpp>`.
A short example of the basic usage:

[source, c++]
----
#include <boost/decimal.hpp>
#include <iostream>
#include <iomanip>
int main()
{
using namespace boost::decimal;
// Outputs 0.30000000000000004
std::cout << std::setprecision(17) << 0.1 + 0.2;
// Construct the two decimal values
constexpr decimal64 a {1, -1}; // 1e-1 or 0.1
constexpr decimal64 b {2, -1}; // 2e-1 or 0.2
// Outputs 0.30000000000000000
std::cout << a + b << std::endl;
return 0;
}
----

35 changes: 21 additions & 14 deletions include/boost/decimal/charconv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,16 +542,16 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_fixed_impl(char* first, char* last, const
{
append_trailing_zeros = true;
}
}

// In general formatting we remove trailing 0s
if (fmt == chars_format::general)
{

const auto zeros_removal {remove_trailing_zeros(significand)};
significand = zeros_removal.trimmed_number;
exponent += static_cast<int>(zeros_removal.number_of_removed_zeros);
num_dig -= static_cast<int>(zeros_removal.number_of_removed_zeros);
}
// In general formatting we remove trailing 0s
// Same with unspecified precision fixed formatting
if ((precision == -1 && fmt == chars_format::fixed) || fmt == chars_format::general)
{
const auto zeros_removal {remove_trailing_zeros(significand)};
significand = zeros_removal.trimmed_number;
exponent += static_cast<int>(zeros_removal.number_of_removed_zeros);
num_dig -= static_cast<int>(zeros_removal.number_of_removed_zeros);
}

// Make sure the result will fit in the buffer
Expand All @@ -569,25 +569,32 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_fixed_impl(char* first, char* last, const
*first++ = '0';
return {first, std::errc()};
}
else if (num_leading_zeros > precision)
else if (precision != -1 && num_leading_zeros > precision)
{
*first++ = '0';
*first++ = '.';
std::memset(first, '0', static_cast<std::size_t>(precision));
boost::decimal::detail::memset(first, '0', static_cast<std::size_t>(precision));
return {first + precision, std::errc()};
}
else
{
*first++ = '0';
*first++ = '.';
std::memset(first, '0', static_cast<std::size_t>(num_leading_zeros));
boost::decimal::detail::memset(first, '0', static_cast<std::size_t>(num_leading_zeros));
first += num_leading_zeros;

// We can skip the rest if there's nothing more to do for the required precision
if (significand == 0)
{
std::memset(first, '0', static_cast<std::size_t>(precision - num_leading_zeros));
return {first + precision, std::errc()};
if (precision - num_leading_zeros > 0)
{
boost::decimal::detail::memset(first, '0', static_cast<std::size_t>(precision - num_leading_zeros));
return {first + precision, std::errc()};
}
else
{
return {first, std::errc()};
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions include/boost/decimal/detail/memcpy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#if defined(__GNUC__) && __GNUC__ >= 10
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wstringop-overflow"
# pragma GCC diagnostic ignored "-Warray-bounds"
# define BOOST_DECIMAL_STRINGOP_OVERFLOW_DISABLED
#endif

Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ project : requirements
run-fail benchmarks.cpp ;
run compare_dec128_and_fast.cpp ;
compile-fail concepts_test.cpp ;
run crash_report_1.cpp ;
run github_issue_426.cpp ;
run github_issue_448.cpp ;
run-fail github_issue_519.cpp ;
Expand Down
27 changes: 27 additions & 0 deletions test/crash_report_1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2025 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/decimal.hpp>
#include <boost/core/lightweight_test.hpp>
#include <iostream>

using namespace boost::decimal;

int main()
{
char buffer[64]{};
const auto print_val {0.000001_df};

const auto r = boost::decimal::to_chars(
buffer,
buffer + sizeof(buffer),
print_val,
boost::decimal::chars_format::fixed
);
*r.ptr = '\0';

BOOST_TEST_CSTR_EQ(buffer, "0.000001");

return boost::report_errors();
}
Loading

0 comments on commit 1a300d3

Please sign in to comment.