@@ -1234,6 +1234,18 @@ static inline uint64_t UInt64FromBigEndian(const uint8_t* bytes, int32_t length)
12341234#endif
12351235}
12361236
1237+ static bool RescaleWouldCauseDataLoss (const Decimal& value, int32_t delta_scale,
1238+ const Decimal& multiplier, Decimal* result) {
1239+ if (delta_scale < 0 ) {
1240+ auto result = value.Divide (multiplier);
1241+ assert (result);
1242+ return result->second != 0 ;
1243+ }
1244+
1245+ *result = value * multiplier;
1246+ return (value < 0 ) ? *result > value : *result < value;
1247+ }
1248+
12371249} // namespace
12381250
12391251Result<Decimal> Decimal::FromReal (float x, int32_t precision, int32_t scale) {
@@ -1322,7 +1334,23 @@ Result<Decimal> Decimal::Rescale(int32_t orig_scale, int32_t new_scale) const {
13221334 return *this ;
13231335 }
13241336
1325- return NotImplemented (" Decimal::Rescale is not implemented yet" );
1337+ const int32_t delta_scale = new_scale - orig_scale;
1338+ const int32_t abs_delta_scale = std::abs (delta_scale);
1339+ Decimal out;
1340+
1341+ assert (abs_delta_scale <= kMaxScale );
1342+
1343+ auto & multiplier = kDecimal128PowersOfTen [abs_delta_scale];
1344+
1345+ const bool rescale_would_cause_data_loss =
1346+ RescaleWouldCauseDataLoss (*this , delta_scale, multiplier, &out);
1347+
1348+ if (rescale_would_cause_data_loss) {
1349+ return Invalid (" Rescale would cause data loss: {} -> {}" , ToIntegerString (),
1350+ out.ToIntegerString ());
1351+ }
1352+
1353+ return out;
13261354}
13271355
13281356bool Decimal::FitsInPrecision (int32_t precision) const {
0 commit comments