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

Method RoundedRightShift

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

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

Source from the content-addressed store, hash-verified

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