blob: 56809f28165b9fd8f23407b7b70d2502c13454f2 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 "arrow/util/basic_decimal.h"
#include <algorithm>
#include <array>
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <limits>
#include <string>
#include "arrow/util/bit_util.h"
#include "arrow/util/endian.h"
#include "arrow/util/int128_internal.h"
#include "arrow/util/int_util_internal.h"
#include "arrow/util/logging.h"
#include "arrow/util/macros.h"
namespace arrow {
using internal::SafeLeftShift;
using internal::SafeSignedAdd;
static const BasicDecimal128 ScaleMultipliers[] = {
BasicDecimal128(1LL),
BasicDecimal128(10LL),
BasicDecimal128(100LL),
BasicDecimal128(1000LL),
BasicDecimal128(10000LL),
BasicDecimal128(100000LL),
BasicDecimal128(1000000LL),
BasicDecimal128(10000000LL),
BasicDecimal128(100000000LL),
BasicDecimal128(1000000000LL),
BasicDecimal128(10000000000LL),
BasicDecimal128(100000000000LL),
BasicDecimal128(1000000000000LL),
BasicDecimal128(10000000000000LL),
BasicDecimal128(100000000000000LL),
BasicDecimal128(1000000000000000LL),
BasicDecimal128(10000000000000000LL),
BasicDecimal128(100000000000000000LL),
BasicDecimal128(1000000000000000000LL),
BasicDecimal128(0LL, 10000000000000000000ULL),
BasicDecimal128(5LL, 7766279631452241920ULL),
BasicDecimal128(54LL, 3875820019684212736ULL),
BasicDecimal128(542LL, 1864712049423024128ULL),
BasicDecimal128(5421LL, 200376420520689664ULL),
BasicDecimal128(54210LL, 2003764205206896640ULL),
BasicDecimal128(542101LL, 1590897978359414784ULL),
BasicDecimal128(5421010LL, 15908979783594147840ULL),
BasicDecimal128(54210108LL, 11515845246265065472ULL),
BasicDecimal128(542101086LL, 4477988020393345024ULL),
BasicDecimal128(5421010862LL, 7886392056514347008ULL),
BasicDecimal128(54210108624LL, 5076944270305263616ULL),
BasicDecimal128(542101086242LL, 13875954555633532928ULL),
BasicDecimal128(5421010862427LL, 9632337040368467968ULL),
BasicDecimal128(54210108624275LL, 4089650035136921600ULL),
BasicDecimal128(542101086242752LL, 4003012203950112768ULL),
BasicDecimal128(5421010862427522LL, 3136633892082024448ULL),
BasicDecimal128(54210108624275221LL, 12919594847110692864ULL),
BasicDecimal128(542101086242752217LL, 68739955140067328ULL),
BasicDecimal128(5421010862427522170LL, 687399551400673280ULL)};
static const BasicDecimal128 ScaleMultipliersHalf[] = {
BasicDecimal128(0ULL),
BasicDecimal128(5ULL),
BasicDecimal128(50ULL),
BasicDecimal128(500ULL),
BasicDecimal128(5000ULL),
BasicDecimal128(50000ULL),
BasicDecimal128(500000ULL),
BasicDecimal128(5000000ULL),
BasicDecimal128(50000000ULL),
BasicDecimal128(500000000ULL),
BasicDecimal128(5000000000ULL),
BasicDecimal128(50000000000ULL),
BasicDecimal128(500000000000ULL),
BasicDecimal128(5000000000000ULL),
BasicDecimal128(50000000000000ULL),
BasicDecimal128(500000000000000ULL),
BasicDecimal128(5000000000000000ULL),
BasicDecimal128(50000000000000000ULL),
BasicDecimal128(500000000000000000ULL),
BasicDecimal128(5000000000000000000ULL),
BasicDecimal128(2LL, 13106511852580896768ULL),
BasicDecimal128(27LL, 1937910009842106368ULL),
BasicDecimal128(271LL, 932356024711512064ULL),
BasicDecimal128(2710LL, 9323560247115120640ULL),
BasicDecimal128(27105LL, 1001882102603448320ULL),
BasicDecimal128(271050LL, 10018821026034483200ULL),
BasicDecimal128(2710505LL, 7954489891797073920ULL),
BasicDecimal128(27105054LL, 5757922623132532736ULL),
BasicDecimal128(271050543LL, 2238994010196672512ULL),
BasicDecimal128(2710505431LL, 3943196028257173504ULL),
BasicDecimal128(27105054312LL, 2538472135152631808ULL),
BasicDecimal128(271050543121LL, 6937977277816766464ULL),
BasicDecimal128(2710505431213LL, 14039540557039009792ULL),
BasicDecimal128(27105054312137LL, 11268197054423236608ULL),
BasicDecimal128(271050543121376LL, 2001506101975056384ULL),
BasicDecimal128(2710505431213761LL, 1568316946041012224ULL),
BasicDecimal128(27105054312137610LL, 15683169460410122240ULL),
BasicDecimal128(271050543121376108LL, 9257742014424809472ULL),
BasicDecimal128(2710505431213761085LL, 343699775700336640ULL)};
static const BasicDecimal256 ScaleMultipliersDecimal256[] = {
BasicDecimal256({1ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({10ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({100ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({1000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({10000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({100000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({1000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({10000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({100000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({1000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({10000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({100000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({1000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({10000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({100000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({1000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({10000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({100000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({1000000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({10000000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({7766279631452241920ULL, 5ULL, 0ULL, 0ULL}),
BasicDecimal256({3875820019684212736ULL, 54ULL, 0ULL, 0ULL}),
BasicDecimal256({1864712049423024128ULL, 542ULL, 0ULL, 0ULL}),
BasicDecimal256({200376420520689664ULL, 5421ULL, 0ULL, 0ULL}),
BasicDecimal256({2003764205206896640ULL, 54210ULL, 0ULL, 0ULL}),
BasicDecimal256({1590897978359414784ULL, 542101ULL, 0ULL, 0ULL}),
BasicDecimal256({15908979783594147840ULL, 5421010ULL, 0ULL, 0ULL}),
BasicDecimal256({11515845246265065472ULL, 54210108ULL, 0ULL, 0ULL}),
BasicDecimal256({4477988020393345024ULL, 542101086ULL, 0ULL, 0ULL}),
BasicDecimal256({7886392056514347008ULL, 5421010862ULL, 0ULL, 0ULL}),
BasicDecimal256({5076944270305263616ULL, 54210108624ULL, 0ULL, 0ULL}),
BasicDecimal256({13875954555633532928ULL, 542101086242ULL, 0ULL, 0ULL}),
BasicDecimal256({9632337040368467968ULL, 5421010862427ULL, 0ULL, 0ULL}),
BasicDecimal256({4089650035136921600ULL, 54210108624275ULL, 0ULL, 0ULL}),
BasicDecimal256({4003012203950112768ULL, 542101086242752ULL, 0ULL, 0ULL}),
BasicDecimal256({3136633892082024448ULL, 5421010862427522ULL, 0ULL, 0ULL}),
BasicDecimal256({12919594847110692864ULL, 54210108624275221ULL, 0ULL, 0ULL}),
BasicDecimal256({68739955140067328ULL, 542101086242752217ULL, 0ULL, 0ULL}),
BasicDecimal256({687399551400673280ULL, 5421010862427522170ULL, 0ULL, 0ULL}),
BasicDecimal256({6873995514006732800ULL, 17316620476856118468ULL, 2ULL, 0ULL}),
BasicDecimal256({13399722918938673152ULL, 7145508105175220139ULL, 29ULL, 0ULL}),
BasicDecimal256({4870020673419870208ULL, 16114848830623546549ULL, 293ULL, 0ULL}),
BasicDecimal256({11806718586779598848ULL, 13574535716559052564ULL, 2938ULL, 0ULL}),
BasicDecimal256({7386721425538678784ULL, 6618148649623664334ULL, 29387ULL, 0ULL}),
BasicDecimal256({80237960548581376ULL, 10841254275107988496ULL, 293873ULL, 0ULL}),
BasicDecimal256({802379605485813760ULL, 16178822382532126880ULL, 2938735ULL, 0ULL}),
BasicDecimal256({8023796054858137600ULL, 14214271235644855872ULL, 29387358ULL, 0ULL}),
BasicDecimal256(
{6450984253743169536ULL, 13015503840481697412ULL, 293873587ULL, 0ULL}),
BasicDecimal256(
{9169610316303040512ULL, 1027829888850112811ULL, 2938735877ULL, 0ULL}),
BasicDecimal256(
{17909126868192198656ULL, 10278298888501128114ULL, 29387358770ULL, 0ULL}),
BasicDecimal256(
{13070572018536022016ULL, 10549268516463523069ULL, 293873587705ULL, 0ULL}),
BasicDecimal256(
{1578511669393358848ULL, 13258964796087472617ULL, 2938735877055ULL, 0ULL}),
BasicDecimal256(
{15785116693933588480ULL, 3462439444907864858ULL, 29387358770557ULL, 0ULL}),
BasicDecimal256(
{10277214349659471872ULL, 16177650375369096972ULL, 293873587705571ULL, 0ULL}),
BasicDecimal256(
{10538423128046960640ULL, 14202551164014556797ULL, 2938735877055718ULL, 0ULL}),
BasicDecimal256(
{13150510911921848320ULL, 12898303124178706663ULL, 29387358770557187ULL, 0ULL}),
BasicDecimal256(
{2377900603251621888ULL, 18302566799529756941ULL, 293873587705571876ULL, 0ULL}),
BasicDecimal256(
{5332261958806667264ULL, 17004971331911604867ULL, 2938735877055718769ULL, 0ULL}),
BasicDecimal256(
{16429131440647569408ULL, 4029016655730084128ULL, 10940614696847636083ULL, 1ULL}),
BasicDecimal256({16717361816799281152ULL, 3396678409881738056ULL,
17172426599928602752ULL, 15ULL}),
BasicDecimal256({1152921504606846976ULL, 15520040025107828953ULL,
5703569335900062977ULL, 159ULL}),
BasicDecimal256({11529215046068469760ULL, 7626447661401876602ULL,
1695461137871974930ULL, 1593ULL}),
BasicDecimal256({4611686018427387904ULL, 2477500319180559562ULL,
16954611378719749304ULL, 15930ULL}),
BasicDecimal256({9223372036854775808ULL, 6328259118096044006ULL,
3525417123811528497ULL, 159309ULL}),
BasicDecimal256({0ULL, 7942358959831785217ULL, 16807427164405733357ULL, 1593091ULL}),
BasicDecimal256({0ULL, 5636613303479645706ULL, 2053574980671369030ULL, 15930919ULL}),
BasicDecimal256({0ULL, 1025900813667802212ULL, 2089005733004138687ULL, 159309191ULL}),
BasicDecimal256(
{0ULL, 10259008136678022120ULL, 2443313256331835254ULL, 1593091911ULL}),
BasicDecimal256(
{0ULL, 10356360998232463120ULL, 5986388489608800929ULL, 15930919111ULL}),
BasicDecimal256(
{0ULL, 11329889613776873120ULL, 4523652674959354447ULL, 159309191113ULL}),
BasicDecimal256(
{0ULL, 2618431695511421504ULL, 8343038602174441244ULL, 1593091911132ULL}),
BasicDecimal256(
{0ULL, 7737572881404663424ULL, 9643409726906205977ULL, 15930919111324ULL}),
BasicDecimal256(
{0ULL, 3588752519208427776ULL, 4200376900514301694ULL, 159309191113245ULL}),
BasicDecimal256(
{0ULL, 17440781118374726144ULL, 5110280857723913709ULL, 1593091911132452ULL}),
BasicDecimal256(
{0ULL, 8387114520361296896ULL, 14209320429820033867ULL, 15930919111324522ULL}),
BasicDecimal256(
{0ULL, 10084168908774762496ULL, 12965995782233477362ULL, 159309191113245227ULL}),
BasicDecimal256(
{0ULL, 8607968719199866880ULL, 532749306367912313ULL, 1593091911132452277ULL})};
static const BasicDecimal256 ScaleMultipliersHalfDecimal256[] = {
BasicDecimal256({0ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({5ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({50ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({500ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({5000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({50000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({500000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({5000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({50000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({500000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({5000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({50000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({500000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({5000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({50000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({500000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({5000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({50000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({500000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({5000000000000000000ULL, 0ULL, 0ULL, 0ULL}),
BasicDecimal256({13106511852580896768ULL, 2ULL, 0ULL, 0ULL}),
BasicDecimal256({1937910009842106368ULL, 27ULL, 0ULL, 0ULL}),
BasicDecimal256({932356024711512064ULL, 271ULL, 0ULL, 0ULL}),
BasicDecimal256({9323560247115120640ULL, 2710ULL, 0ULL, 0ULL}),
BasicDecimal256({1001882102603448320ULL, 27105ULL, 0ULL, 0ULL}),
BasicDecimal256({10018821026034483200ULL, 271050ULL, 0ULL, 0ULL}),
BasicDecimal256({7954489891797073920ULL, 2710505ULL, 0ULL, 0ULL}),
BasicDecimal256({5757922623132532736ULL, 27105054ULL, 0ULL, 0ULL}),
BasicDecimal256({2238994010196672512ULL, 271050543ULL, 0ULL, 0ULL}),
BasicDecimal256({3943196028257173504ULL, 2710505431ULL, 0ULL, 0ULL}),
BasicDecimal256({2538472135152631808ULL, 27105054312ULL, 0ULL, 0ULL}),
BasicDecimal256({6937977277816766464ULL, 271050543121ULL, 0ULL, 0ULL}),
BasicDecimal256({14039540557039009792ULL, 2710505431213ULL, 0ULL, 0ULL}),
BasicDecimal256({11268197054423236608ULL, 27105054312137ULL, 0ULL, 0ULL}),
BasicDecimal256({2001506101975056384ULL, 271050543121376ULL, 0ULL, 0ULL}),
BasicDecimal256({1568316946041012224ULL, 2710505431213761ULL, 0ULL, 0ULL}),
BasicDecimal256({15683169460410122240ULL, 27105054312137610ULL, 0ULL, 0ULL}),
BasicDecimal256({9257742014424809472ULL, 271050543121376108ULL, 0ULL, 0ULL}),
BasicDecimal256({343699775700336640ULL, 2710505431213761085ULL, 0ULL, 0ULL}),
BasicDecimal256({3436997757003366400ULL, 8658310238428059234ULL, 1ULL, 0ULL}),
BasicDecimal256({15923233496324112384ULL, 12796126089442385877ULL, 14ULL, 0ULL}),
BasicDecimal256({11658382373564710912ULL, 17280796452166549082ULL, 146ULL, 0ULL}),
BasicDecimal256({5903359293389799424ULL, 6787267858279526282ULL, 1469ULL, 0ULL}),
BasicDecimal256({3693360712769339392ULL, 12532446361666607975ULL, 14693ULL, 0ULL}),
BasicDecimal256({40118980274290688ULL, 14643999174408770056ULL, 146936ULL, 0ULL}),
BasicDecimal256({401189802742906880ULL, 17312783228120839248ULL, 1469367ULL, 0ULL}),
BasicDecimal256({4011898027429068800ULL, 7107135617822427936ULL, 14693679ULL, 0ULL}),
BasicDecimal256(
{3225492126871584768ULL, 15731123957095624514ULL, 146936793ULL, 0ULL}),
BasicDecimal256(
{13808177195006296064ULL, 9737286981279832213ULL, 1469367938ULL, 0ULL}),
BasicDecimal256(
{8954563434096099328ULL, 5139149444250564057ULL, 14693679385ULL, 0ULL}),
BasicDecimal256(
{15758658046122786816ULL, 14498006295086537342ULL, 146936793852ULL, 0ULL}),
BasicDecimal256(
{10012627871551455232ULL, 15852854434898512116ULL, 1469367938527ULL, 0ULL}),
BasicDecimal256(
{7892558346966794240ULL, 10954591759308708237ULL, 14693679385278ULL, 0ULL}),
BasicDecimal256(
{5138607174829735936ULL, 17312197224539324294ULL, 146936793852785ULL, 0ULL}),
BasicDecimal256(
{14492583600878256128ULL, 7101275582007278398ULL, 1469367938527859ULL, 0ULL}),
BasicDecimal256(
{15798627492815699968ULL, 15672523598944129139ULL, 14693679385278593ULL, 0ULL}),
BasicDecimal256(
{10412322338480586752ULL, 9151283399764878470ULL, 146936793852785938ULL, 0ULL}),
BasicDecimal256(
{11889503016258109440ULL, 17725857702810578241ULL, 1469367938527859384ULL, 0ULL}),
BasicDecimal256(
{8214565720323784704ULL, 11237880364719817872ULL, 14693679385278593849ULL, 0ULL}),
BasicDecimal256(
{8358680908399640576ULL, 1698339204940869028ULL, 17809585336819077184ULL, 7ULL}),
BasicDecimal256({9799832789158199296ULL, 16983392049408690284ULL,
12075156704804807296ULL, 79ULL}),
BasicDecimal256({5764607523034234880ULL, 3813223830700938301ULL,
10071102605790763273ULL, 796ULL}),
BasicDecimal256({2305843009213693952ULL, 1238750159590279781ULL,
8477305689359874652ULL, 7965ULL}),
BasicDecimal256({4611686018427387904ULL, 12387501595902797811ULL,
10986080598760540056ULL, 79654ULL}),
BasicDecimal256({9223372036854775808ULL, 13194551516770668416ULL,
17627085619057642486ULL, 796545ULL}),
BasicDecimal256({0ULL, 2818306651739822853ULL, 10250159527190460323ULL, 7965459ULL}),
BasicDecimal256({0ULL, 9736322443688676914ULL, 10267874903356845151ULL, 79654595ULL}),
BasicDecimal256(
{0ULL, 5129504068339011060ULL, 10445028665020693435ULL, 796545955ULL}),
BasicDecimal256(
{0ULL, 14401552535971007368ULL, 12216566281659176272ULL, 7965459555ULL}),
BasicDecimal256(
{0ULL, 14888316843743212368ULL, 11485198374334453031ULL, 79654595556ULL}),
BasicDecimal256(
{0ULL, 1309215847755710752ULL, 4171519301087220622ULL, 796545955566ULL}),
BasicDecimal256(
{0ULL, 13092158477557107520ULL, 4821704863453102988ULL, 7965459555662ULL}),
BasicDecimal256(
{0ULL, 1794376259604213888ULL, 11323560487111926655ULL, 79654595556622ULL}),
BasicDecimal256(
{0ULL, 17943762596042138880ULL, 2555140428861956854ULL, 796545955566226ULL}),
BasicDecimal256(
{0ULL, 13416929297035424256ULL, 7104660214910016933ULL, 7965459555662261ULL}),
BasicDecimal256(
{0ULL, 5042084454387381248ULL, 15706369927971514489ULL, 79654595556622613ULL}),
BasicDecimal256(
{0ULL, 13527356396454709248ULL, 9489746690038731964ULL, 796545955566226138ULL})};
#ifdef ARROW_USE_NATIVE_INT128
static constexpr uint64_t kInt64Mask = 0xFFFFFFFFFFFFFFFF;
#else
static constexpr uint64_t kInt32Mask = 0xFFFFFFFF;
#endif
// same as ScaleMultipliers[38] - 1
static constexpr BasicDecimal128 kMaxValue =
BasicDecimal128(5421010862427522170LL, 687399551400673280ULL - 1);
#if ARROW_LITTLE_ENDIAN
BasicDecimal128::BasicDecimal128(const uint8_t* bytes)
: BasicDecimal128(reinterpret_cast<const int64_t*>(bytes)[1],
reinterpret_cast<const uint64_t*>(bytes)[0]) {}
#else
BasicDecimal128::BasicDecimal128(const uint8_t* bytes)
: BasicDecimal128(reinterpret_cast<const int64_t*>(bytes)[0],
reinterpret_cast<const uint64_t*>(bytes)[1]) {}
#endif
std::array<uint8_t, 16> BasicDecimal128::ToBytes() const {
std::array<uint8_t, 16> out{{0}};
ToBytes(out.data());
return out;
}
void BasicDecimal128::ToBytes(uint8_t* out) const {
DCHECK_NE(out, nullptr);
#if ARROW_LITTLE_ENDIAN
reinterpret_cast<uint64_t*>(out)[0] = low_bits_;
reinterpret_cast<int64_t*>(out)[1] = high_bits_;
#else
reinterpret_cast<int64_t*>(out)[0] = high_bits_;
reinterpret_cast<uint64_t*>(out)[1] = low_bits_;
#endif
}
BasicDecimal128& BasicDecimal128::Negate() {
low_bits_ = ~low_bits_ + 1;
high_bits_ = ~high_bits_;
if (low_bits_ == 0) {
high_bits_ = SafeSignedAdd<int64_t>(high_bits_, 1);
}
return *this;
}
BasicDecimal128& BasicDecimal128::Abs() { return *this < 0 ? Negate() : *this; }
BasicDecimal128 BasicDecimal128::Abs(const BasicDecimal128& in) {
BasicDecimal128 result(in);
return result.Abs();
}
bool BasicDecimal128::FitsInPrecision(int32_t precision) const {
DCHECK_GT(precision, 0);
DCHECK_LE(precision, 38);
return BasicDecimal128::Abs(*this) < ScaleMultipliers[precision];
}
BasicDecimal128& BasicDecimal128::operator+=(const BasicDecimal128& right) {
const uint64_t sum = low_bits_ + right.low_bits_;
high_bits_ = SafeSignedAdd<int64_t>(high_bits_, right.high_bits_);
if (sum < low_bits_) {
high_bits_ = SafeSignedAdd<int64_t>(high_bits_, 1);
}
low_bits_ = sum;
return *this;
}
BasicDecimal128& BasicDecimal128::operator-=(const BasicDecimal128& right) {
const uint64_t diff = low_bits_ - right.low_bits_;
high_bits_ -= right.high_bits_;
if (diff > low_bits_) {
--high_bits_;
}
low_bits_ = diff;
return *this;
}
BasicDecimal128& BasicDecimal128::operator/=(const BasicDecimal128& right) {
BasicDecimal128 remainder;
auto s = Divide(right, this, &remainder);
DCHECK_EQ(s, DecimalStatus::kSuccess);
return *this;
}
BasicDecimal128& BasicDecimal128::operator|=(const BasicDecimal128& right) {
low_bits_ |= right.low_bits_;
high_bits_ |= right.high_bits_;
return *this;
}
BasicDecimal128& BasicDecimal128::operator&=(const BasicDecimal128& right) {
low_bits_ &= right.low_bits_;
high_bits_ &= right.high_bits_;
return *this;
}
BasicDecimal128& BasicDecimal128::operator<<=(uint32_t bits) {
if (bits != 0) {
if (bits < 64) {
high_bits_ = SafeLeftShift(high_bits_, bits);
high_bits_ |= (low_bits_ >> (64 - bits));
low_bits_ <<= bits;
} else if (bits < 128) {
high_bits_ = static_cast<int64_t>(low_bits_) << (bits - 64);
low_bits_ = 0;
} else {
high_bits_ = 0;
low_bits_ = 0;
}
}
return *this;
}
BasicDecimal128& BasicDecimal128::operator>>=(uint32_t bits) {
if (bits != 0) {
if (bits < 64) {
low_bits_ >>= bits;
low_bits_ |= static_cast<uint64_t>(high_bits_ << (64 - bits));
high_bits_ = static_cast<int64_t>(static_cast<uint64_t>(high_bits_) >> bits);
} else if (bits < 128) {
low_bits_ = static_cast<uint64_t>(high_bits_ >> (bits - 64));
high_bits_ = static_cast<int64_t>(high_bits_ >= 0L ? 0L : -1L);
} else {
high_bits_ = static_cast<int64_t>(high_bits_ >= 0L ? 0L : -1L);
low_bits_ = static_cast<uint64_t>(high_bits_);
}
}
return *this;
}
namespace {
// Convenience wrapper type over 128 bit unsigned integers. We opt not to
// replace the uint128_t type in int128_internal.h because it would require
// significantly more implementation work to be done. This class merely
// provides the minimum necessary set of functions to perform 128+ bit
// multiplication operations when there may or may not be native support.
#ifdef ARROW_USE_NATIVE_INT128
struct uint128_t {
uint128_t() {}
uint128_t(uint64_t hi, uint64_t lo) : val_((static_cast<__uint128_t>(hi) << 64) | lo) {}
explicit uint128_t(const BasicDecimal128& decimal) {
val_ = (static_cast<__uint128_t>(decimal.high_bits()) << 64) | decimal.low_bits();
}
explicit uint128_t(uint64_t value) : val_(value) {}
uint64_t hi() { return val_ >> 64; }
uint64_t lo() { return val_ & kInt64Mask; }
uint128_t& operator+=(const uint128_t& other) {
val_ += other.val_;
return *this;
}
uint128_t& operator*=(const uint128_t& other) {
val_ *= other.val_;
return *this;
}
__uint128_t val_;
};
#else
// Multiply two 64 bit word components into a 128 bit result, with high bits
// stored in hi and low bits in lo.
inline void ExtendAndMultiply(uint64_t x, uint64_t y, uint64_t* hi, uint64_t* lo) {
// Perform multiplication on two 64 bit words x and y into a 128 bit result
// by splitting up x and y into 32 bit high/low bit components,
// allowing us to represent the multiplication as
// x * y = x_lo * y_lo + x_hi * y_lo * 2^32 + y_hi * x_lo * 2^32
// + x_hi * y_hi * 2^64
//
// Now, consider the final output as lo_lo || lo_hi || hi_lo || hi_hi
// Therefore,
// lo_lo is (x_lo * y_lo)_lo,
// lo_hi is ((x_lo * y_lo)_hi + (x_hi * y_lo)_lo + (x_lo * y_hi)_lo)_lo,
// hi_lo is ((x_hi * y_hi)_lo + (x_hi * y_lo)_hi + (x_lo * y_hi)_hi)_hi,
// hi_hi is (x_hi * y_hi)_hi
const uint64_t x_lo = x & kInt32Mask;
const uint64_t y_lo = y & kInt32Mask;
const uint64_t x_hi = x >> 32;
const uint64_t y_hi = y >> 32;
const uint64_t t = x_lo * y_lo;
const uint64_t t_lo = t & kInt32Mask;
const uint64_t t_hi = t >> 32;
const uint64_t u = x_hi * y_lo + t_hi;
const uint64_t u_lo = u & kInt32Mask;
const uint64_t u_hi = u >> 32;
const uint64_t v = x_lo * y_hi + u_lo;
const uint64_t v_hi = v >> 32;
*hi = x_hi * y_hi + u_hi + v_hi;
*lo = (v << 32) + t_lo;
}
struct uint128_t {
uint128_t() {}
uint128_t(uint64_t hi, uint64_t lo) : hi_(hi), lo_(lo) {}
explicit uint128_t(const BasicDecimal128& decimal) {
hi_ = decimal.high_bits();
lo_ = decimal.low_bits();
}
uint64_t hi() const { return hi_; }
uint64_t lo() const { return lo_; }
uint128_t& operator+=(const uint128_t& other) {
// To deduce the carry bit, we perform "65 bit" addition on the low bits and
// seeing if the resulting high bit is 1. This is accomplished by shifting the
// low bits to the right by 1 (chopping off the lowest bit), then adding 1 if the
// result of adding the two chopped bits would have produced a carry.
uint64_t carry = (((lo_ & other.lo_) & 1) + (lo_ >> 1) + (other.lo_ >> 1)) >> 63;
hi_ += other.hi_ + carry;
lo_ += other.lo_;
return *this;
}
uint128_t& operator*=(const uint128_t& other) {
uint128_t r;
ExtendAndMultiply(lo_, other.lo_, &r.hi_, &r.lo_);
r.hi_ += (hi_ * other.lo_) + (lo_ * other.hi_);
*this = r;
return *this;
}
uint64_t hi_;
uint64_t lo_;
};
#endif
// Multiplies two N * 64 bit unsigned integer types, represented by a uint64_t
// array into a same sized output. Elements in the array should be in
// little endian order, and output will be the same. Overflow in multiplication
// will result in the lower N * 64 bits of the result being set.
template <int N>
inline void MultiplyUnsignedArray(const std::array<uint64_t, N>& lh,
const std::array<uint64_t, N>& rh,
std::array<uint64_t, N>* result) {
for (int j = 0; j < N; ++j) {
uint64_t carry = 0;
for (int i = 0; i < N - j; ++i) {
uint128_t tmp(lh[i]);
tmp *= uint128_t(rh[j]);
tmp += uint128_t((*result)[i + j]);
tmp += uint128_t(carry);
(*result)[i + j] = tmp.lo();
carry = tmp.hi();
}
}
}
} // namespace
BasicDecimal128& BasicDecimal128::operator*=(const BasicDecimal128& right) {
// Since the max value of BasicDecimal128 is supposed to be 1e38 - 1 and the
// min the negation taking the absolute values here should always be safe.
const bool negate = Sign() != right.Sign();
BasicDecimal128 x = BasicDecimal128::Abs(*this);
BasicDecimal128 y = BasicDecimal128::Abs(right);
uint128_t r(x);
r *= uint128_t{y};
high_bits_ = r.hi();
low_bits_ = r.lo();
if (negate) {
Negate();
}
return *this;
}
/// Expands the given little endian array of uint64_t into a big endian array of
/// uint32_t. The value of input array is expected to be non-negative. The result_array
/// will remove leading zeros from the input array.
/// \param value_array a little endian array to represent the value
/// \param result_array a big endian array of length N*2 to set with the value
/// \result the output length of the array
template <size_t N>
static int64_t FillInArray(const std::array<uint64_t, N>& value_array,
uint32_t* result_array) {
int64_t next_index = 0;
// 1st loop to find out 1st non-negative value in input
int64_t i = N - 1;
for (; i >= 0; i--) {
if (value_array[i] != 0) {
if (value_array[i] <= std::numeric_limits<uint32_t>::max()) {
result_array[next_index++] = static_cast<uint32_t>(value_array[i]);
i--;
}
break;
}
}
// 2nd loop to fill in the rest of the array.
for (int64_t j = i; j >= 0; j--) {
result_array[next_index++] = static_cast<uint32_t>(value_array[j] >> 32);
result_array[next_index++] = static_cast<uint32_t>(value_array[j]);
}
return next_index;
}
/// Expands the given value into a big endian array of ints so that we can work on
/// it. The array will be converted to an absolute value and the was_negative
/// flag will be set appropriately. The array will remove leading zeros from
/// the value.
/// \param array a big endian array of length 4 to set with the value
/// \param was_negative a flag for whether the value was original negative
/// \result the output length of the array
static int64_t FillInArray(const BasicDecimal128& value, uint32_t* array,
bool& was_negative) {
BasicDecimal128 abs_value = BasicDecimal128::Abs(value);
was_negative = value.high_bits() < 0;
uint64_t high = static_cast<uint64_t>(abs_value.high_bits());
uint64_t low = abs_value.low_bits();
// FillInArray(std::array<uint64_t, N>& value_array, uint32_t* result_array) is not
// called here as the following code has better performance, to avoid regression on
// BasicDecimal128 Division.
if (high != 0) {
if (high > std::numeric_limits<uint32_t>::max()) {
array[0] = static_cast<uint32_t>(high >> 32);
array[1] = static_cast<uint32_t>(high);
array[2] = static_cast<uint32_t>(low >> 32);
array[3] = static_cast<uint32_t>(low);
return 4;
}
array[0] = static_cast<uint32_t>(high);
array[1] = static_cast<uint32_t>(low >> 32);
array[2] = static_cast<uint32_t>(low);
return 3;
}
if (low > std::numeric_limits<uint32_t>::max()) {
array[0] = static_cast<uint32_t>(low >> 32);
array[1] = static_cast<uint32_t>(low);
return 2;
}
if (low == 0) {
return 0;
}
array[0] = static_cast<uint32_t>(low);
return 1;
}
/// Expands the given value into a big endian array of ints so that we can work on
/// it. The array will be converted to an absolute value and the was_negative
/// flag will be set appropriately. The array will remove leading zeros from
/// the value.
/// \param array a big endian array of length 8 to set with the value
/// \param was_negative a flag for whether the value was original negative
/// \result the output length of the array
static int64_t FillInArray(const BasicDecimal256& value, uint32_t* array,
bool& was_negative) {
BasicDecimal256 positive_value = value;
was_negative = false;
if (positive_value.IsNegative()) {
positive_value.Negate();
was_negative = true;
}
return FillInArray<4>(positive_value.little_endian_array(), array);
}
/// Shift the number in the array left by bits positions.
/// \param array the number to shift, must have length elements
/// \param length the number of entries in the array
/// \param bits the number of bits to shift (0 <= bits < 32)
static void ShiftArrayLeft(uint32_t* array, int64_t length, int64_t bits) {
if (length > 0 && bits != 0) {
for (int64_t i = 0; i < length - 1; ++i) {
array[i] = (array[i] << bits) | (array[i + 1] >> (32 - bits));
}
array[length - 1] <<= bits;
}
}
/// Shift the number in the array right by bits positions.
/// \param array the number to shift, must have length elements
/// \param length the number of entries in the array
/// \param bits the number of bits to shift (0 <= bits < 32)
static inline void ShiftArrayRight(uint32_t* array, int64_t length, int64_t bits) {
if (length > 0 && bits != 0) {
for (int64_t i = length - 1; i > 0; --i) {
array[i] = (array[i] >> bits) | (array[i - 1] << (32 - bits));
}
array[0] >>= bits;
}
}
/// \brief Fix the signs of the result and remainder at the end of the division based on
/// the signs of the dividend and divisor.
template <class DecimalClass>
static inline void FixDivisionSigns(DecimalClass* result, DecimalClass* remainder,
bool dividend_was_negative,
bool divisor_was_negative) {
if (dividend_was_negative != divisor_was_negative) {
result->Negate();
}
if (dividend_was_negative) {
remainder->Negate();
}
}
/// \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,
const 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;
size_t i = 0;
for (; i < N && next_index >= 0; i++) {
uint64_t lower_bits = array[next_index--];
(*result_array)[i] =
(next_index < 0)
? lower_bits
: ((static_cast<uint64_t>(array[next_index--]) << 32) + lower_bits);
}
for (; i < N; i++) {
(*result_array)[i] = 0;
}
return DecimalStatus::kSuccess;
}
/// \brief Build a BasicDecimal128 from a big endian array of uint32_t.
static DecimalStatus BuildFromArray(BasicDecimal128* value, const uint32_t* array,
int64_t length) {
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, const uint32_t* array,
int64_t length) {
std::array<uint64_t, 4> result_array;
auto status = BuildFromArray(&result_array, array, length);
if (status != DecimalStatus::kSuccess) {
return status;
}
*value = result_array;
return DecimalStatus::kSuccess;
}
/// \brief Do a division where the divisor fits into a single 32 bit value.
template <class DecimalClass>
static inline DecimalStatus SingleDivide(const uint32_t* dividend,
int64_t dividend_length, uint32_t divisor,
DecimalClass* remainder,
bool dividend_was_negative,
bool divisor_was_negative,
DecimalClass* result) {
uint64_t r = 0;
constexpr int64_t kDecimalArrayLength = DecimalClass::bit_width / sizeof(uint32_t) + 1;
uint32_t result_array[kDecimalArrayLength];
for (int64_t j = 0; j < dividend_length; j++) {
r <<= 32;
r += dividend[j];
result_array[j] = static_cast<uint32_t>(r / divisor);
r %= divisor;
}
auto status = BuildFromArray(result, result_array, dividend_length);
if (status != DecimalStatus::kSuccess) {
return status;
}
*remainder = static_cast<int64_t>(r);
FixDivisionSigns(result, remainder, dividend_was_negative, divisor_was_negative);
return DecimalStatus::kSuccess;
}
/// \brief Do a decimal division with remainder.
template <class DecimalClass>
static inline DecimalStatus DecimalDivide(const DecimalClass& dividend,
const DecimalClass& divisor,
DecimalClass* result, DecimalClass* remainder) {
constexpr int64_t kDecimalArrayLength = DecimalClass::bit_width / sizeof(uint32_t);
// Split the dividend and divisor into integer pieces so that we can
// work on them.
uint32_t dividend_array[kDecimalArrayLength + 1];
uint32_t divisor_array[kDecimalArrayLength];
bool dividend_was_negative;
bool divisor_was_negative;
// leave an extra zero before the dividend
dividend_array[0] = 0;
int64_t dividend_length =
FillInArray(dividend, dividend_array + 1, dividend_was_negative) + 1;
int64_t divisor_length = FillInArray(divisor, divisor_array, divisor_was_negative);
// Handle some of the easy cases.
if (dividend_length <= divisor_length) {
*remainder = dividend;
*result = 0;
return DecimalStatus::kSuccess;
}
if (divisor_length == 0) {
return DecimalStatus::kDivideByZero;
}
if (divisor_length == 1) {
return SingleDivide(dividend_array, dividend_length, divisor_array[0], remainder,
dividend_was_negative, divisor_was_negative, result);
}
int64_t result_length = dividend_length - divisor_length;
uint32_t result_array[kDecimalArrayLength];
DCHECK_LE(result_length, kDecimalArrayLength);
// Normalize by shifting both by a multiple of 2 so that
// the digit guessing is better. The requirement is that
// divisor_array[0] is greater than 2**31.
int64_t normalize_bits = BitUtil::CountLeadingZeros(divisor_array[0]);
ShiftArrayLeft(divisor_array, divisor_length, normalize_bits);
ShiftArrayLeft(dividend_array, dividend_length, normalize_bits);
// compute each digit in the result
for (int64_t j = 0; j < result_length; ++j) {
// Guess the next digit. At worst it is two too large
uint32_t guess = std::numeric_limits<uint32_t>::max();
const auto high_dividend =
static_cast<uint64_t>(dividend_array[j]) << 32 | dividend_array[j + 1];
if (dividend_array[j] != divisor_array[0]) {
guess = static_cast<uint32_t>(high_dividend / divisor_array[0]);
}
// catch all of the cases where guess is two too large and most of the
// cases where it is one too large
auto rhat = static_cast<uint32_t>(high_dividend -
guess * static_cast<uint64_t>(divisor_array[0]));
while (static_cast<uint64_t>(divisor_array[1]) * guess >
(static_cast<uint64_t>(rhat) << 32) + dividend_array[j + 2]) {
--guess;
rhat += divisor_array[0];
if (static_cast<uint64_t>(rhat) < divisor_array[0]) {
break;
}
}
// subtract off the guess * divisor from the dividend
uint64_t mult = 0;
for (int64_t i = divisor_length - 1; i >= 0; --i) {
mult += static_cast<uint64_t>(guess) * divisor_array[i];
uint32_t prev = dividend_array[j + i + 1];
dividend_array[j + i + 1] -= static_cast<uint32_t>(mult);
mult >>= 32;
if (dividend_array[j + i + 1] > prev) {
++mult;
}
}
uint32_t prev = dividend_array[j];
dividend_array[j] -= static_cast<uint32_t>(mult);
// if guess was too big, we add back divisor
if (dividend_array[j] > prev) {
--guess;
uint32_t carry = 0;
for (int64_t i = divisor_length - 1; i >= 0; --i) {
const auto sum =
static_cast<uint64_t>(divisor_array[i]) + dividend_array[j + i + 1] + carry;
dividend_array[j + i + 1] = static_cast<uint32_t>(sum);
carry = static_cast<uint32_t>(sum >> 32);
}
dividend_array[j] += carry;
}
result_array[j] = guess;
}
// denormalize the remainder
ShiftArrayRight(dividend_array, dividend_length, normalize_bits);
// return result and remainder
auto status = BuildFromArray(result, result_array, result_length);
if (status != DecimalStatus::kSuccess) {
return status;
}
status = BuildFromArray(remainder, dividend_array, dividend_length);
if (status != DecimalStatus::kSuccess) {
return status;
}
FixDivisionSigns(result, remainder, dividend_was_negative, divisor_was_negative);
return DecimalStatus::kSuccess;
}
DecimalStatus BasicDecimal128::Divide(const BasicDecimal128& divisor,
BasicDecimal128* result,
BasicDecimal128* remainder) const {
return DecimalDivide(*this, divisor, result, remainder);
}
bool operator==(const BasicDecimal128& left, const BasicDecimal128& right) {
return left.high_bits() == right.high_bits() && left.low_bits() == right.low_bits();
}
bool operator!=(const BasicDecimal128& left, const BasicDecimal128& right) {
return !operator==(left, right);
}
bool operator<(const BasicDecimal128& left, const BasicDecimal128& right) {
return left.high_bits() < right.high_bits() ||
(left.high_bits() == right.high_bits() && left.low_bits() < right.low_bits());
}
bool operator<=(const BasicDecimal128& left, const BasicDecimal128& right) {
return !operator>(left, right);
}
bool operator>(const BasicDecimal128& left, const BasicDecimal128& right) {
return operator<(right, left);
}
bool operator>=(const BasicDecimal128& left, const BasicDecimal128& right) {
return !operator<(left, right);
}
BasicDecimal128 operator-(const BasicDecimal128& operand) {
BasicDecimal128 result(operand.high_bits(), operand.low_bits());
return result.Negate();
}
BasicDecimal128 operator~(const BasicDecimal128& operand) {
BasicDecimal128 result(~operand.high_bits(), ~operand.low_bits());
return result;
}
BasicDecimal128 operator+(const BasicDecimal128& left, const BasicDecimal128& right) {
BasicDecimal128 result(left.high_bits(), left.low_bits());
result += right;
return result;
}
BasicDecimal128 operator-(const BasicDecimal128& left, const BasicDecimal128& right) {
BasicDecimal128 result(left.high_bits(), left.low_bits());
result -= right;
return result;
}
BasicDecimal128 operator*(const BasicDecimal128& left, const BasicDecimal128& right) {
BasicDecimal128 result(left.high_bits(), left.low_bits());
result *= right;
return result;
}
BasicDecimal128 operator/(const BasicDecimal128& left, const BasicDecimal128& right) {
BasicDecimal128 remainder;
BasicDecimal128 result;
auto s = left.Divide(right, &result, &remainder);
DCHECK_EQ(s, DecimalStatus::kSuccess);
return result;
}
BasicDecimal128 operator%(const BasicDecimal128& left, const BasicDecimal128& right) {
BasicDecimal128 remainder;
BasicDecimal128 result;
auto s = left.Divide(right, &result, &remainder);
DCHECK_EQ(s, DecimalStatus::kSuccess);
return remainder;
}
template <class DecimalClass>
static bool RescaleWouldCauseDataLoss(const DecimalClass& value, int32_t delta_scale,
const DecimalClass& multiplier,
DecimalClass* result) {
if (delta_scale < 0) {
DCHECK_NE(multiplier, 0);
DecimalClass remainder;
auto status = value.Divide(multiplier, result, &remainder);
DCHECK_EQ(status, DecimalStatus::kSuccess);
return remainder != 0;
}
*result = value * multiplier;
return (value < 0) ? *result > value : *result < value;
}
template <class DecimalClass>
DecimalStatus DecimalRescale(const DecimalClass& value, int32_t original_scale,
int32_t new_scale, DecimalClass* out) {
DCHECK_NE(out, nullptr);
if (original_scale == new_scale) {
*out = value;
return DecimalStatus::kSuccess;
}
const int32_t delta_scale = new_scale - original_scale;
const int32_t abs_delta_scale = std::abs(delta_scale);
DecimalClass multiplier = DecimalClass::GetScaleMultiplier(abs_delta_scale);
const bool rescale_would_cause_data_loss =
RescaleWouldCauseDataLoss(value, delta_scale, multiplier, out);
// Fail if we overflow or truncate
if (ARROW_PREDICT_FALSE(rescale_would_cause_data_loss)) {
return DecimalStatus::kRescaleDataLoss;
}
return DecimalStatus::kSuccess;
}
DecimalStatus BasicDecimal128::Rescale(int32_t original_scale, int32_t new_scale,
BasicDecimal128* out) const {
return DecimalRescale(*this, original_scale, new_scale, out);
}
void BasicDecimal128::GetWholeAndFraction(int scale, BasicDecimal128* whole,
BasicDecimal128* fraction) const {
DCHECK_GE(scale, 0);
DCHECK_LE(scale, 38);
BasicDecimal128 multiplier(ScaleMultipliers[scale]);
auto s = Divide(multiplier, whole, fraction);
DCHECK_EQ(s, DecimalStatus::kSuccess);
}
const BasicDecimal128& BasicDecimal128::GetScaleMultiplier(int32_t scale) {
DCHECK_GE(scale, 0);
DCHECK_LE(scale, 38);
return ScaleMultipliers[scale];
}
const BasicDecimal128& BasicDecimal128::GetMaxValue() { return kMaxValue; }
BasicDecimal128 BasicDecimal128::IncreaseScaleBy(int32_t increase_by) const {
DCHECK_GE(increase_by, 0);
DCHECK_LE(increase_by, 38);
return (*this) * ScaleMultipliers[increase_by];
}
BasicDecimal128 BasicDecimal128::ReduceScaleBy(int32_t reduce_by, bool round) const {
DCHECK_GE(reduce_by, 0);
DCHECK_LE(reduce_by, 38);
if (reduce_by == 0) {
return *this;
}
BasicDecimal128 divisor(ScaleMultipliers[reduce_by]);
BasicDecimal128 result;
BasicDecimal128 remainder;
auto s = Divide(divisor, &result, &remainder);
DCHECK_EQ(s, DecimalStatus::kSuccess);
if (round) {
auto divisor_half = ScaleMultipliersHalf[reduce_by];
if (remainder.Abs() >= divisor_half) {
if (result > 0) {
result += 1;
} else {
result -= 1;
}
}
}
return result;
}
int32_t BasicDecimal128::CountLeadingBinaryZeros() const {
DCHECK_GE(*this, BasicDecimal128(0));
if (high_bits_ == 0) {
return BitUtil::CountLeadingZeros(low_bits_) + 64;
} else {
return BitUtil::CountLeadingZeros(static_cast<uint64_t>(high_bits_));
}
}
#if ARROW_LITTLE_ENDIAN
BasicDecimal256::BasicDecimal256(const uint8_t* bytes)
: little_endian_array_(
std::array<uint64_t, 4>({reinterpret_cast<const uint64_t*>(bytes)[0],
reinterpret_cast<const uint64_t*>(bytes)[1],
reinterpret_cast<const uint64_t*>(bytes)[2],
reinterpret_cast<const uint64_t*>(bytes)[3]})) {}
#else
BasicDecimal256::BasicDecimal256(const uint8_t* bytes)
: little_endian_array_(
std::array<uint64_t, 4>({reinterpret_cast<const uint64_t*>(bytes)[3],
reinterpret_cast<const uint64_t*>(bytes)[2],
reinterpret_cast<const uint64_t*>(bytes)[1],
reinterpret_cast<const uint64_t*>(bytes)[0]})) {}
#endif
BasicDecimal256& BasicDecimal256::Negate() {
uint64_t carry = 1;
for (uint64_t& elem : little_endian_array_) {
elem = ~elem + carry;
carry &= (elem == 0);
}
return *this;
}
BasicDecimal256& BasicDecimal256::Abs() { return *this < 0 ? Negate() : *this; }
BasicDecimal256 BasicDecimal256::Abs(const BasicDecimal256& in) {
BasicDecimal256 result(in);
return result.Abs();
}
BasicDecimal256& BasicDecimal256::operator+=(const BasicDecimal256& right) {
uint64_t carry = 0;
for (size_t i = 0; i < little_endian_array_.size(); i++) {
const uint64_t right_value = right.little_endian_array_[i];
uint64_t sum = right_value + carry;
carry = 0;
if (sum < right_value) {
carry += 1;
}
sum += little_endian_array_[i];
if (sum < little_endian_array_[i]) {
carry += 1;
}
little_endian_array_[i] = sum;
}
return *this;
}
BasicDecimal256& BasicDecimal256::operator-=(const BasicDecimal256& right) {
*this += -right;
return *this;
}
BasicDecimal256& BasicDecimal256::operator<<=(uint32_t bits) {
if (bits == 0) {
return *this;
}
int cross_word_shift = bits / 64;
if (static_cast<size_t>(cross_word_shift) >= little_endian_array_.size()) {
little_endian_array_ = {0, 0, 0, 0};
return *this;
}
uint32_t in_word_shift = bits % 64;
for (int i = static_cast<int>(little_endian_array_.size() - 1); i >= cross_word_shift;
i--) {
// Account for shifts larger then 64 bits
little_endian_array_[i] = little_endian_array_[i - cross_word_shift];
little_endian_array_[i] <<= in_word_shift;
if (in_word_shift != 0 && i >= cross_word_shift + 1) {
little_endian_array_[i] |=
little_endian_array_[i - (cross_word_shift + 1)] >> (64 - in_word_shift);
}
}
for (int i = cross_word_shift - 1; i >= 0; i--) {
little_endian_array_[i] = 0;
}
return *this;
}
std::array<uint8_t, 32> BasicDecimal256::ToBytes() const {
std::array<uint8_t, 32> out{{0}};
ToBytes(out.data());
return out;
}
void BasicDecimal256::ToBytes(uint8_t* out) const {
DCHECK_NE(out, nullptr);
#if ARROW_LITTLE_ENDIAN
reinterpret_cast<int64_t*>(out)[0] = little_endian_array_[0];
reinterpret_cast<int64_t*>(out)[1] = little_endian_array_[1];
reinterpret_cast<int64_t*>(out)[2] = little_endian_array_[2];
reinterpret_cast<int64_t*>(out)[3] = little_endian_array_[3];
#else
reinterpret_cast<int64_t*>(out)[0] = little_endian_array_[3];
reinterpret_cast<int64_t*>(out)[1] = little_endian_array_[2];
reinterpret_cast<int64_t*>(out)[2] = little_endian_array_[1];
reinterpret_cast<int64_t*>(out)[3] = little_endian_array_[0];
#endif
}
BasicDecimal256& BasicDecimal256::operator*=(const BasicDecimal256& right) {
// Since the max value of BasicDecimal256 is supposed to be 1e76 - 1 and the
// min the negation taking the absolute values here should always be safe.
const bool negate = Sign() != right.Sign();
BasicDecimal256 x = BasicDecimal256::Abs(*this);
BasicDecimal256 y = BasicDecimal256::Abs(right);
uint128_t r_hi;
uint128_t r_lo;
std::array<uint64_t, 4> res{0, 0, 0, 0};
MultiplyUnsignedArray<4>(x.little_endian_array_, y.little_endian_array_, &res);
little_endian_array_ = res;
if (negate) {
Negate();
}
return *this;
}
DecimalStatus BasicDecimal256::Divide(const BasicDecimal256& divisor,
BasicDecimal256* result,
BasicDecimal256* remainder) const {
return DecimalDivide(*this, divisor, result, remainder);
}
DecimalStatus BasicDecimal256::Rescale(int32_t original_scale, int32_t new_scale,
BasicDecimal256* out) const {
return DecimalRescale(*this, original_scale, new_scale, out);
}
BasicDecimal256 BasicDecimal256::IncreaseScaleBy(int32_t increase_by) const {
DCHECK_GE(increase_by, 0);
DCHECK_LE(increase_by, 76);
return (*this) * ScaleMultipliersDecimal256[increase_by];
}
BasicDecimal256 BasicDecimal256::ReduceScaleBy(int32_t reduce_by, bool round) const {
DCHECK_GE(reduce_by, 0);
DCHECK_LE(reduce_by, 76);
if (reduce_by == 0) {
return *this;
}
BasicDecimal256 divisor(ScaleMultipliersDecimal256[reduce_by]);
BasicDecimal256 result;
BasicDecimal256 remainder;
auto s = Divide(divisor, &result, &remainder);
DCHECK_EQ(s, DecimalStatus::kSuccess);
if (round) {
auto divisor_half = ScaleMultipliersHalfDecimal256[reduce_by];
if (remainder.Abs() >= divisor_half) {
if (result > 0) {
result += 1;
} else {
result -= 1;
}
}
}
return result;
}
bool BasicDecimal256::FitsInPrecision(int32_t precision) const {
DCHECK_GT(precision, 0);
DCHECK_LE(precision, 76);
return BasicDecimal256::Abs(*this) < ScaleMultipliersDecimal256[precision];
}
const BasicDecimal256& BasicDecimal256::GetScaleMultiplier(int32_t scale) {
DCHECK_GE(scale, 0);
DCHECK_LE(scale, 76);
return ScaleMultipliersDecimal256[scale];
}
BasicDecimal256 operator*(const BasicDecimal256& left, const BasicDecimal256& right) {
BasicDecimal256 result = left;
result *= right;
return result;
}
bool operator<(const BasicDecimal256& left, const BasicDecimal256& right) {
const std::array<uint64_t, 4>& lhs = left.little_endian_array();
const std::array<uint64_t, 4>& rhs = right.little_endian_array();
return lhs[3] != rhs[3]
? static_cast<int64_t>(lhs[3]) < static_cast<int64_t>(rhs[3])
: lhs[2] != rhs[2] ? lhs[2] < rhs[2]
: lhs[1] != rhs[1] ? lhs[1] < rhs[1] : lhs[0] < rhs[0];
}
BasicDecimal256 operator-(const BasicDecimal256& operand) {
BasicDecimal256 result(operand);
return result.Negate();
}
BasicDecimal256 operator~(const BasicDecimal256& operand) {
const std::array<uint64_t, 4>& arr = operand.little_endian_array();
BasicDecimal256 result({~arr[0], ~arr[1], ~arr[2], ~arr[3]});
return result;
}
BasicDecimal256& BasicDecimal256::operator/=(const BasicDecimal256& right) {
BasicDecimal256 remainder;
auto s = Divide(right, this, &remainder);
DCHECK_EQ(s, DecimalStatus::kSuccess);
return *this;
}
BasicDecimal256 operator+(const BasicDecimal256& left, const BasicDecimal256& right) {
BasicDecimal256 sum = left;
sum += right;
return sum;
}
BasicDecimal256 operator/(const BasicDecimal256& left, const BasicDecimal256& right) {
BasicDecimal256 remainder;
BasicDecimal256 result;
auto s = left.Divide(right, &result, &remainder);
DCHECK_EQ(s, DecimalStatus::kSuccess);
return result;
}
} // namespace arrow