@@ -351,50 +351,34 @@ template <typename T1, typename T2, std::enable_if_t<detail::is_integral_v<T1> &
351351#endif
352352constexpr decimal128_fast::decimal128_fast (T1 coeff, T2 exp, bool sign) noexcept
353353{
354+ // Older compilers have issues with conversions from __uint128, so we skip all that and use our uint128
355+ #if defined(BOOST_DECIMAL_HAS_INT128) && (!defined(__GNUC__) || (defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10)) && (!defined(__clang__) || (defined(__clang__) && __clang_major__ < 13))
356+ using Unsigned_Integer_1 = detail::make_unsigned_t <T1>;
357+ using Unsigned_Integer = std::conditional_t <std::is_same<Unsigned_Integer_1, detail::uint128_t >::value, detail::uint128, Unsigned_Integer_1>;
358+ #else
354359 using Unsigned_Integer = detail::make_unsigned_t <T1>;
360+ #endif
361+
362+ using Basis_Unsigned_Integer = std::conditional_t <std::numeric_limits<Unsigned_Integer>::digits10 < std::numeric_limits<significand_type>::digits10, significand_type, Unsigned_Integer>;
355363
356364 const bool isneg {coeff < static_cast <T1>(0 ) || sign};
357365 sign_ = isneg;
358- Unsigned_Integer unsigned_coeff {detail::make_positive_unsigned (coeff)};
359-
360- auto unsigned_coeff_digits {detail::num_digits (unsigned_coeff)};
361- const bool reduced {unsigned_coeff_digits > detail::precision_v<decimal128>};
362-
363- // Strip digits
364- if (unsigned_coeff_digits > detail::precision_v<decimal128> + 1 )
365- {
366- const auto digits_to_remove {unsigned_coeff_digits - (detail::precision_v<decimal128> + 1 )};
367-
368- #if defined(__GNUC__) && !defined(__clang__)
369- # pragma GCC diagnostic push
370- # pragma GCC diagnostic ignored "-Wconversion"
371- #endif
372-
373- unsigned_coeff /= detail::pow10 (static_cast <Unsigned_Integer>(digits_to_remove));
374-
375- #if defined(__GNUC__) && !defined(__clang__)
376- # pragma GCC diagnostic pop
377- #endif
378-
379- exp += digits_to_remove;
380- unsigned_coeff_digits -= digits_to_remove;
381- }
366+ auto unsigned_coeff {static_cast <Basis_Unsigned_Integer>(detail::make_positive_unsigned (coeff))};
382367
383- // Round as required
384- if (reduced)
385- {
386- exp += static_cast <T2>(detail::fenv_round (unsigned_coeff, isneg));
387- }
368+ // Normalize the significand in the constructor, so we don't have
369+ // to calculate the number of digits for operationss
370+ detail::normalize<decimal128>(unsigned_coeff, exp, sign);
388371
389- significand_ = static_cast <significand_type>( unsigned_coeff) ;
372+ significand_ = unsigned_coeff;
390373
391- // Normalize the handling of zeros
374+ // Normalize the handling of 0
392375 if (significand_ == detail::uint128{UINT64_C (0 ), UINT64_C (0 )})
393376 {
394377 exp = 0 ;
395378 }
396379
397380 const auto biased_exp {static_cast <exponent_type>(exp + detail::bias_v<decimal128>)};
381+
398382 if (biased_exp > detail::max_biased_exp_v<decimal128>)
399383 {
400384 significand_ = detail::d128_fast_inf;
@@ -504,8 +488,9 @@ constexpr auto operator==(const decimal128_fast& lhs, const decimal128_fast& rhs
504488 }
505489 #endif
506490
507- return equal_parts_impl (lhs.significand_ , lhs.biased_exponent (), lhs.sign_ ,
508- rhs.significand_ , rhs.biased_exponent (), rhs.sign_ );
491+ return lhs.sign_ == rhs.sign_ &&
492+ lhs.exponent_ == rhs.exponent_ &&
493+ lhs.significand_ == rhs.significand_ ;
509494}
510495
511496template <typename Integer>
@@ -572,8 +557,17 @@ constexpr auto operator<(const decimal128_fast& lhs, const decimal128_fast& rhs)
572557 }
573558#endif
574559
575- return less_parts_impl<decimal128>(lhs.significand_ , lhs.biased_exponent (), lhs.sign_ ,
576- rhs.significand_ , rhs.biased_exponent (), rhs.sign_ );
560+ if (lhs.significand_ == 0 || rhs.significand_ == 0 )
561+ {
562+ return lhs.significand_ == 0 ? !rhs.sign_ : lhs.sign_ ;
563+ }
564+
565+ if (lhs.exponent_ != rhs.exponent_ )
566+ {
567+ return lhs.sign_ ? lhs.exponent_ > rhs.exponent_ : lhs.exponent_ < rhs.exponent_ ;
568+ }
569+
570+ return lhs.sign_ ? lhs.significand_ > rhs.significand_ : lhs.significand_ < rhs.significand_ ;
577571}
578572
579573template <typename Integer>
@@ -798,17 +792,9 @@ constexpr auto operator+(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d
798792 return lhs - abs (rhs);
799793 }
800794
801- auto lhs_sig {lhs.full_significand ()};
802- auto lhs_exp {lhs.biased_exponent ()};
803- detail::normalize<decimal128>(lhs_sig, lhs_exp);
804-
805- auto rhs_sig {rhs.full_significand ()};
806- auto rhs_exp {rhs.biased_exponent ()};
807- detail::normalize<decimal128>(rhs_sig, rhs_exp);
808-
809795 const auto result {detail::d128_add_impl<detail::decimal128_fast_components>(
810- lhs_sig, lhs_exp , lhs.sign_ ,
811- rhs_sig, rhs_exp , rhs.sign_ )};
796+ lhs. significand_ , lhs. biased_exponent () , lhs.sign_ ,
797+ rhs. significand_ , rhs. biased_exponent () , rhs.sign_ )};
812798
813799 return {result.sig , result.exp , result.sign };
814800};
@@ -831,10 +817,7 @@ constexpr auto operator+(decimal128_fast lhs, Integer rhs) noexcept
831817 }
832818 bool abs_lhs_bigger {abs (lhs) > detail::make_positive_unsigned (rhs)};
833819
834- auto sig_lhs {lhs.full_significand ()};
835- auto exp_lhs {lhs.biased_exponent ()};
836- detail::normalize<decimal128>(sig_lhs, exp_lhs);
837- auto lhs_components {detail::decimal128_fast_components{sig_lhs, exp_lhs, lhs.isneg ()}};
820+ auto lhs_components {detail::decimal128_fast_components{lhs.significand_ , lhs.biased_exponent (), lhs.isneg ()}};
838821
839822 auto sig_rhs {static_cast <detail::uint128>(detail::make_positive_unsigned (rhs))};
840823 std::int32_t exp_rhs {0 };
@@ -901,17 +884,9 @@ constexpr auto operator-(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d
901884
902885 const bool abs_lhs_bigger {abs (lhs) > abs (rhs)};
903886
904- auto sig_lhs {lhs.full_significand ()};
905- auto exp_lhs {lhs.biased_exponent ()};
906- detail::normalize<decimal128>(sig_lhs, exp_lhs);
907-
908- auto sig_rhs {rhs.full_significand ()};
909- auto exp_rhs {rhs.biased_exponent ()};
910- detail::normalize<decimal128>(sig_rhs, exp_rhs);
911-
912887 const auto result {detail::d128_sub_impl<detail::decimal128_fast_components>(
913- sig_lhs, exp_lhs , lhs.sign_ ,
914- sig_rhs, exp_rhs , rhs.sign_ ,
888+ lhs. significand_ , lhs. biased_exponent () , lhs.sign_ ,
889+ rhs. significand_ , rhs. biased_exponent () , rhs.sign_ ,
915890 abs_lhs_bigger
916891 )};
917892
@@ -936,10 +911,7 @@ constexpr auto operator-(decimal128_fast lhs, Integer rhs) noexcept
936911
937912 const bool abs_lhs_bigger {abs (lhs) > detail::make_positive_unsigned (rhs)};
938913
939- auto sig_lhs {lhs.full_significand ()};
940- auto exp_lhs {lhs.biased_exponent ()};
941- detail::normalize<decimal128>(sig_lhs, exp_lhs);
942- auto lhs_components {detail::decimal128_fast_components{sig_lhs, exp_lhs, lhs.isneg ()}};
914+ auto lhs_components {detail::decimal128_fast_components{lhs.significand_ , lhs.biased_exponent (), lhs.isneg ()}};
943915
944916 auto sig_rhs {static_cast <detail::uint128>(detail::make_positive_unsigned (rhs))};
945917 std::int32_t exp_rhs {0 };
@@ -979,10 +951,7 @@ constexpr auto operator-(Integer lhs, decimal128_fast rhs) noexcept
979951 auto unsigned_sig_lhs {detail::make_positive_unsigned (sig_lhs)};
980952 auto lhs_components {detail::decimal128_fast_components{unsigned_sig_lhs, exp_lhs, (lhs < 0 )}};
981953
982- auto sig_rhs {rhs.full_significand ()};
983- auto exp_rhs {rhs.biased_exponent ()};
984- detail::normalize<decimal128>(sig_rhs, exp_rhs);
985- auto rhs_components {detail::decimal128_fast_components{sig_rhs, exp_rhs, rhs.isneg ()}};
954+ auto rhs_components {detail::decimal128_fast_components{rhs.significand_ , rhs.biased_exponent (), rhs.isneg ()}};
986955
987956 const auto result {detail::d128_sub_impl<detail::decimal128_fast_components>(
988957 lhs_components.sig , lhs_components.exp , lhs_components.sign ,
@@ -1115,23 +1084,15 @@ constexpr auto d128f_div_impl(decimal128_fast lhs, decimal128_fast rhs, decimal1
11151084 static_cast <void >(r);
11161085 #endif
11171086
1118- auto sig_lhs {lhs.full_significand ()};
1119- auto exp_lhs {lhs.biased_exponent ()};
1120- detail::normalize<decimal128>(sig_lhs, exp_lhs);
1121-
1122- auto sig_rhs {rhs.full_significand ()};
1123- auto exp_rhs {rhs.biased_exponent ()};
1124- detail::normalize<decimal128>(sig_rhs, exp_rhs);
1125-
11261087 #ifdef BOOST_DECIMAL_DEBUG
11271088 std::cerr << " sig lhs: " << sig_lhs
11281089 << " \n exp lhs: " << exp_lhs
11291090 << " \n sig rhs: " << sig_rhs
11301091 << " \n exp rhs: " << exp_rhs << std::endl;
11311092 #endif
11321093
1133- detail::decimal128_fast_components lhs_components {sig_lhs, exp_lhs , lhs.isneg ()};
1134- detail::decimal128_fast_components rhs_components {sig_rhs, exp_rhs , rhs.isneg ()};
1094+ detail::decimal128_fast_components lhs_components {lhs. significand_ , lhs. biased_exponent () , lhs.isneg ()};
1095+ detail::decimal128_fast_components rhs_components {rhs. significand_ , rhs. biased_exponent () , rhs.isneg ()};
11351096 detail::decimal128_fast_components q_components {};
11361097
11371098 detail::d128_generic_div_impl (lhs_components, rhs_components, q_components);
@@ -1188,11 +1149,7 @@ constexpr auto operator/(decimal128_fast lhs, Integer rhs) noexcept
11881149 }
11891150 #endif
11901151
1191- auto lhs_sig {lhs.full_significand ()};
1192- auto lhs_exp {lhs.biased_exponent ()};
1193- detail::normalize<decimal128>(lhs_sig, lhs_exp);
1194-
1195- detail::decimal128_fast_components lhs_components {lhs_sig, lhs_exp, lhs.isneg ()};
1152+ detail::decimal128_fast_components lhs_components {lhs.significand_ , lhs.biased_exponent (), lhs.isneg ()};
11961153
11971154 auto rhs_sig {detail::make_positive_unsigned (rhs)};
11981155 std::int32_t rhs_exp {};
@@ -1234,12 +1191,8 @@ constexpr auto operator/(Integer lhs, decimal128_fast rhs) noexcept
12341191 }
12351192 #endif
12361193
1237- auto rhs_sig {rhs.full_significand ()};
1238- auto rhs_exp {rhs.biased_exponent ()};
1239- detail::normalize<decimal128>(rhs_sig, rhs_exp);
1240-
12411194 detail::decimal128_fast_components lhs_components {detail::make_positive_unsigned (lhs), 0 , lhs < 0 };
1242- detail::decimal128_fast_components rhs_components {rhs_sig, rhs_exp , rhs.isneg ()};
1195+ detail::decimal128_fast_components rhs_components {rhs. significand_ , rhs. biased_exponent () , rhs.isneg ()};
12431196 detail::decimal128_fast_components q_components {};
12441197
12451198 detail::d128_generic_div_impl (lhs_components, rhs_components, q_components);
0 commit comments