YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/decimal.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
#include "yb/util/decimal.h"
14
15
#include <iomanip>
16
#include <limits>
17
#include <vector>
18
19
#include "yb/gutil/casts.h"
20
21
#include "yb/util/status_format.h"
22
#include "yb/util/status_log.h"
23
#include "yb/util/stol_utils.h"
24
25
using std::string;
26
using std::vector;
27
28
namespace yb {
29
namespace util {
30
31
4.65k
Decimal::Decimal(const std::string& string_val) {
32
4.65k
  CHECK_OK(FromString(string_val));
33
4.65k
}
34
35
5
Decimal::Decimal(double double_val) {
36
5
  CHECK_OK(FromDouble(double_val));
37
5
}
38
39
0
Decimal::Decimal(const VarInt& varint_val) {
40
0
  CHECK_OK(FromVarInt(varint_val));
41
0
}
42
43
5.62k
void Decimal::clear() {
44
5.62k
  digits_ = {};
45
5.62k
  exponent_ = VarInt(0);
46
5.62k
  is_positive_ = true;
47
5.62k
}
48
49
18
string Decimal::ToDebugString() const {
50
18
  string output = "[ ";
51
18
  output += is_positive_ ? 
"+"15
:
"-"3
;
52
18
  output += " 10^";
53
18
  output += exponent_.Sign() >= 0 ? 
"+"13
:
""5
;
54
18
  output += exponent_.ToString() + " * 0.";
55
37
  for (int digit : digits_) {
56
37
    output += '0' + digit;
57
37
  }
58
18
  output += " ]";
59
18
  return output;
60
18
}
61
62
8.35k
Status Decimal::ToPointString(string* string_val, const int max_length) const {
63
8.35k
  if (digits_.empty()) {
64
561
    *string_val = "0";
65
561
    return Status::OK();
66
561
  }
67
7.79k
  int64_t exponent = 
VERIFY_RESULT7.79k
(exponent_.ToInt64());7.79k
68
7.79k
  if (exponent > max_length || 
exponent < -max_length7.04k
) {
69
801
    return STATUS_SUBSTITUTE(InvalidArgument,
70
801
        "Max length $0 too small to encode decimal with exponent $1", max_length, exponent);
71
801
  }
72
6.99k
  string output;
73
6.99k
  if (!is_positive_) {
74
1.14k
    output = "-";
75
1.14k
  }
76
6.99k
  if (exponent <= 0) {
77
278
    output += "0.";
78
1.57k
    for (int i = 0; i < -exponent; 
i++1.30k
) {
79
1.30k
      output.push_back('0');
80
1.30k
    }
81
2.88k
    for (size_t i = 0; i < digits_.size(); 
i++2.60k
) {
82
2.75k
      output.push_back('0' + digits_[i]);
83
2.75k
      if (implicit_cast<int64_t>(output.size()) > max_length) {
84
153
        return STATUS_SUBSTITUTE(InvalidArgument,
85
153
            "Max length $0 too small to encode Decimal", max_length);
86
153
      }
87
2.75k
    }
88
6.71k
  } else {
89
44.8k
    for (size_t i = 0; i < digits_.size(); 
i++38.1k
) {
90
38.9k
      if (implicit_cast<size_t>(exponent) == i) {
91
2.10k
        output.push_back('.');
92
2.10k
      }
93
38.9k
      output.push_back('0' + digits_[i]);
94
38.9k
      if (implicit_cast<int64_t>(output.size()) > max_length) {
95
842
        return STATUS_SUBSTITUTE(InvalidArgument,
96
842
            "Max length $0 too small to encode Decimal", max_length);
97
842
      }
98
38.9k
    }
99
13.9k
    
for (ssize_t i = digits_.size(); 5.87k
i < exponent;
i++8.08k
) {
100
8.08k
      output.push_back('0');
101
8.08k
      if (implicit_cast<int64_t>(output.size()) > max_length) {
102
0
        return STATUS_SUBSTITUTE(InvalidArgument,
103
0
            "Max length $0 too small to encode Decimal", max_length);
104
0
      }
105
8.08k
    }
106
5.87k
  }
107
5.99k
  *string_val = std::move(output);
108
5.99k
  return Status::OK();
109
6.99k
}
110
111
1.80k
string Decimal::ToScientificString() const {
112
1.80k
  if (digits_.empty()) {
113
1
    return "0";
114
1
  }
115
1.80k
  string output;
116
1.80k
  if (!is_positive_) {
117
904
    output = "-";
118
904
  }
119
1.80k
  output.push_back('0' + digits_[0]);
120
1.80k
  output.push_back('.');
121
740k
  for (size_t i = 1; i < digits_.size(); 
i++738k
) {
122
738k
    output.push_back('0' + digits_[i]);
123
738k
  }
124
1.80k
  output.push_back('e');
125
1.80k
  VarInt exponent = exponent_ + VarInt(-1);
126
1.80k
  if (exponent.Sign() >= 0) {
127
1.59k
    output += "+";
128
1.59k
  }
129
1.80k
  output += exponent.ToString();
130
1.80k
  return output;
131
1.80k
}
132
133
8.35k
string Decimal::ToString() const {
134
8.35k
  string output;
135
8.35k
  if (Decimal::ToPointString(&output).ok()) {
136
6.55k
    return output;
137
6.55k
  } else {
138
1.79k
    return ToScientificString();
139
1.79k
  }
140
8.35k
}
141
142
13
Result<long double> Decimal::ToDouble() const {
143
13
  return CheckedStold(ToString());
144
13
}
145
146
2
Result<VarInt> Decimal::ToVarInt() const {
147
2
  string string_val;
148
2
  RETURN_NOT_OK(ToPointString(&string_val, kUnlimitedMaxLength));
149
150
2
  if (!is_integer()) {
151
0
    return STATUS_SUBSTITUTE(InvalidArgument,
152
0
        "Cannot convert non-integer Decimal into integer: $0", string_val);
153
0
  }
154
155
2
  return VarInt::CreateFromString(string_val);
156
2
}
157
158
7.43k
Status Decimal::FromString(const Slice &slice) {
159
7.43k
  if (slice.empty()) {
160
1
    return STATUS_SUBSTITUTE(InvalidArgument,
161
1
        "Cannot decode empty slice to Decimal: $0", slice.ToString());
162
1
  }
163
7.43k
  is_positive_ = slice[0] != '-';
164
7.43k
  size_t i = 0;
165
7.43k
  if (slice[0] == '+' || 
slice[0] == '-'7.42k
) {
166
2.10k
    i++;
167
2.10k
  }
168
7.43k
  bool point_found = false;
169
7.43k
  size_t point_position = 0;
170
7.43k
  digits_.clear();
171
1.36M
  for (; i < slice.size() && 
slice[i] != 'e'1.36M
&&
slice[i] != 'E'1.36M
;
i++1.36M
) {
172
1.36M
    if (slice[i] == '.' && 
!point_found4.73k
) {
173
4.73k
      point_found = true;
174
4.73k
      point_position = digits_.size();
175
4.73k
      continue;
176
4.73k
    }
177
1.35M
    if (PREDICT_TRUE(slice[i] >= '0' && slice[i] <= '9')) {
178
1.35M
      digits_.push_back(slice[i]-'0');
179
1.35M
    } else {
180
2
      return STATUS_SUBSTITUTE(
181
2
          InvalidArgument,
182
2
          "Invalid character $0 found at position $1 when parsing Decimal $2",
183
2
          slice[i], i, slice.ToString());
184
2
    }
185
1.35M
  }
186
7.43k
  if (PREDICT_FALSE(digits_.empty())) {
187
1
    return STATUS_SUBSTITUTE(
188
1
        InvalidArgument,
189
1
        "There are no digits in the decimal $0 before the e / E",
190
1
        slice.ToBuffer());
191
1
  }
192
7.42k
  if (!point_found) {
193
2.69k
    point_position = digits_.size();
194
2.69k
  }
195
7.42k
  if (i < slice.size()) {
196
805
    Slice exponent_slice(slice);
197
805
    exponent_slice.remove_prefix(i+1);
198
805
    RETURN_NOT_OK(exponent_.FromString(exponent_slice.ToBuffer()));
199
6.62k
  } else {
200
6.62k
    exponent_ = VarInt(0);
201
6.62k
  }
202
7.42k
  exponent_ = exponent_ + VarInt(static_cast<int64_t> (point_position));
203
7.42k
  make_canonical();
204
7.42k
  return Status::OK();
205
7.42k
}
206
207
constexpr size_t kPrecisionLimit = 20;
208
209
namespace {
210
211
13
string StringFromDouble(double double_val, int precision_limit = kPrecisionLimit) {
212
13
  std::stringstream ss;
213
13
  ss << std::setprecision(precision_limit);
214
13
  ss << double_val;
215
13
  return ss.str();
216
13
}
217
218
}  // namespace
219
220
13
Status Decimal::FromDouble(double double_val) {
221
13
  string str = StringFromDouble(double_val);
222
13
  if (str == "nan") {
223
2
    return STATUS(Corruption, "Cannot convert nan to Decimal");
224
11
  } else if (str == "-nan") {
225
0
    return STATUS(Corruption, "Cannot convert -nan to Decimal");
226
11
  } else if (str == "inf") {
227
1
    return STATUS(Corruption, "Cannot convert inf to Decimal");
228
10
  } else if (str == "-inf") {
229
1
    return STATUS(Corruption, "Cannot convert -inf to Decimal");
230
1
  }
231
9
  return FromString(str);
232
13
}
233
234
0
Status Decimal::FromVarInt(const VarInt &varint_val) {
235
0
  return FromString(varint_val.ToString());
236
0
}
237
238
18
bool Decimal::is_integer() const {
239
18
  return digits_.empty() || 
exponent_ >= VarInt(static_cast<int64_t>(digits_.size()))17
;
240
18
}
241
242
132
int Decimal::CompareTo(const Decimal &other) const {
243
132
  if (is_positive_ != other.is_positive_) {
244
8
    return static_cast<int>(is_positive_) - static_cast<int>(other.is_positive_);
245
8
  }
246
124
  int comp;
247
  // We must compare zeros in a special way because the exponent logic doesn't work with special
248
  // canonicalization for zero.
249
124
  if (digits_.empty() || 
other.digits_.empty()122
) {
250
10
    comp = static_cast<int>(digits_.empty()) - static_cast<int>(other.digits_.empty());
251
10
    return is_positive_ ? -comp : 
comp0
;
252
10
  }
253
114
  comp = exponent_.CompareTo(other.exponent_);
254
114
  if (comp != 0) {
255
56
    return is_positive_ ? 
comp32
:
-comp24
;
256
56
  }
257
232
  
for (size_t i = 0; 58
i < digits_.size() &&
i < other.digits_.size()198
;
i++174
) {
258
198
    comp = static_cast<int>(digits_[i]) - static_cast<int>(other.digits_[i]);
259
198
    if (comp != 0) {
260
24
      return is_positive_ ? 
comp8
:
-comp16
;
261
24
    }
262
198
  }
263
34
  comp = static_cast<int>(this->digits_.size()) - static_cast<int>(other.digits_.size());
264
34
  return is_positive_ ? 
comp12
:
-comp22
;
265
58
}
266
267
// Encodes pairs of digits into one byte each. The last bit in each byte is the
268
// "continuation bit" which is equal to 1 for all bytes except the last.
269
144k
std::string EncodeToDigitPairs(const std::vector<uint8_t>& digits) {
270
144k
  if (digits.empty()) {
271
0
    return std::string();
272
0
  }
273
144k
  size_t len = (digits.size() + 1) / 2;
274
144k
  std::string result(len, 0);
275
7.25M
  for (size_t i = 0; i < len - 1; 
++i7.10M
) {
276
7.10M
    result[i] = (digits[i * 2] * 10 + digits[i * 2 + 1]) * 2 + 1;
277
7.10M
  }
278
144k
  size_t i = len - 1;
279
144k
  uint8_t last_byte = digits[i * 2] * 10;
280
144k
  if (i * 2 + 1 < digits.size()) {
281
88.2k
    last_byte += digits[i * 2 + 1];
282
88.2k
  }
283
144k
  result[i] = last_byte * 2;
284
144k
  return result;
285
144k
}
286
287
149k
string Decimal::EncodeToComparable() const {
288
  // Zero is encoded to the special value 128.
289
149k
  if (digits_.empty()) {
290
5.02k
    return string(1, static_cast<char>(128));
291
5.02k
  }
292
  // We reserve two bits for sign: -, zero, and +. Their sign portions are resp. '00', '10', '11'.
293
144k
  string exponent = exponent_.EncodeToComparable(/* num_reserved_bits */ 2);
294
144k
  const string mantissa = EncodeToDigitPairs(digits_);
295
144k
  string output = exponent + mantissa;
296
  // The first two (reserved) bits are set to 1 here.
297
144k
  output[0] |= 0xc0;
298
  // For negatives, everything is complemented (including the sign bits) which were set to 1 above.
299
144k
  if (!is_positive_) {
300
3.58M
    for (size_t i = 0; i < output.size(); 
i++3.53M
) {
301
3.53M
      output[i] = ~output[i]; // Bitwise not.
302
3.53M
    }
303
45.5k
  }
304
144k
  return output;
305
149k
}
306
307
CHECKED_STATUS DecodeFromDigitPairs(
308
224k
    const Slice& slice, size_t *num_decoded_bytes, std::vector<uint8_t>* digits) {
309
224k
  digits->clear();
310
224k
  digits->reserve(slice.size() * 2);
311
224k
  *num_decoded_bytes = 0;
312
10.7M
  for (size_t i = 0; i < slice.size(); 
i++10.5M
) {
313
10.5M
    uint8_t byte = slice[i];
314
10.5M
    if (!(byte & 1)) {
315
224k
      *num_decoded_bytes = i + 1;
316
224k
      i = slice.size();
317
224k
    }
318
10.5M
    byte /= 2;
319
10.5M
    digits->push_back(byte / 10);
320
10.5M
    digits->push_back(byte % 10);
321
10.5M
  }
322
224k
  if (*num_decoded_bytes == 0) {
323
0
    return STATUS(Corruption, "Decoded the whole slice but didn't find the ending");
324
0
  }
325
308k
  
while (224k
!digits->empty()308k
&& !digits->back()) {
326
84.4k
    digits->pop_back();
327
84.4k
  }
328
224k
  return Status::OK();
329
224k
}
330
331
229k
Status Decimal::DecodeFromComparable(const Slice& slice, size_t *num_decoded_bytes) {
332
229k
  if (slice.empty()) {
333
54
    return STATUS(Corruption, "Cannot decode Decimal from empty slice.");
334
54
  }
335
  // Zero is specially decoded from the value 128.
336
229k
  if (slice[0] == 128) {
337
5.26k
    clear();
338
5.26k
    *num_decoded_bytes = 1;
339
5.26k
    return Status::OK();
340
5.26k
  }
341
  // The first bit is enough to decode the sign.
342
224k
  is_positive_ = slice[0] >= 128;
343
  // We have to complement everything if negative, so we are making a copy.
344
224k
  string encoded = slice.ToBuffer();
345
224k
  if (!is_positive_) {
346
5.37M
    for (size_t i = 0; i < encoded.size(); 
i++5.30M
) {
347
5.30M
      encoded[i] = ~encoded[i];
348
5.30M
    }
349
66.6k
  }
350
224k
  size_t num_exponent_bytes = 0;
351
224k
  RETURN_NOT_OK(exponent_.DecodeFromComparable(
352
224k
      encoded, &num_exponent_bytes, /* num_reserved_bits */ 2));
353
224k
  Slice remaining_slice(encoded);
354
224k
  remaining_slice.remove_prefix(num_exponent_bytes);
355
224k
  size_t num_mantissa_bytes = 0;
356
224k
  RETURN_NOT_OK(DecodeFromDigitPairs(remaining_slice, &num_mantissa_bytes, &digits_));
357
224k
  *num_decoded_bytes = num_exponent_bytes + num_mantissa_bytes;
358
224k
  return Status::OK();
359
224k
}
360
361
19.8k
Status Decimal::DecodeFromComparable(const Slice& slice) {
362
19.8k
  size_t num_decoded_bytes;
363
19.8k
  return DecodeFromComparable(slice, &num_decoded_bytes);
364
19.8k
}
365
366
11.3k
string Decimal::EncodeToSerializedBigDecimal(bool* is_out_of_range) const {
367
  // Note that BigDecimal's scale is not the same as our exponent, but related by the following:
368
11.3k
  VarInt varint_scale = VarInt(static_cast<int64_t>(digits_.size())) - exponent_;
369
  // Must use 4 bytes for the two's complement encoding of the scale.
370
11.3k
  string scale = varint_scale.EncodeToTwosComplement();
371
11.3k
  if (scale.length() > 4) {
372
2
    *is_out_of_range = true;
373
2
    return std::string();
374
2
  }
375
11.3k
  *is_out_of_range = false;
376
11.3k
  if (scale.length() < 4) {
377
11.3k
    scale = std::string(4 - scale.length(), varint_scale.Sign() < 0 ? 
0xff3.17k
:
0x008.15k
) + scale;
378
11.3k
  }
379
380
11.3k
  std::vector<char> digits;
381
11.3k
  digits.reserve(digits_.size() + 1);
382
1.55M
  for (auto digit : digits_) {
383
1.55M
    digits.push_back('0' + digit);
384
1.55M
  }
385
11.3k
  digits.push_back(0);
386
387
  // Note that the mantissa varint needs to have the same sign as the current decimal.
388
  // Get the digit array in int from int8_t in this class.
389
11.3k
  auto temp = !digits_.empty() ? CHECK_RESULT(VarInt::CreateFromString(digits.data())) : 
VarInt(0)6
;
390
11.3k
  if (!is_positive_) {
391
5.20k
    temp.Negate();
392
5.20k
  }
393
11.3k
  string mantissa = temp.EncodeToTwosComplement();
394
11.3k
  return scale + mantissa;
395
11.3k
}
396
397
219
Status Decimal::DecodeFromSerializedBigDecimal(Slice slice) {
398
219
  if (slice.size() < 5) {
399
0
    return STATUS_SUBSTITUTE(
400
0
        Corruption, "Serialized BigDecimal must have at least 5 bytes. Found $0", slice.size());
401
0
  }
402
  // Decode the scale from the first 4 bytes.
403
219
  VarInt scale;
404
219
  RETURN_NOT_OK(scale.DecodeFromTwosComplement(std::string(slice.cdata(), 4)));
405
219
  slice.remove_prefix(4);
406
219
  VarInt mantissa;
407
219
  RETURN_NOT_OK(mantissa.DecodeFromTwosComplement(slice.ToBuffer()));
408
219
  bool negative = mantissa.Sign() < 0;
409
219
  if (negative) {
410
57
    mantissa.Negate();
411
57
  }
412
219
  auto mantissa_str = mantissa.ToString();
413
  // The sign of the BigDecimal is the sign of the mantissa
414
219
  is_positive_ = !negative;
415
219
  digits_.resize(mantissa_str.size());
416
33.7k
  for (size_t i = 0; i != mantissa_str.size(); 
++i33.5k
) {
417
33.5k
    digits_[i] = mantissa_str[i] - '0';
418
33.5k
  }
419
219
  exponent_ = VarInt(static_cast<int64_t> (digits_.size())) - scale;
420
219
  make_canonical();
421
219
  return Status::OK();
422
219
}
423
424
0
bool Decimal::IsIdenticalTo(const Decimal &other) const {
425
0
  return
426
0
      is_positive_ == other.is_positive_ &&
427
0
      exponent_ == other.exponent_ &&
428
0
      digits_ == other.digits_;
429
0
}
430
431
8.18k
bool Decimal::is_canonical() const {
432
8.18k
  if (digits_.empty()) {
433
7
    return is_positive_ && 
exponent_ == VarInt(0)5
;
434
7
  }
435
8.17k
  return digits_.front() != 0 && 
digits_.back() != 07.44k
;
436
8.18k
}
437
438
8.18k
void Decimal::make_canonical() {
439
8.18k
  if (is_canonical()) {
440
5.80k
    return;
441
5.80k
  }
442
2.38k
  size_t num_zeros = 0;
443
70.5k
  while (num_zeros < digits_.size() && 
digits_[num_zeros] == 070.2k
) {
444
68.1k
    num_zeros++;
445
68.1k
  }
446
2.38k
  exponent_ = exponent_ - VarInt(num_zeros);
447
705k
  for (size_t i = num_zeros; i < digits_.size() + num_zeros; 
i++703k
) {
448
703k
    digits_[i-num_zeros] = i < digits_.size() ? 
digits_[i]634k
:
068.1k
;
449
703k
  }
450
597k
  while (!digits_.empty() && 
digits_.back() == 0596k
) {
451
594k
    digits_.pop_back();
452
594k
  }
453
2.38k
  if (digits_.empty()) {
454
357
    clear();
455
357
  }
456
2.38k
}
457
458
11.3k
Decimal DecimalFromComparable(const Slice& slice) {
459
11.3k
  Decimal decimal;
460
11.3k
  CHECK_OK(decimal.DecodeFromComparable(slice));
461
11.3k
  return decimal;
462
11.3k
}
463
464
11.3k
Decimal DecimalFromComparable(const std::string& str) {
465
11.3k
  return DecimalFromComparable(Slice(str));
466
11.3k
}
467
468
// Normalize so that both Decimals have same exponent and same number of digits
469
// Add digits considering sign
470
// Canonicalize result
471
472
115
Decimal Decimal::operator+(const Decimal& other) const {
473
115
  Decimal decimal(digits_, exponent_, is_positive_);
474
115
  Decimal other1(other.digits_, other.exponent_, other.is_positive_);
475
476
  // Normalize the exponents
477
  // eg. if we are adding 0.1E+3 and 0.5E+2, we first convert them to 0.1E+3 and 0.05E+3
478
115
  VarInt max_exponent = std::max(other1.exponent_, decimal.exponent_);
479
115
  VarInt var_int_one(1);
480
115
  if (decimal.exponent_ < max_exponent) {
481
3
    VarInt increase_varint = max_exponent - decimal.exponent_;
482
3
    int64_t increase = CHECK_RESULT(increase_varint.ToInt64());
483
3
    decimal.digits_.insert(decimal.digits_.begin(), increase, 0);
484
3
    decimal.exponent_ = max_exponent;
485
3
  }
486
115
  if (other1.exponent_ < max_exponent) {
487
110
    VarInt increase_varint = max_exponent - other1.exponent_;
488
110
    int64_t increase = CHECK_RESULT(increase_varint.ToInt64());
489
110
    other1.digits_.insert(other1.digits_.begin(), increase, 0);
490
110
    other1.exponent_ = max_exponent;
491
110
  }
492
493
  // Make length of digits the same.
494
  // If we need to add 0.1E+3 and 0.05E+3, we convert them to 0.10E+3 and 0.05E+3
495
115
  size_t max_digits = std::max(decimal.digits_.size(), other1.digits_.size());
496
115
  if (decimal.digits_.size() < max_digits) {
497
24
    auto increase = max_digits - decimal.digits_.size();
498
1.65k
    for (size_t i = 0; i < increase; 
i = i + 11.63k
) {
499
1.63k
      decimal.digits_.push_back(0);
500
1.63k
    }
501
24
  }
502
115
  if (other1.digits_.size() < max_digits) {
503
90
    auto increase = max_digits - other1.digits_.size();
504
53.6k
    for (size_t i = 0; i < increase; 
i++53.5k
) {
505
53.5k
      other1.digits_.push_back(0);
506
53.5k
    }
507
90
  }
508
509
  // Add mantissa
510
  // For the case when the both numbers are positive (eg. 0.1E+3 and 0.05E+3)
511
  // or both negative (eg. -0.1E+3 and -0.05E+3), we just add the mantissas
512
115
  if (decimal.is_positive_ == other1.is_positive_) {
513
38.5k
    for (int64_t i = max_digits - 1; i >= 0; 
i--38.4k
) {
514
38.4k
      decimal.digits_[i] += other1.digits_[i];
515
38.4k
      if (decimal.digits_[i] > 9) {
516
2.05k
        decimal.digits_[i] -= 10;
517
2.05k
        if (i > 0) {
518
2.05k
          decimal.digits_[i - 1]++;
519
2.05k
        } else {
520
0
          decimal.digits_.insert(decimal.digits_.begin(), 1);
521
0
          decimal.exponent_ = decimal.exponent_ + var_int_one;
522
0
        }
523
2.05k
      }
524
38.4k
    }
525
61
  } else {
526
  // For the case when the two numbers have opposite sign (eg. 0.1E+3 and -0.05E+3)
527
  // or (-0.1E+3 and 0.05E+3), we subtract the smaller mantissa from the larger mantissa
528
  // and use the sign of the larger mantissa
529
61
    int comp = 0; // indicates whether mantissa of this is bigger
530
61
    for (size_t i = 0; i < decimal.digits_.size() && i < other1.digits_.size(); 
i++0
) {
531
61
      comp = static_cast<int>(decimal.digits_[i]) - static_cast<int>(other1.digits_[i]);
532
61
      if (comp != 0) {
533
61
        break;
534
61
      }
535
61
    }
536
61
    if (comp < 0) {
537
2
      decimal.digits_.swap(other1.digits_);
538
2
      decimal.is_positive_ = !decimal.is_positive_;
539
2
    }
540
96.7k
    for (int64_t i = max_digits - 1; i >= 0; 
i--96.7k
) {
541
96.7k
      if (decimal.digits_[i] >= other1.digits_[i]) {
542
91.5k
        decimal.digits_[i] -= other1.digits_[i];
543
91.5k
      } else {
544
5.16k
        other1.digits_[i-1]++;
545
5.16k
        decimal.digits_[i] = decimal.digits_[i] + 10 - other1.digits_[i];
546
5.16k
      }
547
96.7k
    }
548
61
  }
549
550
  // Finally we normalize the number obtained to get rid of leading and trailing 0's
551
  // in the mantissa.
552
115
  decimal.make_canonical();
553
115
  return decimal;
554
115
}
555
556
0
std::ostream& operator<<(ostream& os, const Decimal& d) {
557
0
  os << d.ToString();
558
0
  return os;
559
0
}
560
561
} // namespace util
562
} // namespace yb