YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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.27k
Decimal::Decimal(const std::string& string_val) {
32
4.27k
  CHECK_OK(FromString(string_val));
33
4.27k
}
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
93
void Decimal::clear() {
44
93
  digits_ = {};
45
93
  exponent_ = VarInt(0);
46
93
  is_positive_ = true;
47
93
}
48
49
18
string Decimal::ToDebugString() const {
50
18
  string output = "[ ";
51
15
  output += is_positive_ ? "+" : "-";
52
18
  output += " 10^";
53
13
  output += exponent_.Sign() >= 0 ? "+" : "";
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.19k
Status Decimal::ToPointString(string* string_val, const int max_length) const {
63
8.19k
  if (digits_.empty()) {
64
4
    *string_val = "0";
65
4
    return Status::OK();
66
4
  }
67
8.18k
  int64_t exponent = VERIFY_RESULT(exponent_.ToInt64());
68
8.18k
  if (exponent > max_length || exponent < -max_length) {
69
9
    return STATUS_SUBSTITUTE(InvalidArgument,
70
9
        "Max length $0 too small to encode decimal with exponent $1", max_length, exponent);
71
9
  }
72
8.17k
  string output;
73
8.17k
  if (!is_positive_) {
74
11
    output = "-";
75
11
  }
76
8.17k
  if (exponent <= 0) {
77
12
    output += "0.";
78
46
    for (int i = 0; i < -exponent; i++) {
79
34
      output.push_back('0');
80
34
    }
81
170
    for (size_t i = 0; i < digits_.size(); i++) {
82
168
      output.push_back('0' + digits_[i]);
83
168
      if (implicit_cast<int64_t>(output.size()) > max_length) {
84
10
        return STATUS_SUBSTITUTE(InvalidArgument,
85
10
            "Max length $0 too small to encode Decimal", max_length);
86
10
      }
87
168
    }
88
8.16k
  } else {
89
16.5k
    for (size_t i = 0; i < digits_.size(); i++) {
90
8.38k
      if (implicit_cast<size_t>(exponent) == i) {
91
39
        output.push_back('.');
92
39
      }
93
8.38k
      output.push_back('0' + digits_[i]);
94
8.38k
      if (implicit_cast<int64_t>(output.size()) > max_length) {
95
4
        return STATUS_SUBSTITUTE(InvalidArgument,
96
4
            "Max length $0 too small to encode Decimal", max_length);
97
4
      }
98
8.38k
    }
99
24.3k
    for (ssize_t i = digits_.size(); i < exponent; i++) {
100
16.2k
      output.push_back('0');
101
16.2k
      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
16.2k
    }
106
8.15k
  }
107
8.16k
  *string_val = std::move(output);
108
8.16k
  return Status::OK();
109
8.17k
}
110
111
31
string Decimal::ToScientificString() const {
112
31
  if (digits_.empty()) {
113
1
    return "0";
114
1
  }
115
30
  string output;
116
30
  if (!is_positive_) {
117
4
    output = "-";
118
4
  }
119
30
  output.push_back('0' + digits_[0]);
120
30
  output.push_back('.');
121
732
  for (size_t i = 1; i < digits_.size(); i++) {
122
702
    output.push_back('0' + digits_[i]);
123
702
  }
124
30
  output.push_back('e');
125
30
  VarInt exponent = exponent_ + VarInt(-1);
126
30
  if (exponent.Sign() >= 0) {
127
12
    output += "+";
128
12
  }
129
30
  output += exponent.ToString();
130
30
  return output;
131
30
}
132
133
8.18k
string Decimal::ToString() const {
134
8.18k
  string output;
135
8.18k
  if (Decimal::ToPointString(&output).ok()) {
136
8.15k
    return output;
137
25
  } else {
138
25
    return ToScientificString();
139
25
  }
140
8.18k
}
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.05k
Status Decimal::FromString(const Slice &slice) {
159
7.05k
  if (slice.empty()) {
160
1
    return STATUS_SUBSTITUTE(InvalidArgument,
161
1
        "Cannot decode empty slice to Decimal: $0", slice.ToString());
162
1
  }
163
7.05k
  is_positive_ = slice[0] != '-';
164
7.05k
  size_t i = 0;
165
7.05k
  if (slice[0] == '+' || slice[0] == '-') {
166
1.08k
    i++;
167
1.08k
  }
168
7.05k
  bool point_found = false;
169
7.05k
  size_t point_position = 0;
170
7.05k
  digits_.clear();
171
320k
  for (; i < slice.size() && slice[i] != 'e' && slice[i] != 'E'; i++) {
172
313k
    if (slice[i] == '.' && !point_found) {
173
2.69k
      point_found = true;
174
2.69k
      point_position = digits_.size();
175
2.69k
      continue;
176
2.69k
    }
177
310k
    if (PREDICT_TRUE(slice[i] >= '0' && slice[i] <= '9')) {
178
310k
      digits_.push_back(slice[i]-'0');
179
2
    } 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
310k
  }
186
7.04k
  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.04k
  if (!point_found) {
193
4.35k
    point_position = digits_.size();
194
4.35k
  }
195
7.04k
  if (i < slice.size()) {
196
833
    Slice exponent_slice(slice);
197
833
    exponent_slice.remove_prefix(i+1);
198
833
    RETURN_NOT_OK(exponent_.FromString(exponent_slice.ToBuffer()));
199
6.21k
  } else {
200
6.21k
    exponent_ = VarInt(0);
201
6.21k
  }
202
7.04k
  exponent_ = exponent_ + VarInt(static_cast<int64_t> (point_position));
203
7.04k
  make_canonical();
204
7.04k
  return Status::OK();
205
7.04k
}
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
9
}
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()));
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()) {
250
10
    comp = static_cast<int>(digits_.empty()) - static_cast<int>(other.digits_.empty());
251
10
    return is_positive_ ? -comp : comp;
252
10
  }
253
114
  comp = exponent_.CompareTo(other.exponent_);
254
114
  if (comp != 0) {
255
32
    return is_positive_ ? comp : -comp;
256
56
  }
257
232
  for (size_t i = 0; i < digits_.size() && i < other.digits_.size(); i++) {
258
198
    comp = static_cast<int>(digits_[i]) - static_cast<int>(other.digits_[i]);
259
198
    if (comp != 0) {
260
16
      return is_positive_ ? comp : -comp;
261
24
    }
262
198
  }
263
34
  comp = static_cast<int>(this->digits_.size()) - static_cast<int>(other.digits_.size());
264
22
  return is_positive_ ? comp : -comp;
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
115k
std::string EncodeToDigitPairs(const std::vector<uint8_t>& digits) {
270
115k
  if (digits.empty()) {
271
0
    return std::string();
272
0
  }
273
115k
  size_t len = (digits.size() + 1) / 2;
274
115k
  std::string result(len, 0);
275
4.10M
  for (size_t i = 0; i < len - 1; ++i) {
276
3.99M
    result[i] = (digits[i * 2] * 10 + digits[i * 2 + 1]) * 2 + 1;
277
3.99M
  }
278
115k
  size_t i = len - 1;
279
115k
  uint8_t last_byte = digits[i * 2] * 10;
280
115k
  if (i * 2 + 1 < digits.size()) {
281
71.8k
    last_byte += digits[i * 2 + 1];
282
71.8k
  }
283
115k
  result[i] = last_byte * 2;
284
115k
  return result;
285
115k
}
286
287
115k
string Decimal::EncodeToComparable() const {
288
  // Zero is encoded to the special value 128.
289
115k
  if (digits_.empty()) {
290
57
    return string(1, static_cast<char>(128));
291
57
  }
292
  // We reserve two bits for sign: -, zero, and +. Their sign portions are resp. '00', '10', '11'.
293
115k
  string exponent = exponent_.EncodeToComparable(/* num_reserved_bits */ 2);
294
115k
  const string mantissa = EncodeToDigitPairs(digits_);
295
115k
  string output = exponent + mantissa;
296
  // The first two (reserved) bits are set to 1 here.
297
115k
  output[0] |= 0xc0;
298
  // For negatives, everything is complemented (including the sign bits) which were set to 1 above.
299
115k
  if (!is_positive_) {
300
2.22M
    for (size_t i = 0; i < output.size(); i++) {
301
2.19M
      output[i] = ~output[i]; // Bitwise not.
302
2.19M
    }
303
32.3k
  }
304
115k
  return output;
305
115k
}
306
307
CHECKED_STATUS DecodeFromDigitPairs(
308
194k
    const Slice& slice, size_t *num_decoded_bytes, std::vector<uint8_t>* digits) {
309
194k
  digits->clear();
310
194k
  digits->reserve(slice.size() * 2);
311
194k
  *num_decoded_bytes = 0;
312
7.40M
  for (size_t i = 0; i < slice.size(); i++) {
313
7.20M
    uint8_t byte = slice[i];
314
7.20M
    if (!(byte & 1)) {
315
194k
      *num_decoded_bytes = i + 1;
316
194k
      i = slice.size();
317
194k
    }
318
7.20M
    byte /= 2;
319
7.20M
    digits->push_back(byte / 10);
320
7.20M
    digits->push_back(byte % 10);
321
7.20M
  }
322
194k
  if (*num_decoded_bytes == 0) {
323
0
    return STATUS(Corruption, "Decoded the whole slice but didn't find the ending");
324
0
  }
325
269k
  while (!digits->empty() && !digits->back()) {
326
75.1k
    digits->pop_back();
327
75.1k
  }
328
194k
  return Status::OK();
329
194k
}
330
331
194k
Status Decimal::DecodeFromComparable(const Slice& slice, size_t *num_decoded_bytes) {
332
194k
  if (slice.empty()) {
333
0
    return STATUS(Corruption, "Cannot decode Decimal from empty slice.");
334
0
  }
335
  // Zero is specially decoded from the value 128.
336
194k
  if (slice[0] == 128) {
337
71
    clear();
338
71
    *num_decoded_bytes = 1;
339
71
    return Status::OK();
340
71
  }
341
  // The first bit is enough to decode the sign.
342
194k
  is_positive_ = slice[0] >= 128;
343
  // We have to complement everything if negative, so we are making a copy.
344
194k
  string encoded = slice.ToBuffer();
345
194k
  if (!is_positive_) {
346
4.27M
    for (size_t i = 0; i < encoded.size(); i++) {
347
4.21M
      encoded[i] = ~encoded[i];
348
4.21M
    }
349
57.5k
  }
350
194k
  size_t num_exponent_bytes = 0;
351
194k
  RETURN_NOT_OK(exponent_.DecodeFromComparable(
352
194k
      encoded, &num_exponent_bytes, /* num_reserved_bits */ 2));
353
194k
  Slice remaining_slice(encoded);
354
194k
  remaining_slice.remove_prefix(num_exponent_bytes);
355
194k
  size_t num_mantissa_bytes = 0;
356
194k
  RETURN_NOT_OK(DecodeFromDigitPairs(remaining_slice, &num_mantissa_bytes, &digits_));
357
194k
  *num_decoded_bytes = num_exponent_bytes + num_mantissa_bytes;
358
194k
  return Status::OK();
359
194k
}
360
361
19.7k
Status Decimal::DecodeFromComparable(const Slice& slice) {
362
19.7k
  size_t num_decoded_bytes;
363
19.7k
  return DecodeFromComparable(slice, &num_decoded_bytes);
364
19.7k
}
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
8.45k
    scale = std::string(4 - scale.length(), varint_scale.Sign() < 0 ? 0xff : 0x00) + scale;
378
11.3k
  }
379
380
11.3k
  std::vector<char> digits;
381
11.3k
  digits.reserve(digits_.size() + 1);
382
1.52M
  for (auto digit : digits_) {
383
1.52M
    digits.push_back('0' + digit);
384
1.52M
  }
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);
390
11.3k
  if (!is_positive_) {
391
6.36k
    temp.Negate();
392
6.36k
  }
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
54
    mantissa.Negate();
411
54
  }
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
28.8k
  for (size_t i = 0; i != mantissa_str.size(); ++i) {
417
28.6k
    digits_[i] = mantissa_str[i] - '0';
418
28.6k
  }
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
7.80k
bool Decimal::is_canonical() const {
432
7.80k
  if (digits_.empty()) {
433
7
    return is_positive_ && exponent_ == VarInt(0);
434
7
  }
435
7.79k
  return digits_.front() != 0 && digits_.back() != 0;
436
7.79k
}
437
438
7.80k
void Decimal::make_canonical() {
439
7.80k
  if (is_canonical()) {
440
4.20k
    return;
441
4.20k
  }
442
3.59k
  size_t num_zeros = 0;
443
3.80k
  while (num_zeros < digits_.size() && digits_[num_zeros] == 0) {
444
205
    num_zeros++;
445
205
  }
446
3.59k
  exponent_ = exponent_ - VarInt(num_zeros);
447
87.7k
  for (size_t i = num_zeros; i < digits_.size() + num_zeros; i++) {
448
83.9k
    digits_[i-num_zeros] = i < digits_.size() ? digits_[i] : 0;
449
84.1k
  }
450
8.74k
  while (!digits_.empty() && digits_.back() == 0) {
451
5.14k
    digits_.pop_back();
452
5.14k
  }
453
3.59k
  if (digits_.empty()) {
454
22
    clear();
455
22
  }
456
3.59k
}
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
111
    VarInt increase_varint = max_exponent - other1.exponent_;
488
111
    int64_t increase = CHECK_RESULT(increase_varint.ToInt64());
489
111
    other1.digits_.insert(other1.digits_.begin(), increase, 0);
490
111
    other1.exponent_ = max_exponent;
491
111
  }
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
29
    auto increase = max_digits - decimal.digits_.size();
498
1.75k
    for (size_t i = 0; i < increase; i = i + 1) {
499
1.72k
      decimal.digits_.push_back(0);
500
1.72k
    }
501
29
  }
502
115
  if (other1.digits_.size() < max_digits) {
503
85
    auto increase = max_digits - other1.digits_.size();
504
41.9k
    for (size_t i = 0; i < increase; i++) {
505
41.8k
      other1.digits_.push_back(0);
506
41.8k
    }
507
85
  }
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
52.4k
    for (int64_t i = max_digits - 1; i >= 0; i--) {
514
52.3k
      decimal.digits_[i] += other1.digits_[i];
515
52.3k
      if (decimal.digits_[i] > 9) {
516
2.80k
        decimal.digits_[i] -= 10;
517
2.80k
        if (i > 0) {
518
2.80k
          decimal.digits_[i - 1]++;
519
0
        } else {
520
0
          decimal.digits_.insert(decimal.digits_.begin(), 1);
521
0
          decimal.exponent_ = decimal.exponent_ + var_int_one;
522
0
        }
523
2.80k
      }
524
52.3k
    }
525
51
  } 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
51
    int comp = 0; // indicates whether mantissa of this is bigger
530
51
    for (size_t i = 0; i < decimal.digits_.size() && i < other1.digits_.size(); i++) {
531
51
      comp = static_cast<int>(decimal.digits_[i]) - static_cast<int>(other1.digits_[i]);
532
51
      if (comp != 0) {
533
51
        break;
534
51
      }
535
51
    }
536
51
    if (comp < 0) {
537
2
      decimal.digits_.swap(other1.digits_);
538
2
      decimal.is_positive_ = !decimal.is_positive_;
539
2
    }
540
82.7k
    for (int64_t i = max_digits - 1; i >= 0; i--) {
541
82.6k
      if (decimal.digits_[i] >= other1.digits_[i]) {
542
78.2k
        decimal.digits_[i] -= other1.digits_[i];
543
4.46k
      } else {
544
4.46k
        other1.digits_[i-1]++;
545
4.46k
        decimal.digits_[i] = decimal.digits_[i] + 10 - other1.digits_[i];
546
4.46k
      }
547
82.6k
    }
548
51
  }
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