@@ -51,15 +51,15 @@ namespace {
5151// Signed left shift with well-defined behaviour on negative numbers or overflow
5252template <typename SignedInt, typename Shift>
5353 requires std::is_signed_v<SignedInt> && std::is_integral_v<Shift>
54- constexpr SignedInt SafeLeftShift (SignedInt u, Shift shift ) {
54+ constexpr SignedInt SafeLeftShift (SignedInt u, Shift bits ) {
5555 using UnsignedInt = std::make_unsigned_t <SignedInt>;
56- return static_cast <SignedInt>(static_cast <UnsignedInt>(u) << shift );
56+ return static_cast <SignedInt>(static_cast <UnsignedInt>(u) << bits );
5757}
5858
5959struct DecimalComponents {
6060 std::string_view while_digits;
6161 std::string_view fractional_digits;
62- int32_t exponent;
62+ int32_t exponent{ 0 } ;
6363 char sign{0 };
6464 bool has_exponent{false };
6565};
@@ -100,9 +100,8 @@ bool ParseDecimalComponents(std::string_view str, DecimalComponents* out) {
100100
101101 // Optional dot
102102 if (IsDot (str[pos])) {
103- ++pos;
104103 // Second run of digits after the dot
105- pos = ParseDigitsRun (str, pos, &out->fractional_digits );
104+ pos = ParseDigitsRun (str, ++ pos, &out->fractional_digits );
106105 }
107106 if (out->fractional_digits .empty () && out->while_digits .empty ()) {
108107 // Need at least some digits (whole or fractional)
@@ -200,7 +199,7 @@ constexpr std::array<Decimal, Decimal::kMaxScale + 1> kDecimal128PowersOfTen = {
200199 Decimal (542101086242752217LL , 68739955140067328ULL ),
201200 Decimal (5421010862427522170LL , 687399551400673280ULL )};
202201
203- static inline void ShiftAndAdd (std::string_view input, uint128_t & out) {
202+ inline void ShiftAndAdd (std::string_view input, uint128_t & out) {
204203 for (size_t pos = 0 ; pos < input.size ();) {
205204 const size_t group_size = std::min (kInt64DecimalDigits , input.size () - pos);
206205 const uint64_t multiple = kUInt64PowersOfTen [group_size];
@@ -213,12 +212,11 @@ static inline void ShiftAndAdd(std::string_view input, uint128_t& out) {
213212 }
214213}
215214
216- static void AdjustIntegerStringWithScale (std::string* str, int32_t scale ) {
215+ void AdjustIntegerStringWithScale (int32_t scale, std::string* str) {
217216 if (scale == 0 ) {
218217 return ;
219218 }
220- assert (str != nullptr );
221- assert (!str->empty ());
219+ ICEBERG_DCHECK (str != nullptr && !str->empty (), " str must not be null or empty" );
222220 const bool is_negative = str->front () == ' -' ;
223221 const auto is_negative_offset = static_cast <int32_t >(is_negative);
224222 const auto len = static_cast <int32_t >(str->size ());
@@ -291,7 +289,7 @@ Decimal::Decimal(std::string_view str) {
291289}
292290
293291Decimal& Decimal::Negate () {
294- uint128_t u = static_cast <uint128_t >(~ data_) + 1 ;
292+ uint128_t u = ~ static_cast <uint128_t >(data_) + 1 ;
295293 data_ = static_cast <int128_t >(u);
296294 return *this ;
297295}
@@ -341,25 +339,17 @@ Decimal& Decimal::operator&=(const Decimal& other) {
341339 return *this ;
342340}
343341
344- Decimal& Decimal::operator <<=(uint32_t shift) {
345- if (shift != 0 ) {
346- if (shift < 128 ) {
347- data_ = static_cast <int128_t >(static_cast <uint128_t >(data_) << shift);
348- } else {
349- data_ = 0 ;
350- }
342+ Decimal& Decimal::operator <<=(uint32_t bits) {
343+ if (bits != 0 ) {
344+ data_ = static_cast <int128_t >(static_cast <uint128_t >(data_) << bits);
351345 }
352346
353347 return *this ;
354348}
355349
356- Decimal& Decimal::operator >>=(uint32_t shift) {
357- if (shift != 0 ) {
358- if (shift < 128 ) {
359- data_ >>= shift;
360- } else {
361- data_ = (data_ < 0 ) ? -1 : 0 ;
362- }
350+ Decimal& Decimal::operator >>=(uint32_t bits) {
351+ if (bits != 0 ) {
352+ data_ >>= bits;
363353 }
364354
365355 return *this ;
@@ -372,7 +362,7 @@ Result<std::string> Decimal::ToString(int32_t scale) const {
372362 kMaxScale , scale);
373363 }
374364 std::string str (ToIntegerString ());
375- AdjustIntegerStringWithScale (&str, scale );
365+ AdjustIntegerStringWithScale (scale, &str );
376366 return str;
377367}
378368
@@ -571,7 +561,7 @@ struct DecimalRealConversion {
571561 template <typename Real>
572562 static Real PowerOfTen (int32_t exp) {
573563 constexpr int32_t N = kPrecomputedPowersOfTen ;
574- assert (exp >= -N && exp <= N);
564+ ICEBERG_DCHECK (exp >= -N && exp <= N, " " );
575565 return RealTraits<Real>::powers_of_ten ()[N + exp];
576566 }
577567
@@ -590,7 +580,7 @@ struct DecimalRealConversion {
590580 static constexpr int32_t kMaxScale = Decimal::kMaxScale ;
591581
592582 static constexpr auto & DecimalPowerOfTen (int32_t exp) {
593- assert (exp >= 0 && exp <= kMaxPrecision );
583+ ICEBERG_DCHECK (exp >= 0 && exp <= kMaxPrecision , " " );
594584 return kDecimal128PowersOfTen [exp];
595585 }
596586
@@ -635,11 +625,12 @@ struct DecimalRealConversion {
635625 }
636626
637627 template <typename Real>
638- static Result<Decimal> FromPositiveApprox (Real real, int32_t precision, int32_t scale) {
628+ static Result<Decimal> FromPositiveRealApprox (Real real, int32_t precision,
629+ int32_t scale) {
639630 // Approximate algorithm that operates in the FP domain (thus subject
640631 // to precision loss).
641- const auto x = std::nearbyint (real * PowerOfTen<double >(scale));
642- const auto max_abs = PowerOfTen<double >(precision);
632+ const auto x = std::nearbyint (real * PowerOfTen<Real >(scale));
633+ const auto max_abs = PowerOfTen<Real >(precision);
643634 if (x <= -max_abs || x >= max_abs) {
644635 return Invalid (" Cannot convert {} to Decimal(precision = {}, scale = {}): overflow" ,
645636 real, precision, scale);
@@ -649,10 +640,10 @@ struct DecimalRealConversion {
649640 const auto high = std::floor (std::ldexp (x, -64 ));
650641 const auto low = x - std::ldexp (high, 64 );
651642
652- assert (high >= 0 );
653- assert (high < 9.223372036854776e+18 ); // 2**63
654- assert (low >= 0 );
655- assert (low < 1.8446744073709552e+19 ); // 2**64
643+ ICEBERG_DCHECK (high >= 0 , " " );
644+ ICEBERG_DCHECK (high < 9.223372036854776e+18 , " " ); // 2**63
645+ ICEBERG_DCHECK (low >= 0 , " " );
646+ ICEBERG_DCHECK (low < 1.8446744073709552e+19 , " " ); // 2**64
656647 return Decimal (static_cast <int64_t >(high), static_cast <uint64_t >(low));
657648 }
658649
@@ -665,7 +656,7 @@ struct DecimalRealConversion {
665656 // closest to `real * 10^scale`.
666657 if (scale < 0 ) {
667658 // Negative scales are not handled below, fall back to approx algorithm
668- return FromPositiveApprox (real, precision, scale);
659+ return FromPositiveRealApprox (real, precision, scale);
669660 }
670661
671662 // 1. Check that `real` is within acceptable bounds.
@@ -737,7 +728,8 @@ struct DecimalRealConversion {
737728 total_exp += exp;
738729 // The supplementary right shift required so that
739730 // `x * 10^total_exp / 2^total_shift` fits in the decimal.
740- assert (static_cast <size_t >(total_exp) < sizeof (kCeilLog2PowersOfTen ));
731+ ICEBERG_DCHECK (static_cast <size_t >(total_exp) < sizeof (kCeilLog2PowersOfTen ),
732+ " " );
741733 const int32_t bits =
742734 std::min (right_shift_by, kCeilLog2PowersOfTen [total_exp] - total_shift);
743735 total_shift += bits;
@@ -799,7 +791,7 @@ struct DecimalRealConversion {
799791
800792 // Split decimal into whole and fractional parts to avoid precision loss
801793 auto s = decimal.GetWholeAndFraction (scale);
802- assert (s );
794+ ICEBERG_DCHECK (s, " Decimal::GetWholeAndFraction failed " );
803795
804796 Real whole = ToRealPositiveNoSplit<Real>(s->first , 0 );
805797 Real fraction = ToRealPositiveNoSplit<Real>(s->second , scale);
@@ -809,8 +801,8 @@ struct DecimalRealConversion {
809801
810802 template <typename Real>
811803 static Result<Decimal> FromReal (Real value, int32_t precision, int32_t scale) {
812- assert (precision >= 1 && precision <= kMaxPrecision );
813- assert (scale >= -kMaxScale && scale <= kMaxScale );
804+ ICEBERG_DCHECK (precision >= 1 && precision <= kMaxPrecision , " " );
805+ ICEBERG_DCHECK (scale >= -kMaxScale && scale <= kMaxScale , " " );
814806
815807 if (!std::isfinite (value)) {
816808 return InvalidArgument (" Cannot convert {} to Decimal" , value);
@@ -830,7 +822,7 @@ struct DecimalRealConversion {
830822
831823 template <typename Real>
832824 static Real ToReal (const Decimal& decimal, int32_t scale) {
833- assert (scale >= -kMaxScale && scale <= kMaxScale );
825+ ICEBERG_DCHECK (scale >= -kMaxScale && scale <= kMaxScale , " " );
834826
835827 if (decimal.IsNegative ()) {
836828 // Convert the absolute value to avoid precision loss
@@ -866,7 +858,7 @@ static bool RescaleWouldCauseDataLoss(const Decimal& value, int32_t delta_scale,
866858 const Decimal& multiplier, Decimal* result) {
867859 if (delta_scale < 0 ) {
868860 auto res = value.Divide (multiplier);
869- assert (res);
861+ ICEBERG_DCHECK (res, " Decimal::Divide failed " );
870862 *result = res->first ;
871863 return res->second != 0 ;
872864 }
@@ -886,7 +878,7 @@ Result<Decimal> Decimal::FromReal(double x, int32_t precision, int32_t scale) {
886878}
887879
888880Result<std::pair<Decimal, Decimal>> Decimal::GetWholeAndFraction (int32_t scale) const {
889- assert (scale >= 0 && scale <= kMaxScale );
881+ ICEBERG_DCHECK (scale >= 0 && scale <= kMaxScale , " " );
890882
891883 Decimal multiplier (kDecimal128PowersOfTen [scale]);
892884 return Divide (multiplier);
@@ -946,19 +938,6 @@ Result<Decimal> Decimal::FromBigEndian(const uint8_t* bytes, int32_t length) {
946938}
947939
948940Result<Decimal> Decimal::Rescale (int32_t orig_scale, int32_t new_scale) const {
949- if (orig_scale < 0 || orig_scale > kMaxScale ) {
950- return InvalidArgument (
951- " Decimal::Rescale: original scale must be in the range [0, {}], "
952- " was {}" ,
953- kMaxScale , orig_scale);
954- }
955- if (new_scale < 0 || new_scale > kMaxScale ) {
956- return InvalidArgument (
957- " Decimal::Rescale: new scale must be in the range [0, {}], "
958- " was {}" ,
959- kMaxScale , new_scale);
960- }
961-
962941 if (orig_scale == new_scale) {
963942 return *this ;
964943 }
@@ -967,23 +946,23 @@ Result<Decimal> Decimal::Rescale(int32_t orig_scale, int32_t new_scale) const {
967946 const int32_t abs_delta_scale = std::abs (delta_scale);
968947 Decimal out;
969948
970- assert (abs_delta_scale <= kMaxScale );
949+ ICEBERG_DCHECK (abs_delta_scale <= kMaxScale , " " );
971950
972951 auto & multiplier = kDecimal128PowersOfTen [abs_delta_scale];
973952
974953 const bool rescale_would_cause_data_loss =
975954 RescaleWouldCauseDataLoss (*this , delta_scale, multiplier, &out);
976955
977956 if (rescale_would_cause_data_loss) {
978- return Invalid (" Rescale would cause data loss: {} -> {}" , ToIntegerString (),
979- out. ToIntegerString () );
957+ return Invalid (" Rescale {} from {} to {} would cause data loss " , ToIntegerString (),
958+ orig_scale, new_scale );
980959 }
981960
982961 return out;
983962}
984963
985964bool Decimal::FitsInPrecision (int32_t precision) const {
986- assert (precision >= 1 && precision <= kMaxPrecision );
965+ ICEBERG_DCHECK (precision >= 1 && precision <= kMaxPrecision , " " );
987966 return Decimal::Abs (*this ) < kDecimal128PowersOfTen [precision];
988967}
989968
0 commit comments