Skip to content

Commit 1cd6c70

Browse files
authored
Merge pull request #654 from cppalliance/dec128fstl
Finish decimal128_fast
2 parents 00cd5ea + 7170194 commit 1cd6c70

File tree

12 files changed

+403
-57
lines changed

12 files changed

+403
-57
lines changed

doc/decimal.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ include::decimal/decimal32.adoc[]
2121
include::decimal/decimal32_fast.adoc[]
2222
include::decimal/decimal64.adoc[]
2323
include::decimal/decimal128.adoc[]
24+
include::decimal/decimal128_fast.adoc[]
2425
include::decimal/conversions.adoc[]
2526
include::decimal/literals.adoc[]
2627
include::decimal/numbers.adoc[]

doc/decimal/benchmarks.adoc

Lines changed: 90 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,29 @@ Run using a Macbook pro with M1 pro chipset running macOS Sonoma 14.4.1 and home
3232
|===
3333
| Type | Runtime (us) | Ratio to `double`
3434
| `float`
35-
| 8764
36-
| 1.577
35+
| 8587
36+
| 1.376
3737
| `double`
38-
| 5559
38+
| 6240
3939
| 1.000
4040
| `decimal32`
41-
| 276,124
42-
| 49.672
41+
| 275,597
42+
| 44.166
4343
| `decimal64`
44-
| 355,999
45-
| 64.760
44+
| 296,929
45+
| 47.587
4646
| `decimal128`
47-
| 989,028
48-
| 177.915
47+
| 821,847
48+
| 131.706
49+
| `decimal32_fast`
50+
| 99,664
51+
| 15.972
52+
| `decimal64_fast`
53+
| 102,132
54+
| 16.367
55+
| `decimal128_fast`
56+
| 1,427,647
57+
| 228.790
4958
|===
5059

5160
== Basic Operations
@@ -62,83 +71,119 @@ Run using a Macbook pro with M1 pro chipset running macOS Sonoma 14.4.1 and home
6271
|===
6372
| Type | Runtime (us) | Ratio to `double`
6473
| `float`
65-
| 2113
66-
| 0.739
74+
| 2705
75+
| 0.859
6776
| `double`
68-
| 2860
77+
| 3148
6978
| 1.000
7079
| `decimal32`
71-
| 353,836
72-
| 123.719
80+
| 351,505
81+
| 111.660
7382
| `decimal64`
74-
| 409,098
75-
| 143.041
83+
| 359,425
84+
| 114.176
7685
| `decimal128`
77-
| 2,418,039
78-
| 845.468
86+
| 1,446,674
87+
| 459.553
88+
| `decimal32_fast`
89+
| 146,873
90+
| 46.656
91+
| `decimal64_fast`
92+
| 139,294
93+
| 44.248
94+
| `decimal128_fast`
95+
| 1,351,882
96+
| 429.442
7997
|===
8098

8199
==== Subtraction
82100

83101
|===
84102
| Type | Runtime (us) | Ratio to `double`
85103
| `float`
86-
| 1782
87-
| 1.061
104+
| 3339
105+
| 2.014
88106
| `double`
89-
| 1680
107+
| 1658
90108
| 1.000
91109
| `decimal32`
92-
| 293,927
93-
| 174.957
110+
| 267,646
111+
| 161.427
94112
| `decimal64`
95-
| 329,425
96-
| 196.086
113+
| 303,589
114+
| 183.106
97115
| `decimal128`
98-
| 1,527,261
99-
| 909.084
116+
| 954,211
117+
| 575.519
118+
| `decimal32_fast`
119+
| 147,112
120+
| 88.729
121+
| `decimal64_fast`
122+
| 145,606
123+
| 87.820
124+
| `decimal128_fast`
125+
| 894,695
126+
| 539.623
100127
|===
101128

102129
==== Multiplication
103130

104131
|===
105132
| Type | Runtime (us) | Ratio to `double`
106133
| `float`
107-
| 1691
108-
| 0.979
134+
| 1646
135+
| 0.957
109136
| `double`
110-
| 1728
137+
| 1720
111138
| 1.000
112139
| `decimal32`
113-
| 309,117
114-
| 178.887
140+
| 313,219
141+
| 182.104
115142
| `decimal64`
116-
| 408,010
117-
| 236.117
143+
| 583,818
144+
| 339.429
118145
| `decimal128`
119-
| 2,506,105
120-
| 1450.292
146+
| 1,881,936
147+
| 1094.149
148+
| `decimal32_fast`
149+
| 86,093
150+
| 50.054
151+
| `decimal64_fast`
152+
| 333,582
153+
| 193.943
154+
| `decimal128_fast`
155+
| 1,822,921
156+
| 1059.838
121157
|===
122158

123159
==== Division
124160

125161
|===
126162
| Type | Runtime (us) | Ratio to `double`
127163
| `float`
128-
| 2058
129-
| 0.846
164+
| 2120
165+
| 0.547
130166
| `double`
131-
| 2434
167+
| 3874
132168
| 1.000
133169
| `decimal32`
134-
| 304,852
135-
| 125.247
170+
| 307,337
171+
| 79.333
136172
| `decimal64`
137-
| 519,990
138-
| 213.636
173+
| 447,910
174+
| 115.620
139175
| `decimal128`
140-
| 3,534,909
141-
| 1452.304
176+
| 2,544,798
177+
| 656.892
178+
| `decimal32_fast`
179+
| 105,796
180+
| 27.309
181+
| `decimal64_fast`
182+
| 291,671
183+
| 75.289
184+
| `decimal128_fast`
185+
| 292,556
186+
| 75.518
142187
|===
143188

144189
== Selected Special Functions

doc/decimal/decimal128.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ https://www.boost.org/LICENSE_1_0.txt
1010

1111
== Description
1212

13-
Decimal64 is the 128-bit version of the decimal interchange format, and has the following properties as defined in IEEE 754-2019 table 3.6
13+
Decimal128 is the 128-bit version of the decimal interchange format, and has the following properties as defined in IEEE 754-2019 table 3.6
1414

1515
- Storage width - 128 bits
1616
- Precision - 34 decimal digits (not bits like binary)

doc/decimal/decimal128_fast.adoc

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
////
2+
Copyright 2024 Matt Borland
3+
Distributed under the Boost Software License, Version 1.0.
4+
https://www.boost.org/LICENSE_1_0.txt
5+
////
6+
7+
[#decimal128_fast]
8+
= Decimal128_fast
9+
:idprefix: decimal128_fast_
10+
11+
== Description
12+
13+
`decimal128_fast` has the same ranges of values and representations as `decimal128_fast` but with greater performance.
14+
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.
15+
As is often the case this trades space for time by having greater storage width requirements.
16+
17+
- Storage width - 128 bits
18+
- Precision - 34 decimal digits (not bits like binary)
19+
- Max exponent - 6145
20+
- Max Value - 9.99999...e6145
21+
- Smallest normalized value - 1.0000...e-6142
22+
- Smallest subnormal - 1e-6176
23+
24+
[source, c++]
25+
----
26+
#include <boost/decimal/decimal128_fast.hpp>
27+
28+
namespace boost {
29+
namespace decimal {
30+
31+
// Paragraph numbers are from ISO/IEC DTR 24733
32+
33+
// 3.2.4.1 construct/copy/destroy
34+
constexpr decimal128_fast() noexcept = default;
35+
36+
// 3.2.4.2 Conversion form floating-point type
37+
template <typename Float>
38+
explicit BOOST_DECIMAL_CXX20_CONSTEXPR decimal128_fast(Float val) noexcept;
39+
40+
// 3.2.4.3 Conversion from integral type
41+
template <typename Integer>
42+
explicit constexpr decimal128_fast(Integer val) noexcept;
43+
44+
template <typename Integral1, typename Integral2>
45+
constexpr decimal128_fast(Integral1 coeff, Integral2 exp, bool sign = false) noexcept;
46+
47+
template <typename Integral>
48+
constexpr decimal128_fast& operator=(const Integeral& RHS) noexcept;
49+
50+
// 3.2.4.4 Conversion to integral type
51+
explicit constexpr operator int() const noexcept;
52+
explicit constexpr operator unsigned() const noexcept;
53+
explicit constexpr operator long() const noexcept;
54+
explicit constexpr operator unsigned long() const noexcept;
55+
explicit constexpr operator long long() const noexcept;
56+
explicit constexpr operator unsigned long long() const noexcept;
57+
explicit constexpr operator std::int8_t() const noexcept;
58+
explicit constexpr operator std::uint8_t() const noexcept;
59+
explicit constexpr operator std::int16_t() const noexcept;
60+
explicit constexpr operator std::uint16_t() const noexcept;
61+
62+
// 3.2.4.5 increment and decrement operators:
63+
constexpr decimal128_fast& operator++();
64+
constexpr decimal128_fast operator++(int);
65+
constexpr decimal128_fast& operator--();
66+
constexpr decimal128_fast operator--(int);
67+
68+
// 3.2.4.6 compound assignment:
69+
constexpr decimal128_fast& operator+=(RHS rhs);
70+
constexpr decimal128_fast& operator-=(RHS rhs);
71+
constexpr decimal128_fast& operator*=(RHS rhs);
72+
constexpr decimal128_fast& operator/=(RHS rhs);
73+
74+
// 3.2.6 Conversion to floating-point type
75+
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator float() const noexcept;
76+
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator double() const noexcept;
77+
explicit BOOST_DECIMAL_CXX20_CONSTEXPR operator long double() const noexcept;
78+
79+
// The following are available assuming a C++23 compiler that provides the header <stdfloat>
80+
explicit constexpr operator std::float16_t() const noexcept;
81+
explicit constexpr operator std::float32_t() const noexcept;
82+
explicit constexpr operator std::float64_t() const noexcept;
83+
explicit constexpr operator std::bfloat16_t() const noexcept;
84+
85+
explicit constexpr operator decimal32() const noexcept;
86+
explicit constexpr operator decimal64() const noexcept;
87+
88+
} //namespace decimal
89+
} //namespace boost
90+
91+
----

include/boost/decimal/bid_conversion.hpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d128(detail::uint128 bits) noexcept
8484
return val;
8585
}
8686

87+
BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid_d128f(decimal128_fast val) noexcept -> detail::uint128
88+
{
89+
const decimal128 compliant_val {val};
90+
const auto bits {detail::bit_cast<detail::uint128>(compliant_val)};
91+
return bits;
92+
}
93+
94+
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d128f(detail::uint128 bits) noexcept -> decimal128_fast
95+
{
96+
const auto compliant_val {detail::bit_cast<decimal128>(bits)};
97+
const decimal128_fast val {compliant_val};
98+
return val;
99+
}
100+
87101
BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal32 val) noexcept -> std::uint32_t
88102
{
89103
return to_bid_d32(val);
@@ -109,6 +123,11 @@ BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal128 val) noexcept -> detail::ui
109123
return to_bid_d128(val);
110124
}
111125

126+
BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal128_fast val) noexcept -> detail::uint128
127+
{
128+
return to_bid_d128f(val);
129+
}
130+
112131
template <typename T = decimal32_fast>
113132
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid(std::uint32_t bits) noexcept
114133
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
@@ -135,9 +154,15 @@ BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid<decimal64>(std::uint64_t bits) noexc
135154
return from_bid_d64(bits);
136155
}
137156

138-
template <typename T = decimal128>
157+
template <typename T = decimal128_fast>
139158
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid(detail::uint128 bits) noexcept
140159
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
160+
{
161+
return from_bid_d128f(bits);
162+
}
163+
164+
template <>
165+
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid<decimal128>(detail::uint128 bits) noexcept -> decimal128
141166
{
142167
return from_bid_d128(bits);
143168
}

0 commit comments

Comments
 (0)