Bei-z commented on a change in pull request #8542: URL: https://github.com/apache/arrow/pull/8542#discussion_r520841038
########## File path: cpp/src/arrow/util/basic_decimal.cc ########## @@ -490,49 +527,60 @@ static void FixDivisionSigns(BasicDecimal128* result, BasicDecimal128* remainder } } -/// \brief Build a BasicDecimal128 from a list of ints. +/// \brief Build a little endian array of uint64_t from a big endian array of uint32_t. +template <size_t N> +static DecimalStatus BuildFromArray(std::array<uint64_t, N>* result_array, + uint32_t* array, int64_t length) { + for (int64_t i = length - 2 * N - 1; i >= 0; i--) { + if (array[i] != 0) { + return DecimalStatus::kOverflow; + } + } + int64_t next_index = length - 1; + for (size_t i = 0; i < N; i++) { + uint64_t lower_bits = (next_index < 0) ? 0 : array[next_index--]; + (*result_array)[i] = + (next_index < 0) Review comment: Thank you for your suggestion! Changed this part of code to 2 loops, but there is a little performance regression. Is there anything I can improve on the current code to help with the performance, or should we consider change back to one loop? Current benchmark: BinaryMathOp128 156 ns 156 ns 4316716 items_per_second=64.2915M/s BinaryMathOp256 152 ns 152 ns 4426239 items_per_second=65.7017M/s ########## File path: cpp/src/arrow/util/basic_decimal.cc ########## @@ -490,49 +527,60 @@ static void FixDivisionSigns(BasicDecimal128* result, BasicDecimal128* remainder } } -/// \brief Build a BasicDecimal128 from a list of ints. +/// \brief Build a little endian array of uint64_t from a big endian array of uint32_t. +template <size_t N> +static DecimalStatus BuildFromArray(std::array<uint64_t, N>* result_array, + uint32_t* array, int64_t length) { + for (int64_t i = length - 2 * N - 1; i >= 0; i--) { + if (array[i] != 0) { + return DecimalStatus::kOverflow; + } + } + int64_t next_index = length - 1; + for (size_t i = 0; i < N; i++) { + uint64_t lower_bits = (next_index < 0) ? 0 : array[next_index--]; + (*result_array)[i] = + (next_index < 0) + ? lower_bits + : ((static_cast<uint64_t>(array[next_index--]) << 32) + lower_bits); + } + return DecimalStatus::kSuccess; +} + +/// \brief Build a BasicDecimal128 from a big endian array of uint32_t. static DecimalStatus BuildFromArray(BasicDecimal128* value, uint32_t* array, Review comment: Changed accordingly, thank you! ########## File path: cpp/src/arrow/util/basic_decimal.cc ########## @@ -490,49 +527,60 @@ static void FixDivisionSigns(BasicDecimal128* result, BasicDecimal128* remainder } } -/// \brief Build a BasicDecimal128 from a list of ints. +/// \brief Build a little endian array of uint64_t from a big endian array of uint32_t. +template <size_t N> +static DecimalStatus BuildFromArray(std::array<uint64_t, N>* result_array, + uint32_t* array, int64_t length) { + for (int64_t i = length - 2 * N - 1; i >= 0; i--) { + if (array[i] != 0) { + return DecimalStatus::kOverflow; + } + } + int64_t next_index = length - 1; + for (size_t i = 0; i < N; i++) { + uint64_t lower_bits = (next_index < 0) ? 0 : array[next_index--]; + (*result_array)[i] = + (next_index < 0) + ? lower_bits + : ((static_cast<uint64_t>(array[next_index--]) << 32) + lower_bits); + } + return DecimalStatus::kSuccess; +} + +/// \brief Build a BasicDecimal128 from a big endian array of uint32_t. static DecimalStatus BuildFromArray(BasicDecimal128* value, uint32_t* array, int64_t length) { - switch (length) { - case 0: - *value = {static_cast<int64_t>(0)}; - break; - case 1: - *value = {static_cast<int64_t>(array[0])}; - break; - case 2: - *value = {static_cast<int64_t>(0), - (static_cast<uint64_t>(array[0]) << 32) + array[1]}; - break; - case 3: - *value = {static_cast<int64_t>(array[0]), - (static_cast<uint64_t>(array[1]) << 32) + array[2]}; - break; - case 4: - *value = {(static_cast<int64_t>(array[0]) << 32) + array[1], - (static_cast<uint64_t>(array[2]) << 32) + array[3]}; - break; - case 5: - if (array[0] != 0) { - return DecimalStatus::kOverflow; - } - *value = {(static_cast<int64_t>(array[1]) << 32) + array[2], - (static_cast<uint64_t>(array[3]) << 32) + array[4]}; - break; - default: - return DecimalStatus::kOverflow; + std::array<uint64_t, 2> result_array; + auto status = BuildFromArray(&result_array, array, length); + if (status != DecimalStatus::kSuccess) { + return status; } + *value = {static_cast<int64_t>(result_array[1]), result_array[0]}; + return DecimalStatus::kSuccess; +} +/// \brief Build a BasicDecimal256 from a big endian array of uint32_t. +static DecimalStatus BuildFromArray(BasicDecimal256* value, uint32_t* array, Review comment: Changed accordingly, thank you! ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org