sql_utils/common/multiprecision_int_impl.cc (54 lines of code) (raw):
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sql_utils/common/multiprecision_int_impl.h"
#include <cstdint>
#include <string>
namespace bigquery_ml_utils {
namespace multiprecision_int_impl {
template <typename UnsignedWord, int kNumberDigits>
inline int PrintDigits(UnsignedWord digits, bool skip_leading_zeros,
char output[kNumberDigits]) {
for (int j = kNumberDigits - 1; j >= 0; --j) {
output[j] = static_cast<char>(digits % 10) + '0';
digits /= 10;
if (skip_leading_zeros && digits == 0) {
memmove(output, output + j, kNumberDigits - j);
return kNumberDigits - j;
}
}
return kNumberDigits;
}
template <typename UnsignedWord>
void AppendSegmentsToString(const UnsignedWord segments[], size_t num_segments,
std::string* result) {
if (num_segments == 0) {
result->push_back('0');
return;
}
size_t old_size = result->size();
constexpr UnsignedWord kBitWidth =
static_cast<UnsignedWord>(sizeof(UnsignedWord) * 8);
constexpr int kMaxWholeDecimalDigits =
IntTraits<kBitWidth>::kMaxWholeDecimalDigits;
size_t new_size = old_size + num_segments * kMaxWholeDecimalDigits;
result->resize(new_size);
char* output = result->data() + old_size;
const UnsignedWord* segment = &segments[num_segments - 1];
int num_digits_in_first_segment =
PrintDigits<UnsignedWord, kMaxWholeDecimalDigits>(
*segment, /* skip_leading_zeros */ true, output);
output += num_digits_in_first_segment;
while (segment != segments) {
--segment;
output += PrintDigits<UnsignedWord, kMaxWholeDecimalDigits>(
*segment, /* skip_leading_zeros */ false, output);
}
result->resize(new_size -
(kMaxWholeDecimalDigits - num_digits_in_first_segment));
}
template void AppendSegmentsToString<uint64_t>(const uint64_t segments[],
size_t num_segments,
std::string* result);
template void AppendSegmentsToString<uint32_t>(const uint32_t segments[],
size_t num_segments,
std::string* result);
} // namespace multiprecision_int_impl
} // namespace bigquery_ml_utils