Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
decimal-test.cc
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <iostream>
18 #include <limits>
19 #include <gtest/gtest.h>
20 #include <boost/cstdint.hpp>
21 #include <boost/lexical_cast.hpp>
22 #include "runtime/decimal-value.h"
23 #include "util/string-parser.h"
24 
25 #include "common/names.h"
26 
27 using std::max;
28 using std::min;
29 
30 namespace impala {
31 
32 // Compare decimal result against double.
33 static const double MAX_ERROR = 0.0001;
34 
35 template <typename T>
36 void VerifyEquals(const DecimalValue<T>& t1, const DecimalValue<T>& t2) {
37  if (t1 != t2) {
38  LOG(ERROR) << t1 << " != " << t2;
39  EXPECT_TRUE(false);
40  }
41 }
42 
43 template <typename T>
44 void VerifyParse(const string& s, const ColumnType& t,
45  const DecimalValue<T>& expected_val, StringParser::ParseResult expected_result) {
46  StringParser::ParseResult parse_result;
47  DecimalValue<T> val = StringParser::StringToDecimal<T>(
48  s.c_str(), s.size(), t, &parse_result);
49  EXPECT_EQ(expected_result, parse_result) << "Failed test string: " << s;
50  if (expected_result == StringParser::PARSE_SUCCESS ||
51  expected_result == StringParser::PARSE_UNDERFLOW) {
52  VerifyEquals(expected_val, val);
53  }
54 }
55 
56 template<typename T>
57 void VerifyToString(const T& decimal, const ColumnType& t, const string& expected) {
58  EXPECT_EQ(decimal.ToString(t), expected);
59 }
60 
61 void StringToAllDecimals(const string& s, const ColumnType& t, int32_t val,
63  VerifyParse(s, t, Decimal4Value(val), result);
64  VerifyParse(s, t, Decimal8Value(val), result);
65  VerifyParse(s, t, Decimal16Value(val), result);
66 }
67 
68 TEST(IntToDecimal, Basic) {
69  Decimal16Value d16;
70  bool overflow = false;
71 
72  d16 = Decimal16Value::FromInt(ColumnType::CreateDecimalType(27, 18), -25559, &overflow);
73  EXPECT_FALSE(overflow);
74  VerifyToString(d16, ColumnType::CreateDecimalType(27, 18), "-25559.000000000000000000");
75 
76  d16 = Decimal16Value::FromInt(ColumnType::CreateDecimalType(36, 29), 32130, &overflow);
77  EXPECT_FALSE(overflow);
79  "32130.00000000000000000000000000000");
80 
81  d16 = Decimal16Value::FromInt(ColumnType::CreateDecimalType(38, 38), 1, &overflow);
82  EXPECT_TRUE(overflow);
83 
84  // Smaller decimal types can't overflow here since the FE should never generate
85  // that.
86 }
87 
88 TEST(DoubleToDecimal, Basic) {
94 
95  Decimal4Value d4;
96  Decimal8Value d8;
97  Decimal16Value d16;
98 
99  bool overflow = false;
100  d4 = Decimal4Value::FromDouble(t1, 1.1, &overflow);
101  EXPECT_FALSE(overflow);
102  EXPECT_EQ(d4.value(), 1);
103  VerifyToString(d4, t1, "1");
104 
105  d4 = Decimal4Value::FromDouble(t4, 1, &overflow);
106  EXPECT_FALSE(overflow);
107  EXPECT_EQ(d4.value(), 1);
108  VerifyToString(d4, t4, "1");
109 
110  d4 = Decimal4Value::FromDouble(t4, 0, &overflow);
111  EXPECT_FALSE(overflow);
112  EXPECT_EQ(d4.value(), 0);
113  VerifyToString(d4, t4, "0");
114 
115  d4 = Decimal4Value::FromDouble(t4, -1, &overflow);
116  EXPECT_FALSE(overflow);
117  EXPECT_EQ(d4.value(), -1);
118  VerifyToString(d4, t4, "-1");
119 
120  d4 = Decimal4Value::FromDouble(t5, 0.1, &overflow);
121  EXPECT_FALSE(overflow);
122  EXPECT_EQ(d4.value(), 1);
123  VerifyToString(d4, t5, "0.1");
124 
125  d4 = Decimal4Value::FromDouble(t5, 0.0, &overflow);
126  EXPECT_FALSE(overflow);
127  EXPECT_EQ(d4.value(), 0);
128  VerifyToString(d4, t5, "0.0");
129 
130  d4 = Decimal4Value::FromDouble(t5, -0.1, &overflow);
131  EXPECT_FALSE(overflow);
132  EXPECT_EQ(d4.value(), -1);
133  VerifyToString(d4, t5, "-0.1");
134 
135  overflow = false;
136  d8 = Decimal8Value::FromDouble(t2, -100.1, &overflow);
137  EXPECT_FALSE(overflow);
138  EXPECT_EQ(d8.value(), -10010000);
139  VerifyToString(d8, t2, "-100.10000");
140 
141  overflow = false;
142  d16 = Decimal16Value::FromDouble(t3, -.1, &overflow);
143  EXPECT_FALSE(overflow);
144  EXPECT_EQ(d16.value(), -1000000000);
145  VerifyToString(d16, t3, "-0.1000000000");
146 
147  // Test overflow
148  overflow = false;
149  Decimal4Value::FromDouble(t1, 999999999.123, &overflow);
150  EXPECT_FALSE(overflow);
151 
152  overflow = false;
153  Decimal4Value::FromDouble(t1, 1234567890.1, &overflow);
154  EXPECT_TRUE(overflow);
155 
156  overflow = false;
157  Decimal8Value::FromDouble(t1, -1234567890.123, &overflow);
158  EXPECT_TRUE(overflow);
159 
160  overflow = false;
161  Decimal8Value::FromDouble(t2, 99999.1234567, &overflow);
162  EXPECT_FALSE(overflow);
163 
164  overflow = false;
165  Decimal8Value::FromDouble(t2, 100000.1, &overflow);
166  EXPECT_TRUE(overflow);
167 
168  overflow = false;
169  Decimal8Value::FromDouble(t2, -123456.123, &overflow);
170  EXPECT_TRUE(overflow);
171 
172  overflow = false;
173  d16 = Decimal16Value::FromDouble(t3, 0.1234, &overflow);
174  EXPECT_FALSE(overflow);
175  VerifyToString(d16, t3, "0.1234000000");
176 
177  overflow = false;
178  Decimal16Value::FromDouble(t3, 1.1, &overflow);
179  EXPECT_TRUE(overflow);
180 
181  overflow = false;
182  Decimal16Value::FromDouble(t3, -1.1, &overflow);
183  EXPECT_TRUE(overflow);
184 }
185 
186 TEST(StringToDecimal, Basic) {
191 
208 
211  StringToAllDecimals("-1234", t2, -123400, StringParser::PARSE_SUCCESS);
219  StringToAllDecimals("00012.3", t2, 1230, StringParser::PARSE_SUCCESS);
220  StringToAllDecimals("-00012.3", t2, -1230, StringParser::PARSE_SUCCESS);
221 
222  StringToAllDecimals("123.45", t2, 12345, StringParser::PARSE_SUCCESS);
225  StringToAllDecimals(" 123.4 ", t4, 12340000, StringParser::PARSE_SUCCESS);
226  StringToAllDecimals("-123.45", t4, -12345000, StringParser::PARSE_SUCCESS);
227  StringToAllDecimals("-123.456", t2, -12345, StringParser::PARSE_UNDERFLOW);
228 
244  StringToAllDecimals("1e9999999999999999999", t1, 100, StringParser::PARSE_OVERFLOW);
245 
252  StringToAllDecimals(".00011e5 ", t3, 11, StringParser::PARSE_SUCCESS);
256 }
257 
258 TEST(StringToDecimal, LargeDecimals) {
262 
268 
269  VerifyParse(".1234567890", t2,
271  VerifyParse("-.1234567890", t2,
273  VerifyParse(".12345678900", t2,
275  VerifyParse("-.12345678900", t2,
277  VerifyParse(".1234567890", t2,
279  VerifyParse("-.1234567890", t2,
281  VerifyParse(".12345678900", t2,
283  VerifyParse("-.12345678900", t2,
285 
286  // Up to 8 digits with 5 before the decimal and 3 after.
287  VerifyParse("12345.678", t3,
289  VerifyParse("-12345.678", t3,
291  VerifyParse("123456.78", t3,
293  VerifyParse("1234.5678", t3,
295  VerifyParse("12345.678", t3,
297  VerifyParse("-12345.678", t3,
299  VerifyParse("123456.78", t3,
301  VerifyParse("1234.5678", t3,
303 
304  // Test max unscaled value for each of the decimal types.
305  VerifyParse("999999999", ColumnType::CreateDecimalType(9, 0),
307  VerifyParse("99999.9999", ColumnType::CreateDecimalType(9, 4),
309  VerifyParse("0.999999999", ColumnType::CreateDecimalType(9, 9),
311  VerifyParse("-999999999", ColumnType::CreateDecimalType(9, 0),
313  VerifyParse("-99999.9999", ColumnType::CreateDecimalType(9, 4),
315  VerifyParse("-0.999999999", ColumnType::CreateDecimalType(9, 9),
317  VerifyParse("1000000000", ColumnType::CreateDecimalType(9, 0),
319  VerifyParse("-1000000000", ColumnType::CreateDecimalType(9, 0),
321 
322  VerifyParse("999999999999999999", ColumnType::CreateDecimalType(18, 0),
323  Decimal8Value(999999999999999999ll), StringParser::PARSE_SUCCESS);
324  VerifyParse("999999.999999999999", ColumnType::CreateDecimalType(18, 12),
325  Decimal8Value(999999999999999999ll), StringParser::PARSE_SUCCESS);
326  VerifyParse(".999999999999999999", ColumnType::CreateDecimalType(18, 18),
327  Decimal8Value(999999999999999999ll), StringParser::PARSE_SUCCESS);
328  VerifyParse("-999999999999999999", ColumnType::CreateDecimalType(18, 0),
329  Decimal8Value(-999999999999999999ll), StringParser::PARSE_SUCCESS);
330  VerifyParse("-999999.999999999999", ColumnType::CreateDecimalType(18, 12),
331  Decimal8Value(-999999999999999999ll), StringParser::PARSE_SUCCESS);
332  VerifyParse("-.999999999999999999", ColumnType::CreateDecimalType(18, 18),
333  Decimal8Value(-999999999999999999ll), StringParser::PARSE_SUCCESS);
334  VerifyParse("1000000000000000000", ColumnType::CreateDecimalType(18, 0),
336  VerifyParse("01000000000000000000", ColumnType::CreateDecimalType(18, 0),
338 
340  VerifyParse("99999999999999999999999999999999999999",
343  VerifyParse("99999999999999999999999999999999999999e1",
346  VerifyParse("999999999999999999999999999999999999990e-1",
349  VerifyParse("999999999999999999999999999999999.99999",
352  VerifyParse(".99999999999999999999999999999999999999",
355  VerifyParse("-99999999999999999999999999999999999999",
358  VerifyParse("-999999999999999999999999999999999.99999",
361  VerifyParse("-.99999999999999999999999999999999999999",
364  VerifyParse("-.99999999999999999999999999999999999999e1",
367  VerifyParse("-.999999999999999999999999999999999999990e-1",
370  VerifyParse("-.999999999999999999999999999999999999990000000000000000e-20",
372  Decimal16Value(-result / DecimalUtil::GetScaleMultiplier<int128_t>(20)),
374  VerifyParse("100000000000000000000000000000000000000",
377  VerifyParse("-100000000000000000000000000000000000000",
380 }
381 
382 TEST(DecimalTest, Overflow) {
383  bool overflow = false;
385 
386  Decimal16Value result;
388  Decimal16Value two(2);
389  Decimal16Value one(1);
390  Decimal16Value zero(0);
391 
392  // Adding same sign
393  overflow = false;
394  d_max.Add<int128_t>(t1, one, t1, 0, &overflow);
395  EXPECT_TRUE(overflow);
396 
397  overflow = false;
398  one.Add<int128_t>(t1, d_max, t1, 0, &overflow);
399  EXPECT_TRUE(overflow);
400 
401  overflow = false;
402  d_max.Add<int128_t>(t1, d_max, t1, 0, &overflow);
403  EXPECT_TRUE(overflow);
404 
405  overflow = false;
406  result = d_max.Add<int128_t>(t1, zero, t1, 0, &overflow);
407  EXPECT_FALSE(overflow);
408  EXPECT_TRUE(result.value() == d_max.value());
409 
410  // Subtracting same sign
411  overflow = false;
412  result = d_max.Subtract<int128_t>(t1, one, t1, 0, &overflow);
413  EXPECT_FALSE(overflow);
414 
415  overflow = false;
416  EXPECT_TRUE(result.value() == d_max.value() - 1);
417  result = one.Subtract<int128_t>(t1, d_max, t1, 0, &overflow);
418  EXPECT_FALSE(overflow);
419 
420  overflow = false;
421  EXPECT_TRUE(result.value() == -(d_max.value() - 1));
422  result = d_max.Subtract<int128_t>(t1, d_max, t1, 0, &overflow);
423  EXPECT_FALSE(overflow);
424 
425  overflow = false;
426  EXPECT_TRUE(result.value() == 0);
427  result = d_max.Subtract<int128_t>(t1, zero, t1, 0, &overflow);
428  EXPECT_FALSE(overflow);
429  EXPECT_TRUE(result.value() == d_max.value());
430 
431  // Adding different sign
432  overflow = false;
433  result = d_max.Add<int128_t>(t1, -one, t1, 0, &overflow);
434  EXPECT_FALSE(overflow);
435  EXPECT_TRUE(result.value() == d_max.value() - 1);
436 
437  overflow = false;
438  result = one.Add<int128_t>(t1, -d_max, t1, 0, &overflow);
439  EXPECT_FALSE(overflow);
440  EXPECT_TRUE(result.value() == -(d_max.value() - 1));
441 
442  overflow = false;
443  result = d_max.Add<int128_t>(t1, -d_max, t1, 0, &overflow);
444  EXPECT_FALSE(overflow);
445  EXPECT_TRUE(result.value() == 0);
446 
447  overflow = false;
448  result = d_max.Add<int128_t>(t1, -zero, t1, 0, &overflow);
449  EXPECT_FALSE(overflow);
450  EXPECT_TRUE(result.value() == d_max.value());
451 
452  // Subtracting different sign
453  overflow = false;
454  d_max.Subtract<int128_t>(t1, -one, t1, 0, &overflow);
455  EXPECT_TRUE(overflow);
456  one.Subtract<int128_t>(t1, -d_max, t1, 0, &overflow);
457  EXPECT_TRUE(overflow);
458 
459  overflow = false;
460  d_max.Subtract<int128_t>(t1, -d_max, t1, 0, &overflow);
461  EXPECT_TRUE(overflow);
462 
463  overflow = false;
464  result = d_max.Subtract<int128_t>(t1, -zero, t1, 0, &overflow);
465  EXPECT_FALSE(overflow);
466  EXPECT_TRUE(result.value() == d_max.value());
467 
468  // Multiply
469  overflow = false;
470  result = d_max.Multiply<int128_t>(t1, one, t1, 0, &overflow);
471  EXPECT_FALSE(overflow);
472  EXPECT_TRUE(result.value() == d_max.value());
473 
474  overflow = false;
475  result = d_max.Multiply<int128_t>(t1, -one, t1, 0, &overflow);
476  EXPECT_FALSE(overflow);
477  EXPECT_TRUE(result.value() == -d_max.value());
478 
479  overflow = false;
480  result = d_max.Multiply<int128_t>(t1, two, t1, 0, &overflow);
481  EXPECT_TRUE(overflow);
482 
483  overflow = false;
484  result = d_max.Multiply<int128_t>(t1, -two, t1, 0, &overflow);
485  EXPECT_TRUE(overflow);
486 
487  overflow = false;
488  result = d_max.Multiply<int128_t>(t1, d_max, t1, 0, &overflow);
489  EXPECT_TRUE(overflow);
490 
491  overflow = false;
492  result = d_max.Multiply<int128_t>(t1, -d_max, t1, 0, &overflow);
493  EXPECT_TRUE(overflow);
494 
495  // Multiply by 0
496  overflow = false;
497  result = zero.Multiply<int128_t>(t1, one, t1, 0, &overflow);
498  EXPECT_FALSE(overflow);
499  EXPECT_TRUE(result.value() == 0);
500 
501  overflow = false;
502  result = one.Multiply<int128_t>(t1, zero, t1, 0, &overflow);
503  EXPECT_FALSE(overflow);
504  EXPECT_TRUE(result.value() == 0);
505 
506  overflow = false;
507  result = zero.Multiply<int128_t>(t1, zero, t1, 0, &overflow);
508  EXPECT_FALSE(overflow);
509  EXPECT_TRUE(result.value() == 0);
510 
511  // Adding any value with scale to (38, 0) will overflow if the most significant
512  // digit is set.
514  overflow = false;
515  result = d_max.Add<int128_t>(t1, zero, t2, 1, &overflow);
516  EXPECT_TRUE(overflow);
517 
518  // Add 37 9's (with scale 0)
520  overflow = false;
521  result = d3.Add<int128_t>(t1, zero, t2, 1, &overflow);
522  EXPECT_FALSE(overflow);
523  EXPECT_EQ(result.value(), DecimalUtil::MAX_UNSCALED_DECIMAL - 9);
524 
525  overflow = false;
526  result = d3.Add<int128_t>(t1, one, t2, 1, &overflow);
527  EXPECT_FALSE(overflow);
528  EXPECT_EQ(result.value(), DecimalUtil::MAX_UNSCALED_DECIMAL - 8);
529 
530  // Mod
531  overflow = false;
532  bool is_nan;
534  result = d3.Mod<int128_t>(t1, d3, t3, 20, &is_nan, &overflow);
535  EXPECT_TRUE(overflow);
536  EXPECT_FALSE(is_nan);
537 
538  overflow = false;
539  result = d3.Mod<int128_t>(t1, two, t1, 0, &is_nan, &overflow);
540  EXPECT_FALSE(overflow);
541  EXPECT_FALSE(is_nan);
542  EXPECT_EQ(result.value(), DecimalUtil::MAX_UNSCALED_DECIMAL % 2);
543 
544  result = d3.Mod<int128_t>(t1, zero, t2, 1, &is_nan, &overflow);
545  EXPECT_TRUE(is_nan);
546 }
547 
548 // Overflow cases only need to test with Decimal16Value with max precision. In
549 // the other cases, the planner should have casted the values to this precision.
550 // Add/Subtract/Mod cannot overflow the scale. With division, we always handle the case
551 // where the result scale needs to be adjusted.
552 TEST(DecimalTest, MultiplyScaleOverflow) {
553  bool overflow = false;
554  Decimal16Value x(1);
555  Decimal16Value y(3);
556  ColumnType max_scale = ColumnType::CreateDecimalType(38, 38);
557 
558  // x = 0.<37 zeroes>1. y = 0.<37 zeroes>3 The result should be 0.<74 zeroes>3.
559  // Since this can't be represented, the result will truncate to 0.
560  Decimal16Value result = x.Multiply<int128_t>(max_scale, y, max_scale, 38, &overflow);
561  EXPECT_TRUE(result.value() == 0);
562  EXPECT_FALSE(overflow);
563 
565  ColumnType scale_37 = ColumnType::CreateDecimalType(38, 37);
566  // x = 0.<36 zeroes>1, y = 0.3
567  // The result should be 0.<37 zeroes>11, which would require scale = 39.
568  // The truncated version should 0.<37 zeroes>3.
569  result = x.Multiply<int128_t>(scale_37, y, scale_1, 38, &overflow);
570  EXPECT_TRUE(result.value() == 3);
571  EXPECT_FALSE(overflow);
572 }
573 
574 enum Op {
580 };
581 
582 // Implementation of decimal rules. This is handled in the planner in the normal
583 // execution paths.
584 ColumnType GetResultType(const ColumnType& t1, const ColumnType& t2, Op op) {
585  switch (op) {
586  case ADD:
587  case SUBTRACT:
589  max(t1.scale, t2.scale) +
590  max(t1.precision - t1.scale, t2.precision - t2.scale) + 1,
591  max(t1.scale, t2.scale));
592  case MULTIPLY:
594  t1.precision + t2.precision, t1.scale + t2.scale);
595  case DIVIDE:
597  min(38,
598  t1.precision - t1.scale + t2.scale + max(4, t1.scale + t2.precision + 1)),
599  max(4, t1.scale + t2.precision + 1));
600  case MOD:
602  min(t1.precision - t1.scale, t2.precision - t2.scale) + max(t1.scale, t2.scale),
603  max(t1.scale, t2.scale));
604  default:
605  DCHECK(false);
606  return ColumnType();
607  }
608 }
609 
610 template<typename T>
611 void VerifyFuzzyEquals(const T& actual, const ColumnType& t,
612  double expected, bool overflow) {
613  double actual_d = actual.ToDouble(t);
614  EXPECT_FALSE(overflow);
615  EXPECT_TRUE(fabs(actual_d - expected) < MAX_ERROR)
616  << actual_d << " != " << expected;
617 }
618 
619 TEST(DecimalArithmetic, Basic) {
622  ColumnType t1_plus_2 = GetResultType(t1, t2, ADD);
623  ColumnType t1_times_2 = GetResultType(t1, t2, MULTIPLY);
624 
625  Decimal4Value d1(123456789);
626  Decimal4Value d2(23456);
627  Decimal4Value d3(-23456);
628  double d1_double = d1.ToDouble(t1);
629  double d2_double = d2.ToDouble(t2);
630  double d3_double = d3.ToDouble(t2);
631 
632  bool overflow = false;
633  // TODO: what's the best way to author a bunch of tests like this?
634  VerifyFuzzyEquals(d1.Add<int64_t>(t1, d2, t2, t1_plus_2.scale, &overflow),
635  t1_plus_2, d1_double + d2_double, overflow);
636  VerifyFuzzyEquals(d1.Add<int64_t>(t1, d3, t2, t1_plus_2.scale, &overflow),
637  t1_plus_2, d1_double + d3_double, overflow);
638  VerifyFuzzyEquals(d1.Subtract<int64_t>(t1, d2, t2, t1_plus_2.scale, &overflow),
639  t1_plus_2, d1_double - d2_double, overflow);
640  VerifyFuzzyEquals(d1.Subtract<int64_t>(t1, d3, t2, t1_plus_2.scale, &overflow),
641  t1_plus_2, d1_double - d3_double, overflow);
642  VerifyFuzzyEquals(d1.Multiply<int128_t>(t1, d2, t2, t1_times_2.scale, &overflow),
643  t1_times_2, d1_double * d2_double, overflow);
644  VerifyFuzzyEquals(d1.Multiply<int64_t>(t1, d3, t2, t1_times_2.scale, &overflow),
645  t1_times_2, d1_double * d3_double, overflow);
646 }
647 
648 TEST(DecimalArithmetic, Divide) {
649  // Exhaustively test precision and scale for 4 byte decimals. The logic errors tend
650  // to be by powers of 10 so not testing the other decimal types is okay.
651  Decimal4Value x(123456789);
652  Decimal4Value y(234);
653  for (int numerator_p = 1; numerator_p <= 9; ++numerator_p) {
654  for (int numerator_s = 0; numerator_s <= numerator_p; ++numerator_s) {
655  for (int denominator_p = 1; denominator_p <= 3; ++denominator_p) {
656  for (int denominator_s = 0; denominator_s <= denominator_p; ++denominator_s) {
657  ColumnType t1 = ColumnType::CreateDecimalType(numerator_p, numerator_s);
658  ColumnType t2 = ColumnType::CreateDecimalType(denominator_p, denominator_s);
659  ColumnType t3 = GetResultType(t1, t2, DIVIDE);
660  bool is_nan = false;
661  bool is_overflow = false;
662  Decimal8Value r = x.Divide<int64_t>(t1, y, t2, t3.scale, &is_nan, &is_overflow);
663  double approx_x = x.ToDouble(t1);
664  double approx_y = y.ToDouble(t2);
665  double approx_r = r.ToDouble(t3);
666  double expected_r = approx_x / approx_y;
667 
668  EXPECT_FALSE(is_nan);
669  EXPECT_FALSE(is_overflow);
670  if (fabs(approx_r - expected_r) > MAX_ERROR) {
671  LOG(ERROR) << approx_r << " " << expected_r;
672  LOG(ERROR) << x.ToString(t1) << "/" << y.ToString(t2)
673  << "=" << r.ToString(t3);
674  EXPECT_TRUE(false);
675  }
676  }
677  }
678  }
679  }
680  // Divide by 0
681  bool is_nan = false;
682  bool is_overflow = false;
683  Decimal8Value r = x.Divide<int64_t>(ColumnType::CreateDecimalType(10, 0),
684  Decimal4Value(0), ColumnType::CreateDecimalType(2,0), 4, &is_nan, &is_overflow);
685  EXPECT_TRUE(is_nan) << "Expected NaN, got: " << r;
686  EXPECT_FALSE(is_overflow);
687 
688  // In this case, we are dividing large precision decimals meaning the resulting
689  // decimal underflows. The resulting type is (38,38).
691  Decimal16Value x2(53994500);
692  Decimal16Value y2(5399450);
693  is_nan = false;
694  is_overflow = false;
695  x2.Divide<int128_t>(t4, y2, t4, 38, &is_nan, &is_overflow);
696  EXPECT_TRUE(is_overflow);
697  EXPECT_FALSE(is_nan);
698 }
699 
700 TEST(DecimalArithmetic, DivideLargeScales) {
703  ColumnType t3 = GetResultType(t1, t2, DIVIDE);
705  const char* data = "319391280635.61476055";
706  Decimal16Value x =
707  StringParser::StringToDecimal<int128_t>(data, strlen(data), t1, &result);
708  Decimal16Value y(10000);
709  bool is_nan = false;
710  bool is_overflow = false;
711  Decimal16Value r = x.Divide<int128_t>(t1, y, t2, t3.scale, &is_nan, &is_overflow);
712  VerifyToString(r, t3, "31939128.06356147605500000000000000000");
713  EXPECT_FALSE(is_nan);
714  EXPECT_FALSE(is_overflow);
715 
716  y = -y;
717  r = x.Divide<int128_t>(t1, y, t2, t3.scale, &is_nan, &is_overflow);
718  VerifyToString(r, t3, "-31939128.06356147605500000000000000000");
719  EXPECT_FALSE(is_nan);
720  EXPECT_FALSE(is_overflow);
721 }
722 
723 template<typename T>
724 DecimalValue<T> RandDecimal(int max_precision) {
725  T val = 0;
726  int precision = rand() % max_precision;
727  for (int i = 0; i < precision; ++i) {
728  int digit = rand() % 10;
729  val = val * 10 + digit;
730  }
731  return DecimalValue<T>(rand() % 2 == 0 ? val : -val);
732 }
733 
734 int DoubleCompare(double x, double y) {
735  if (x < y) return -1;
736  if (x > y) return 1;
737  return 0;
738 }
739 
740 // Randomly test decimal operations, comparing the result with a double ground truth.
741 TEST(DecimalArithmetic, RandTesting) {
742  int NUM_ITERS = 1000000;
743  int seed = time(0);
744  LOG(ERROR) << "Seed: " << seed;
745  for (int i = 0; i < NUM_ITERS; ++i) {
746  // TODO: double is too imprecise so we can't test with high scales.
747  int p1 = rand() % 12 + 1;
748  int s1 = rand() % min(4, p1);
749  int p2 = rand() % 12 + 1;
750  int s2 = rand() % min(4, p2);
751 
752  DecimalValue<int64_t> dec1 = RandDecimal<int64_t>(p1);
753  DecimalValue<int64_t> dec2 = RandDecimal<int64_t>(p2);
756  double t1_d = dec1.ToDouble(t1);
757  double t2_d = dec2.ToDouble(t2);
758 
759  ColumnType add_t = GetResultType(t1, t2, ADD);
760 
761  bool overflow = false;
762  VerifyFuzzyEquals(dec1.Add<int64_t>(t1, dec2, t2, add_t.scale, &overflow),
763  add_t, t1_d + t2_d, overflow);
764  VerifyFuzzyEquals(dec1.Subtract<int64_t>(t1, dec2, t2, add_t.scale, &overflow),
765  add_t, t1_d - t2_d, overflow);
766 #if 0
767  TODO: doubles are not precise enough for this
768  ColumnType multiply_t = GetResultType(t1, t2, MULTIPLY);
769  ColumnType divide_t = GetResultType(t1, t2, DIVIDE);
770  // double is too imprecise to generate the right result.
771  // TODO: compare against the ground truth using the multi precision float library.
772  VerifyFuzzyEquals(dec1.Multiply<int64_t>(
773  t1, dec2, t2, multiply_t.scale), multiply_t, t1_d * t2_d);
774  if (dec2.value() != 0) {
775  VerifyFuzzyEquals(dec1.Divide<int64_t>(
776  t1, dec2, t2, divide_t.scale), divide_t, t1_d / t2_d);
777  }
778 #endif
779 
780  EXPECT_EQ(dec1.Compare(t1, dec2, t2), DoubleCompare(t1_d, t2_d));
781  EXPECT_TRUE(dec1.Compare(t1, dec1, t1) == 0);
782  EXPECT_TRUE(dec2.Compare(t2, dec2, t2) == 0);
783  }
784 }
785 
786 }
787 
788 int main(int argc, char **argv) {
789  ::testing::InitGoogleTest(&argc, argv);
791  return RUN_ALL_TESTS();
792 }
const T & value() const
static DecimalValue FromDouble(const ColumnType &t, double d, bool *overflow)
Definition: decimal-value.h:52
int main(int argc, char **argv)
int precision
Only set if type == TYPE_DECIMAL.
Definition: types.h:68
DecimalValue< int128_t > Decimal16Value
TEST(AtomicTest, Basic)
Definition: atomic-test.cc:28
void VerifyEquals(const DecimalValue< T > &t1, const DecimalValue< T > &t2)
Definition: decimal-test.cc:36
DecimalValue< RESULT_T > Subtract(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *overflow) const
static int128_t MAX_UNSCALED_DECIMAL
Maximum absolute value of int128_t that we use. This is 38 digits of 9's.
Definition: decimal-util.h:32
DecimalValue< int64_t > Decimal8Value
DecimalValue< int32_t > Decimal4Value
ColumnType GetResultType(const ColumnType &t1, const ColumnType &t2, Op op)
int DoubleCompare(double x, double y)
static const double MAX_ERROR
Definition: decimal-test.cc:33
DecimalValue< RESULT_T > Divide(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *is_nan, bool *overflow) const
is_nan is set to true if 'other' is 0. The value returned is undefined.
static DecimalValue FromInt(const ColumnType &t, int64_t d, bool *overflow)
Assigns *result as a decimal.
Definition: decimal-value.h:67
std::string ToString(const ColumnType &type) const
static void InitMaxUnscaledDecimal()
Initializes MAX_UNSCALED_DECIMAL. Must be called once before using it.
Definition: decimal-util.cc:22
DecimalValue< T > RandDecimal(int max_precision)
void VerifyToString(const T &decimal, const ColumnType &t, const string &expected)
Definition: decimal-test.cc:57
void VerifyFuzzyEquals(const T &actual, const ColumnType &t, double expected, bool overflow)
DecimalValue< RESULT_T > Multiply(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *overflow) const
DecimalValue< RESULT_T > Mod(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *is_nan, bool *overflow) const
is_nan is set to true if 'other' is 0. The value returned is undefined.
void VerifyParse(const string &s, const ColumnType &t, const DecimalValue< T > &expected_val, StringParser::ParseResult expected_result)
Definition: decimal-test.cc:44
int Compare(const DecimalValue &other) const
static ColumnType CreateDecimalType(int precision, int scale)
Definition: types.h:103
DecimalValue< RESULT_T > Add(const ColumnType &this_type, const DecimalValue &other, const ColumnType &other_type, int result_scale, bool *overflow) const
double ToDouble(const ColumnType &type) const
Returns an approximate double for this decimal.
__int128_t int128_t
We use the c++ int128_t type. This is stored using 16 bytes and very performant.
void StringToAllDecimals(const string &s, const ColumnType &t, int32_t val, StringParser::ParseResult result)
Definition: decimal-test.cc:61