unari arithm operations for decimal (partial support)

This commit is contained in:
chertus 2018-08-03 19:32:55 +03:00
parent e31e4e164f
commit a338f657d5
3 changed files with 55 additions and 12 deletions

View File

@ -602,7 +602,9 @@ struct AbsImpl
static inline ResultType apply(A a) static inline ResultType apply(A a)
{ {
if constexpr (std::is_integral_v<A> && std::is_signed_v<A>) if constexpr (std::is_same_v<A, __int128>)
return a < 0 ? -a : a;
else if constexpr (std::is_integral_v<A> && std::is_signed_v<A>)
return a < 0 ? static_cast<ResultType>(~a) + 1 : a; return a < 0 ? static_cast<ResultType>(~a) + 1 : a;
else if constexpr (std::is_integral_v<A> && std::is_unsigned_v<A>) else if constexpr (std::is_integral_v<A> && std::is_unsigned_v<A>)
return static_cast<ResultType>(a); return static_cast<ResultType>(a);
@ -1238,6 +1240,9 @@ struct FunctionUnaryArithmeticMonotonicity;
template <template <typename> class Op, typename Name, bool is_injective> template <template <typename> class Op, typename Name, bool is_injective>
class FunctionUnaryArithmetic : public IFunction class FunctionUnaryArithmetic : public IFunction
{ {
//static constexpr bool allow_decimal = std::is_same_v<Op<Int8>, NegateImpl<Int8>> || std::is_same_v<Op<Int8>, AbsImpl<Int8>>;
static constexpr bool allow_decimal = std::is_same_v<Op<Int8>, NegateImpl<Int8>>;
template <typename F> template <typename F>
static bool castType(const IDataType * type, F && f) static bool castType(const IDataType * type, F && f)
{ {
@ -1251,7 +1256,10 @@ class FunctionUnaryArithmetic : public IFunction
DataTypeInt32, DataTypeInt32,
DataTypeInt64, DataTypeInt64,
DataTypeFloat32, DataTypeFloat32,
DataTypeFloat64 DataTypeFloat64,
DataTypeDecimal<Int32>,
DataTypeDecimal<Int64>
//DataTypeDecimal<Int128> // TODO: needs visitor
>(type, std::forward<F>(f)); >(type, std::forward<F>(f));
} }
@ -1274,8 +1282,17 @@ public:
DataTypePtr result; DataTypePtr result;
bool valid = castType(arguments[0].get(), [&](const auto & type) bool valid = castType(arguments[0].get(), [&](const auto & type)
{ {
using T0 = typename std::decay_t<decltype(type)>::FieldType; using DataType = std::decay_t<decltype(type)>;
result = std::make_shared<DataTypeNumber<typename Op<T0>::ResultType>>(); using T0 = typename DataType::FieldType;
if constexpr (IsDecimal<DataType>)
{
if constexpr (!allow_decimal)
return false;
result = std::make_shared<DataType>(type.getPrecision(), type.getScale());
}
else
result = std::make_shared<DataTypeNumber<typename Op<T0>::ResultType>>();
return true; return true;
}); });
if (!valid) if (!valid)
@ -1288,16 +1305,37 @@ public:
{ {
bool valid = castType(block.getByPosition(arguments[0]).type.get(), [&](const auto & type) bool valid = castType(block.getByPosition(arguments[0]).type.get(), [&](const auto & type)
{ {
using T0 = typename std::decay_t<decltype(type)>::FieldType; using DataType = std::decay_t<decltype(type)>;
if (auto col = checkAndGetColumn<ColumnVector<T0>>(block.getByPosition(arguments[0]).column.get())) using T0 = typename DataType::FieldType;
if constexpr (IsDecimal<DataType>)
{ {
auto col_res = ColumnVector<typename Op<T0>::ResultType>::create(); if constexpr (allow_decimal)
auto & vec_res = col_res->getData(); {
vec_res.resize(col->getData().size()); if (auto col = checkAndGetColumn<ColumnVector<T0, false>>(block.getByPosition(arguments[0]).column.get()))
UnaryOperationImpl<T0, Op<T0>>::vector(col->getData(), vec_res); {
block.getByPosition(result).column = std::move(col_res); auto col_res = ColumnVector<typename Op<T0>::ResultType, false>::create();
return true; auto & vec_res = col_res->getData();
vec_res.resize(col->getData().size());
UnaryOperationImpl<T0, Op<T0>>::vector(col->getData(), vec_res);
block.getByPosition(result).column = std::move(col_res);
return true;
}
}
} }
else
{
if (auto col = checkAndGetColumn<ColumnVector<T0>>(block.getByPosition(arguments[0]).column.get()))
{
auto col_res = ColumnVector<typename Op<T0>::ResultType>::create();
auto & vec_res = col_res->getData();
vec_res.resize(col->getData().size());
UnaryOperationImpl<T0, Op<T0>>::vector(col->getData(), vec_res);
block.getByPosition(result).column = std::move(col_res);
return true;
}
}
return false; return false;
}); });
if (!valid) if (!valid)

View File

@ -17,3 +17,6 @@
63.420000000 -21.420000000 41.580000000 890.820000000 -890.820000000 63.420000000 -21.420000000 41.580000000 890.820000000 -890.820000000
63.420000000000000000 -21.420000000000000000 41.580000000000000000 890.820000000000000000 -890.820000000000000000 0.495049504950495049 1.980198019801980198 63.420000000000000000 -21.420000000000000000 41.580000000000000000 890.820000000000000000 -890.820000000000000000 0.495049504950495049 1.980198019801980198
63.42 -21.42 41.58 890.82 -890.82 0.49 1.98 63.42 -21.42 41.58 890.82 -890.82 0.49 1.98
-42 42 42 0.420000000 0.420000000000000000 42.420 42.420000000 42.42
0 0 0 0.000000000 0.000000000000000000 0.000 0.000000000 0.00
42 -42 -42 -0.420000000 -0.420000000000000000 -42.420 -42.420000000 -42.42

View File

@ -49,4 +49,6 @@ SELECT 21 + h, 21 - h, 84 - h, 21 * h, -21 * h FROM test.decimal WHERE h > 0; --
SELECT 21 + i, 21 - i, 84 - i, 21 * i, -21 * i, 21 / i, 84 / i FROM test.decimal WHERE i > 0; SELECT 21 + i, 21 - i, 84 - i, 21 * i, -21 * i, 21 / i, 84 / i FROM test.decimal WHERE i > 0;
SELECT 21 + j, 21 - j, 84 - j, 21 * j, -21 * j, 21 / j, 84 / j FROM test.decimal WHERE j > 0; SELECT 21 + j, 21 - j, 84 - j, 21 * j, -21 * j, 21 / j, 84 / j FROM test.decimal WHERE j > 0;
SELECT a, -a, -b, -d, -e, -g, -h, -j from test.decimal ORDER BY a;
DROP TABLE IF EXISTS test.decimal; DROP TABLE IF EXISTS test.decimal;