////
Copyright 2024 Matt Borland
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////

[#decimal_fast128_t]
= `decimal_fast128_t`
:idprefix: decimal_fast128_t_

== Description

`decimal_fast128_t` has the same ranges of values and representations as `decimal_fast128_t` but with greater performance.
The performance changes by being non-IEEE 754 compliant so that the value does not have to be decoded from bits, but is instead directly represented internal to the type.
As is often the case this trades space for time by having greater storage width requirements.

|===
| Attribute | values
| Storage Width | 168 bits
| Precision | 34 decimal digits
| Max exponent | 6145
| Max Value | 9.99999...e+6145
| Smallest Normalized Value | 1.0000...e-6142
| Smallest Subnormal Value | Flushed to 0
|===

IMPORTANT: `decimal_fast128_t` does not support subnormal values

IMPORTANT: Prior to v5.0.0 this type was known as `decimal128_fast`.
This name has been removed in v6.0.0.

[source, c++]
----
#include <boost/decimal/decimal_fast128_t.hpp>

namespace boost {
namespace decimal {

class decimal_fast128_t {

public:
    using significand_type = detail::uint128;
    using exponent_type = std::uint_fast32_t;
    using biased_exponent_type = std::int32_t;

// Paragraph numbers are from ISO/IEC DTR 24733

// 3.2.4.1 construct/copy/destroy
constexpr decimal_fast128_t() noexcept = default;

// 3.2.4.2 Conversion form floating-point type
template <typename Float>
explicit BOOST_DECIMAL_CXX20_CONSTEXPR decimal_fast128_t(Float val) noexcept;

// 3.2.4.3 Conversion from integral type
template <typename Integer>
explicit constexpr decimal_fast128_t(Integer val) noexcept;

// Extension: Construction from (c)string
explicit constexpr decimal_fast128_t(const char* str);

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
explicit inline decimal_fast128_t(const std::string& str);
#else
explicit constexpr decimal_fast128_t(std::string_view str);
#endif

template <typename UnsignedIntegral, typename Integral>
constexpr decimal_fast128_t(UnsignedIntegral coeff, Integral exp, bool is_negative = false) noexcept;

template <typename SignedIntegral, typename Integral>
constexpr decimal_fast128_t(SignedIntegral coeff, Integral exp) noexcept;

template <typename Integral>
constexpr decimal_fast128_t& operator=(const Integeral& RHS) noexcept;

// 3.2.4.4 Conversion to integral type
// If the value exceeds the range of the integral,
// or is non-finite std::numeric_limits::max() is returned
explicit constexpr operator int() const noexcept;
explicit constexpr operator unsigned() const noexcept;
explicit constexpr operator long() const noexcept;
explicit constexpr operator unsigned long() const noexcept;
explicit constexpr operator long long() const noexcept;
explicit constexpr operator unsigned long long() const noexcept;

// 3.2.4.5 increment and decrement operators:
constexpr decimal_fast128_t& operator++();
constexpr decimal_fast128_t  operator++(int);
constexpr decimal_fast128_t& operator--();
constexpr decimal_fast128_t  operator--(int);

// 3.2.4.6 compound assignment:
constexpr decimal_fast128_t& operator+=(RHS rhs);
constexpr decimal_fast128_t& operator-=(RHS rhs);
constexpr decimal_fast128_t& operator*=(RHS rhs);
constexpr decimal_fast128_t& operator/=(RHS rhs);

// 3.2.6 Conversion to floating-point type
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator float() const noexcept;
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator double() const noexcept;
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator long double() const noexcept;

// The following are available assuming a C++23 compiler that provides the header <stdfloat>
explicit constexpr operator std::float16_t() const noexcept;
explicit constexpr operator std::float32_t() const noexcept;
explicit constexpr operator std::float64_t() const noexcept;
explicit constexpr operator std::bfloat16_t() const noexcept;

explicit constexpr operator decimal32_t() const noexcept;
explicit constexpr operator decimal_fast32_t() const noexcept;
explicit constexpr operator decimal64_t() const noexcept;
explicit constexpr operator decimal_fast64_t() const noexcept;
explicit constexpr operator decimal128_t() const noexcept;

}; // class decimal_fast128_t

} //namespace decimal
} //namespace boost

----


== Operator Behavior

=== Construction to and from binary floating-point type

[source, c++]
----
// 3.2.2.2 Conversion from floating-point type
template <typename Float>
explicit BOOST_DECIMAL_CXX20_CONSTEXPR decimal_fast128_t(Float val) noexcept;

// 3.2.6 Conversion to floating-point type
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator float() const noexcept;
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator double() const noexcept;
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator long double() const noexcept;

// If C++23 and <stdfloat> are available
explicit constexpr operator std::float16_t() const noexcept;
explicit constexpr operator std::float32_t() const noexcept;
explicit constexpr operator std::float64_t() const noexcept;
explicit constexpr operator std::bfloat16_t() const noexcept;
----

See: xref:binary_floating_conversions.adoc[]

=== Construction From Integral Type

[source,c++]
----
// 3.2.2.3 Conversion from integral type
template <typename Integer>
explicit constexpr decimal_fast128_t(Integer val) noexcept;
----

Constructs a decimal value subject to the current rounding mode (if necessary).

=== Construction From String

[source,c++]
----
// Extension: Construction from (c)string
explicit constexpr decimal_fast128_t(const char* str);

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
explicit inline decimal_fast128_t(const std::string& str);
#else
explicit constexpr decimal_fast128_t(std::string_view str);
#endif
----

Constructs a decimal value that matches `str` subject to:

. If `str` is a `nullptr` or of length 0 either:
.. `throw std::runtime_error`
.. Constructs a `QNAN` in a no exception environment
. If `str` is an invalid string either:
.. `throw std::runtime_error`
.. Constructs a `QNAN` in a no exception environment
. On overflow constructs `INF`
. On underflow constructs `0`
. Rounds value represented by `str` according to current rounding mode

=== Conversion to Integral Type

[source,c++]
----
// 3.2.2.4 Conversion to integral type

explicit constexpr operator int() const noexcept;
explicit constexpr operator unsigned() const noexcept;
explicit constexpr operator long() const noexcept;
explicit constexpr operator unsigned long() const noexcept;
explicit constexpr operator long long() const noexcept;
explicit constexpr operator unsigned long long() const noexcept;
----

Constructs an integer representation of the decimal value subject to:

. If the decimal value is `INF` returns `std::numeric_limits<IntegerType>::max()`
. If the decimal value is `NAN` returns `std::numeric_limits<IntegerType>::max()`
. If the decimal value exceeds the range of the `IntegerType` returns `std::numeric_limits<IntegerType>::max()`

=== Increment and Decrement Operators

[source,c++]
----
// 3.2.2.5 increment and decrement operators:
constexpr decimal_fast128_t& operator++();
constexpr decimal_fast128_t  operator++(int);
constexpr decimal_fast128_t& operator--();
constexpr decimal_fast128_t  operator--(int);
----

Increments/Decrements the decimal value subject to:

. If the decimal value is `NAN` returns `QNAN`
. If the decimal value is `INF` returns `INF`

=== Compound Operators

[source, c++]
----
// 3.2.2.6 compound assignment:
constexpr decimal_fast128_t& operator+=(RHS rhs);
constexpr decimal_fast128_t& operator-=(RHS rhs);
constexpr decimal_fast128_t& operator*=(RHS rhs);
constexpr decimal_fast128_t& operator/=(RHS rhs);
----

Matches the behavior of xref:generic_decimal.adoc#operator_behavior[addition, subtraction, multiplication, and division].

=== Conversion to Other Decimal Types

[source,c++]
----
explicit constexpr operator decimal32_t() const noexcept;
explicit constexpr operator decimal_fast32_t() const noexcept;
explicit constexpr operator decimal64_t() const noexcept;
explicit constexpr operator decimal_fast64_t() const noexcept;
explicit constexpr operator decimal128_t() const noexcept;
----

Conversion to `decimal128_t` is lossless in all cases.

Conversion to any other decimal type is subject to:

. Current rounding mode if the number of digits exceeds the precision of the target type.
. Overflow constructs `INF`.
. Underflow constructs `0`.

== Non-Member Operator Behavior

See xref:fast_types.adoc#fast_operator_behavior[here] for behavior of non-member operators.
