|
19 | 19 | #include <Interpreters/Context.h> |
20 | 20 | #include <TestUtils/FunctionTestUtils.h> |
21 | 21 | #include <TestUtils/TiFlashTestBasic.h> |
| 22 | +#include <gtest/gtest.h> |
22 | 23 |
|
| 24 | +#include <Functions/divide.cpp> |
23 | 25 | #include <string> |
24 | 26 | #include <unordered_map> |
25 | 27 | #include <vector> |
@@ -103,6 +105,141 @@ class TestBinaryArithmeticFunctions : public DB::tests::FunctionTest |
103 | 105 | } |
104 | 106 | }; |
105 | 107 |
|
| 108 | +template <typename TYPE> |
| 109 | +void doTiDBDivideDecimalRoundInternalTest() |
| 110 | +{ |
| 111 | + auto apply = static_cast<TYPE (*)(TYPE, TYPE)>(&TiDBDivideFloatingImpl<TYPE, TYPE, false>::apply); |
| 112 | + |
| 113 | + constexpr TYPE max = std::numeric_limits<TYPE>::max(); |
| 114 | + // note: Int256's min is not equal to -max-1 |
| 115 | + // according to https://www.boost.org/doc/libs/1_60_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html |
| 116 | + constexpr TYPE min = std::numeric_limits<TYPE>::min(); |
| 117 | + |
| 118 | + // clang-format off |
| 119 | + const std::vector<std::array<TYPE, 3>> cases = { |
| 120 | + {1, 2, 1}, {1, -2, -1}, {-1, 2, -1}, {-1, -2, 1}, |
| 121 | + |
| 122 | + {0, 3, 0}, {0, -3, 0}, {0, 3, 0}, {0, -3, 0}, |
| 123 | + {1, 3, 0}, {1, -3, 0}, {-1, 3, 0}, {-1, -3, 0}, |
| 124 | + {2, 3, 1}, {2, -3, -1}, {-2, 3, -1}, {-2, -3, 1}, |
| 125 | + {3, 3, 1}, {3, -3, -1}, {-3, 3, -1}, {-3, -3, 1}, |
| 126 | + {4, 3, 1}, {4, -3, -1}, {-4, 3, -1}, {-4, -3, 1}, |
| 127 | + {5, 3, 2}, {5, -3, -2}, {-5, 3, -2}, {-5, -3, 2}, |
| 128 | + |
| 129 | + // ±max as divisor |
| 130 | + {0, max, 0}, {max/2-1, max, 0}, {max/2, max, 0}, {max/2+1, max, 1}, {max-1, max, 1}, {max, max, 1}, |
| 131 | + {-1, max, 0}, {-max/2+1, max, 0}, {-max/2, max, 0}, {-max/2-1, max, -1}, {-max+1, max, -1}, {-max, max, -1}, {min, max, -1}, |
| 132 | + {0, -max, 0}, {max/2-1, -max, 0}, {max/2, -max, 0}, {max/2+1, -max, -1}, {max-1, -max, -1}, {max, -max, -1}, |
| 133 | + {-1, -max, 0}, {-max/2+1, -max, 0}, {-max/2, -max, 0}, {-max/2-1, -max, 1}, {-max+1, -max, 1}, {-max, -max, 1}, {min, -max, 1}, |
| 134 | + |
| 135 | + // ±max as dividend |
| 136 | + {max, 1, max}, {max, 2, max/2+1}, {max, max/2-1, 2}, {max, max/2, 2}, {max, max/2+1, 2}, {max, max-1, 1}, |
| 137 | + {max, -1, -max}, {max, -2, -max/2-1}, {max, -max/2+1, -2}, {max, -max/2, -2}, {max, -max/2-1, -2}, {max, -max+1, -1}, |
| 138 | + {-max, 1, -max}, {-max, 2, -max/2-1}, {-max, max/2+1, -2}, {-max, max/2, -2}, {-max, max/2-1, -2}, {-max, max-1, -1}, |
| 139 | + {-max, -1, max}, {-max, -2, max/2+1}, {-max, -max/2-1, 2}, {-max, -max/2, 2}, {-max, -max/2+1, 2}, {-max, -max+1, 1}, |
| 140 | + }; |
| 141 | + // clang-format on |
| 142 | + |
| 143 | + for (const auto & expect : cases) |
| 144 | + { |
| 145 | + std::array<TYPE, 3> actual = {expect[0], expect[1], apply(expect[0], expect[1])}; |
| 146 | + ASSERT_EQ(expect, actual); |
| 147 | + } |
| 148 | +} |
| 149 | + |
| 150 | +TEST_F(TestBinaryArithmeticFunctions, TiDBDivideDecimalRoundInternal) |
| 151 | +try |
| 152 | +{ |
| 153 | + doTiDBDivideDecimalRoundInternalTest<Int32>(); |
| 154 | + doTiDBDivideDecimalRoundInternalTest<Int64>(); |
| 155 | + doTiDBDivideDecimalRoundInternalTest<Int128>(); |
| 156 | + doTiDBDivideDecimalRoundInternalTest<Int256>(); |
| 157 | +} |
| 158 | +CATCH |
| 159 | + |
| 160 | +TEST_F(TestBinaryArithmeticFunctions, TiDBDivideDecimalRound) |
| 161 | +try |
| 162 | +{ |
| 163 | + const String func_name = "tidbDivide"; |
| 164 | + |
| 165 | + // decimal32 |
| 166 | + { |
| 167 | + // int and decimal |
| 168 | + ASSERT_COLUMN_EQ( |
| 169 | + createColumn<Nullable<Decimal64>>(std::make_tuple(18, 4), {DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(0, 4)}), |
| 170 | + executeFunction( |
| 171 | + func_name, |
| 172 | + createColumn<Int32>({1, 1, 1, 1, 1}), |
| 173 | + createColumn<Decimal32>(std::make_tuple(20, 4), {DecimalField32(100000000, 4), DecimalField32(100010000, 4), DecimalField32(199990000, 4), DecimalField32(200000000, 4), DecimalField32(200010000, 4)}))); |
| 174 | + |
| 175 | + // decimal and decimal |
| 176 | + ASSERT_COLUMN_EQ( |
| 177 | + createColumn<Nullable<Decimal128>>(std::make_tuple(26, 8), {DecimalField128(10000, 8), DecimalField128(9999, 8), DecimalField128(5000, 8), DecimalField128(5000, 8), DecimalField128(5000, 8)}), |
| 178 | + executeFunction( |
| 179 | + func_name, |
| 180 | + createColumn<Decimal32>(std::make_tuple(18, 4), {DecimalField32(10000, 4), DecimalField32(10000, 4), DecimalField32(10000, 4), DecimalField32(10000, 4), DecimalField32(10000, 4)}), |
| 181 | + createColumn<Decimal32>(std::make_tuple(18, 4), {DecimalField32(100000000, 4), DecimalField32(100010000, 4), DecimalField32(199990000, 4), DecimalField32(200000000, 4), DecimalField32(200010000, 4)}))); |
| 182 | + } |
| 183 | + |
| 184 | + // decimal64 |
| 185 | + { |
| 186 | + // int and decimal |
| 187 | + ASSERT_COLUMN_EQ( |
| 188 | + createColumn<Nullable<Decimal64>>(std::make_tuple(18, 4), {DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(0, 4)}), |
| 189 | + executeFunction( |
| 190 | + func_name, |
| 191 | + createColumn<Int32>({1, 1, 1, 1, 1}), |
| 192 | + createColumn<Decimal64>(std::make_tuple(20, 4), {DecimalField64(100000000, 4), DecimalField64(100010000, 4), DecimalField64(199990000, 4), DecimalField64(200000000, 4), DecimalField64(200010000, 4)}))); |
| 193 | + |
| 194 | + // decimal and decimal |
| 195 | + ASSERT_COLUMN_EQ( |
| 196 | + createColumn<Nullable<Decimal128>>(std::make_tuple(26, 8), {DecimalField128(10000, 8), DecimalField128(9999, 8), DecimalField128(5000, 8), DecimalField128(5000, 8), DecimalField128(5000, 8)}), |
| 197 | + executeFunction( |
| 198 | + func_name, |
| 199 | + createColumn<Decimal64>(std::make_tuple(18, 4), {DecimalField64(10000, 4), DecimalField64(10000, 4), DecimalField64(10000, 4), DecimalField64(10000, 4), DecimalField64(10000, 4)}), |
| 200 | + createColumn<Decimal64>(std::make_tuple(18, 4), {DecimalField64(100000000, 4), DecimalField64(100010000, 4), DecimalField64(199990000, 4), DecimalField64(200000000, 4), DecimalField64(200010000, 4)}))); |
| 201 | + } |
| 202 | + |
| 203 | + // decimal128 |
| 204 | + { |
| 205 | + // int and decimal |
| 206 | + ASSERT_COLUMN_EQ( |
| 207 | + createColumn<Nullable<Decimal64>>(std::make_tuple(18, 4), {DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(0, 4)}), |
| 208 | + executeFunction( |
| 209 | + func_name, |
| 210 | + createColumn<Int32>({1, 1, 1, 1, 1}), |
| 211 | + createColumn<Decimal128>(std::make_tuple(20, 4), {DecimalField128(100000000, 4), DecimalField128(100010000, 4), DecimalField128(199990000, 4), DecimalField128(200000000, 4), DecimalField128(200010000, 4)}))); |
| 212 | + |
| 213 | + // decimal and decimal |
| 214 | + ASSERT_COLUMN_EQ( |
| 215 | + createColumn<Nullable<Decimal128>>(std::make_tuple(26, 8), {DecimalField128(10000, 8), DecimalField128(9999, 8), DecimalField128(5000, 8), DecimalField128(5000, 8), DecimalField128(5000, 8)}), |
| 216 | + executeFunction( |
| 217 | + func_name, |
| 218 | + createColumn<Decimal128>(std::make_tuple(18, 4), {DecimalField128(10000, 4), DecimalField128(10000, 4), DecimalField128(10000, 4), DecimalField128(10000, 4), DecimalField128(10000, 4)}), |
| 219 | + createColumn<Decimal128>(std::make_tuple(18, 4), {DecimalField128(100000000, 4), DecimalField128(100010000, 4), DecimalField128(199990000, 4), DecimalField128(200000000, 4), DecimalField128(200010000, 4)}))); |
| 220 | + } |
| 221 | + |
| 222 | + // decimal256 |
| 223 | + { |
| 224 | + // int and decimal |
| 225 | + ASSERT_COLUMN_EQ( |
| 226 | + createColumn<Nullable<Decimal64>>(std::make_tuple(18, 4), {DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(1, 4), DecimalField64(0, 4)}), |
| 227 | + executeFunction( |
| 228 | + func_name, |
| 229 | + createColumn<Int32>({1, 1, 1, 1, 1}), |
| 230 | + createColumn<Decimal256>(std::make_tuple(20, 4), {DecimalField256(Int256(100000000), 4), DecimalField256(Int256(100010000), 4), DecimalField256(Int256(199990000), 4), DecimalField256(Int256(200000000), 4), DecimalField256(Int256(200010000), 4)}))); |
| 231 | + |
| 232 | + // decimal and decimal |
| 233 | + ASSERT_COLUMN_EQ( |
| 234 | + createColumn<Nullable<Decimal128>>(std::make_tuple(26, 8), {DecimalField128(10000, 8), DecimalField128(9999, 8), DecimalField128(5000, 8), DecimalField128(5000, 8), DecimalField128(5000, 8)}), |
| 235 | + executeFunction( |
| 236 | + func_name, |
| 237 | + createColumn<Decimal256>(std::make_tuple(18, 4), {DecimalField256(Int256(10000), 4), DecimalField256(Int256(10000), 4), DecimalField256(Int256(10000), 4), DecimalField256(Int256(10000), 4), DecimalField256(Int256(10000), 4)}), |
| 238 | + createColumn<Decimal256>(std::make_tuple(18, 4), {DecimalField256(Int256(100000000), 4), DecimalField256(Int256(100010000), 4), DecimalField256(Int256(199990000), 4), DecimalField256(Int256(200000000), 4), DecimalField256(Int256(200010000), 4)}))); |
| 239 | + } |
| 240 | +} |
| 241 | +CATCH |
| 242 | + |
106 | 243 | TEST_F(TestBinaryArithmeticFunctions, TiDBDivideDecimal) |
107 | 244 | try |
108 | 245 | { |
|
0 commit comments