Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
multi-precision-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 <string>
16 #include <gtest/gtest.h>
17 
18 #include <boost/math/constants/constants.hpp>
19 #include "common/logging.h"
21 
22 #include "common/names.h"
23 
24 namespace mp = boost::multiprecision;
25 using std::max;
26 using std::min;
27 using std::numeric_limits;
28 
29 namespace impala {
30 
31 TEST(MultiPrecisionIntTest, Conversion) {
32  int128_t x = 0;
33  int256_t y = 0;
34  EXPECT_TRUE(ConvertToInt256(x) == 0);
35 
36  x = -1;
37  EXPECT_TRUE(ConvertToInt256(x) == -1);
38 
39  x = 1;
40  EXPECT_TRUE(ConvertToInt256(x) == 1);
41 
42  x = numeric_limits<int32_t>::max();
43  EXPECT_TRUE(ConvertToInt256(x) == numeric_limits<int32_t>::max());
44 
45  x = numeric_limits<int32_t>::min();
46  EXPECT_TRUE(ConvertToInt256(x) == numeric_limits<int32_t>::min());
47 
48  x = numeric_limits<int64_t>::max();
49  EXPECT_TRUE(ConvertToInt256(x) == numeric_limits<int64_t>::max());
50 
51  x = numeric_limits<int64_t>::min();
52  EXPECT_TRUE(ConvertToInt256(x) == numeric_limits<int64_t>::min());
53 
54  x = numeric_limits<int64_t>::max();
55  x *= 1000;
56  y = numeric_limits<int64_t>::max();
57  y *= 1000;
58  EXPECT_TRUE(ConvertToInt256(x) == y);
59 
60  x = -numeric_limits<int64_t>::max();
61  x *= 1000;
62  y = -numeric_limits<int64_t>::max();
63  y *= 1000;
64  EXPECT_TRUE(ConvertToInt256(x) == y);
65 
66  // Note: numer_limits<> doesn't work for int128_t.
67  static int128_t MAX_VALUE;
68  memset(&MAX_VALUE, 255, sizeof(MAX_VALUE));
69  uint8_t* buf = reinterpret_cast<uint8_t*>(&MAX_VALUE);
70  buf[15] = 127;
71 
72  bool overflow = false;
73  EXPECT_TRUE(ConvertToInt128(ConvertToInt256(x), MAX_VALUE, &overflow) == x);
74  EXPECT_FALSE(overflow);
75 }
76 
77 TEST(MultiPrecisionIntTest, HighLowBits) {
78  // x = 0x0f0e0d0c0b0a09080706050403020100
79  int128_t x;
80  for (int i = 0; i < sizeof(x); ++i) {
81  *(reinterpret_cast<uint8_t*>(&x) + i) = i;
82  }
83  EXPECT_EQ(LowBits(x), 0x0706050403020100);
84  EXPECT_EQ(HighBits(x), 0x0f0e0d0c0b0a0908);
85 }
86 
87 // Simple example of adding and subtracting numbers that use more than
88 // 64 bits.
89 TEST(MultiPrecisionIntTest, Example) {
90  int128_t v128 = 0;
91  v128 += int128_t(numeric_limits<uint64_t>::max());
92  v128 += int128_t(numeric_limits<uint64_t>::max());
93 
94  v128 -= int128_t(numeric_limits<uint64_t>::max());
95  EXPECT_EQ(v128, numeric_limits<uint64_t>::max());
96 
97  v128 -= int128_t(numeric_limits<uint64_t>::max());
98  EXPECT_EQ(v128, 0);
99 }
100 
101 // Example taken from:
102 // http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/fp_eg/aos.html
103 
104 template<typename T> inline T area_of_a_circle(T r) {
105  using boost::math::constants::pi;
106  return pi<T>() * r * r;
107 }
108 
109 TEST(MultiPrecisionFloatTest, Example) {
110  const float r_f(float(123) / 100);
111  const float a_f = area_of_a_circle(r_f);
112 
113  const double r_d(double(123) / 100);
114  const double a_d = area_of_a_circle(r_d);
115 
116  const mp::cpp_dec_float_50 r_mp(mp::cpp_dec_float_50(123) / 100);
117  const mp::cpp_dec_float_50 a_mp = area_of_a_circle(r_mp);
118 
119  stringstream ss;
120 
121  // Verify the results at different precisions.
122  ss.str("");
123  ss << setprecision(numeric_limits<float>::digits10)
124  << a_f;
125  EXPECT_EQ(ss.str(), "4.75292");
126 
127  ss.str("");
128  ss << std::setprecision(std::numeric_limits<double>::digits10)
129  << a_d;
130  EXPECT_EQ(ss.str(), "4.752915525616");
131 
132  ss.str("");
133  ss << std::setprecision(std::numeric_limits<mp::cpp_dec_float_50>::digits10)
134  << a_mp;
135  EXPECT_EQ(ss.str(), "4.7529155256159981904701331745635599135018975843146");
136 }
137 
138 }
139 
140 int main(int argc, char **argv) {
141  ::testing::InitGoogleTest(&argc, argv);
142  return RUN_ALL_TESTS();
143 }
int128_t ConvertToInt128(int256_t x, int128_t max_value, bool *overflow)
TEST(AtomicTest, Basic)
Definition: atomic-test.cc:28
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void > > int256_t
Define 256 bit int type.
int256_t ConvertToInt256(const int128_t &x)
T area_of_a_circle(T r)
uint64_t LowBits(int128_t x)
int main(int argc, char **argv)
uint64_t HighBits(int128_t x)
Get the high and low bits of an int128_t.
__int128_t int128_t
We use the c++ int128_t type. This is stored using 16 bytes and very performant.