MCPcopy Create free account
hub / github.com/apache/arrow / RoundedRightShift

Method RoundedRightShift

cpp/src/arrow/util/decimal.cc:1316–1361  ·  view source on GitHub ↗

Right shift positive `x` by positive `bits`, rounded half to even

Source from the content-addressed store, hash-verified

1314
1315 // Right shift positive `x` by positive `bits`, rounded half to even
1316 static Decimal256 RoundedRightShift(Decimal256 x, int bits) {
1317 if (bits == 0) {
1318 return x;
1319 }
1320 const int cross_word_shift = bits / 64;
1321 if (cross_word_shift >= Decimal256::kNumWords) {
1322 return Decimal256();
1323 }
1324 const uint32_t in_word_shift = bits % 64;
1325 const auto array_le = x.little_endian_array();
1326 Decimal256::WordArray shifted_le{};
1327 uint64_t shifted_out = 0;
1328 // Iterate from LSW to MSW
1329 for (int i = 0; i < cross_word_shift; ++i) {
1330 // Retain the information that non-zero bits were shifted out.
1331 // This is important for half-to-even rounding.
1332 shifted_out = (shifted_out > 0) | array_le[i];
1333 }
1334 if (in_word_shift != 0) {
1335 const uint64_t carry_bits = array_le[cross_word_shift] << (64 - in_word_shift);
1336 shifted_out = (shifted_out > 0) | (shifted_out >> in_word_shift) | carry_bits;
1337 }
1338 for (int i = cross_word_shift; i < Decimal256::kNumWords; ++i) {
1339 shifted_le[i - cross_word_shift] = array_le[i] >> in_word_shift;
1340 if (in_word_shift != 0 && i + 1 < Decimal256::kNumWords) {
1341 const uint64_t carry_bits = array_le[i + 1] << (64 - in_word_shift);
1342 shifted_le[i - cross_word_shift] |= carry_bits;
1343 }
1344 }
1345 auto result = Decimal256(Decimal256::LittleEndianArray, shifted_le);
1346
1347 // We almost have our result, but now do the rounding.
1348 constexpr uint64_t kHalf = 0x8000000000000000ULL;
1349 if (shifted_out > kHalf) {
1350 // Strictly more than half => round up
1351 result += 1;
1352 } else if (shifted_out == kHalf) {
1353 // Exactly half => round to even
1354 if ((result.low_bits() & 1) != 0) {
1355 result += 1;
1356 }
1357 } else {
1358 // Strictly less than half => round down
1359 }
1360 return result;
1361 }
1362
1363 template <typename Real>
1364 static Result<Decimal256> FromPositiveRealApprox(Real real, int32_t precision,

Callers

nothing calls this directly

Calls 2

little_endian_arrayMethod · 0.80
Decimal256Function · 0.70

Tested by

no test coverage detected