mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
Simplification #1416
This commit is contained in:
parent
d899d3f8f5
commit
9b914cf93e
@ -20,11 +20,9 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
/** Functions are logical links: and, or, not, xor.
|
||||
* Accept any numeric types, return a UInt8 containing 0 or 1.
|
||||
/** Return an UInt8 containing 0 or 1.
|
||||
*/
|
||||
|
||||
template <typename B>
|
||||
struct AndImpl
|
||||
{
|
||||
static inline bool isSaturable()
|
||||
@ -37,13 +35,12 @@ struct AndImpl
|
||||
return !a;
|
||||
}
|
||||
|
||||
static inline UInt8 apply(UInt8 a, B b)
|
||||
static inline UInt8 apply(UInt8 a, UInt8 b)
|
||||
{
|
||||
return a && b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename B>
|
||||
struct OrImpl
|
||||
{
|
||||
static inline bool isSaturable()
|
||||
@ -56,13 +53,12 @@ struct OrImpl
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline UInt8 apply(UInt8 a, B b)
|
||||
static inline UInt8 apply(UInt8 a, UInt8 b)
|
||||
{
|
||||
return a || b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename B>
|
||||
struct XorImpl
|
||||
{
|
||||
static inline bool isSaturable()
|
||||
@ -75,7 +71,7 @@ struct XorImpl
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline UInt8 apply(UInt8 a, B b)
|
||||
static inline UInt8 apply(UInt8 a, UInt8 b)
|
||||
{
|
||||
return (!a) != (!b);
|
||||
}
|
||||
@ -161,7 +157,7 @@ struct AssociativeOperationImpl<Op, 1>
|
||||
};
|
||||
|
||||
|
||||
template <template <typename> class Impl, typename Name>
|
||||
template <typename Impl, typename Name>
|
||||
class FunctionAnyArityLogical : public IFunction
|
||||
{
|
||||
public:
|
||||
@ -179,7 +175,7 @@ private:
|
||||
UInt8 x = !!in[i]->getUInt(0);
|
||||
if (has_res)
|
||||
{
|
||||
res = Impl<UInt8>::apply(res, x);
|
||||
res = Impl::apply(res, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -221,33 +217,6 @@ private:
|
||||
throw Exception("Unexpected type of column: " + column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool executeUInt8Type(const UInt8Container & uint8_vec, const IColumn * column, UInt8Container & res)
|
||||
{
|
||||
auto col = checkAndGetColumn<ColumnVector<T>>(column);
|
||||
if (!col)
|
||||
return false;
|
||||
const typename ColumnVector<T>::Container & other_vec = col->getData();
|
||||
size_t n = res.size();
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
res[i] = Impl<T>::apply(uint8_vec[i], other_vec[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void executeUInt8Other(const UInt8Container & uint8_vec, const IColumn * column, UInt8Container & res)
|
||||
{
|
||||
if (!executeUInt8Type<Int8 >(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<Int16>(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<Int32>(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<Int64>(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<UInt16>(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<UInt32>(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<UInt64>(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<Float32>(uint8_vec, column, res) &&
|
||||
!executeUInt8Type<Float64>(uint8_vec, column, res))
|
||||
throw Exception("Unexpected type of column: " + column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
public:
|
||||
String getName() const override
|
||||
{
|
||||
@ -289,16 +258,16 @@ public:
|
||||
bool has_consts = extractConstColumns(in, const_val);
|
||||
|
||||
// If this value uniquely determines the result, return it.
|
||||
if (has_consts && (in.empty() || Impl<UInt8>::apply(const_val, 0) == Impl<UInt8>::apply(const_val, 1)))
|
||||
if (has_consts && (in.empty() || Impl::apply(const_val, 0) == Impl::apply(const_val, 1)))
|
||||
{
|
||||
if (!in.empty())
|
||||
const_val = Impl<UInt8>::apply(const_val, 0);
|
||||
const_val = Impl::apply(const_val, 0);
|
||||
block.getByPosition(result).column = DataTypeUInt8().createColumnConst(rows, toField(const_val));
|
||||
return;
|
||||
}
|
||||
|
||||
/// If this value is a neutral element, let's forget about it.
|
||||
if (has_consts && Impl<UInt8>::apply(const_val, 0) == 0 && Impl<UInt8>::apply(const_val, 1) == 1)
|
||||
if (has_consts && Impl::apply(const_val, 0) == 0 && Impl::apply(const_val, 1) == 1)
|
||||
has_consts = false;
|
||||
|
||||
auto col_res = ColumnUInt8::create();
|
||||
@ -314,27 +283,21 @@ public:
|
||||
vec_res.resize(rows);
|
||||
}
|
||||
|
||||
/// Divide the input columns into UInt8 and the rest. The first will be processed more efficiently.
|
||||
/// col_res at each moment will either be at the end of uint8_in, or not contained in uint8_in.
|
||||
/// Convert all columns to UInt8
|
||||
UInt8ColumnPtrs uint8_in;
|
||||
ColumnRawPtrs other_in;
|
||||
Columns converted_columns;
|
||||
|
||||
for (const IColumn * column : in)
|
||||
{
|
||||
if (auto uint8_column = typeid_cast<const ColumnUInt8 *>(column))
|
||||
if (auto uint8_column = checkAndGetColumn<ColumnUInt8>(column))
|
||||
uint8_in.push_back(uint8_column);
|
||||
else
|
||||
other_in.push_back(column);
|
||||
}
|
||||
|
||||
/// You need at least one column in uint8_in, so that you can combine columns from other_in.
|
||||
if (uint8_in.empty())
|
||||
{
|
||||
if (other_in.empty())
|
||||
throw Exception("Logical error in FunctionAnyArityLogical: other_in is empty", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
convertToUInt8(other_in.back(), vec_res);
|
||||
other_in.pop_back();
|
||||
uint8_in.push_back(col_res.get());
|
||||
{
|
||||
auto converted_column = ColumnUInt8::create(rows);
|
||||
convertToUInt8(column, converted_column->getData());
|
||||
uint8_in.push_back(converted_column.get());
|
||||
converted_columns.emplace_back(std::move(converted_column));
|
||||
}
|
||||
}
|
||||
|
||||
/// Effeciently combine all the columns of the correct type.
|
||||
@ -342,18 +305,10 @@ public:
|
||||
{
|
||||
/// With a large block size, combining 6 columns per pass is the fastest.
|
||||
/// When small - more, is faster.
|
||||
AssociativeOperationImpl<Impl<UInt8>, 10>::execute(uint8_in, vec_res);
|
||||
AssociativeOperationImpl<Impl, 10>::execute(uint8_in, vec_res);
|
||||
uint8_in.push_back(col_res.get());
|
||||
}
|
||||
|
||||
/// Add all the columns of the wrong type one at a time.
|
||||
while (!other_in.empty())
|
||||
{
|
||||
executeUInt8Other(uint8_in[0]->getData(), other_in.back(), vec_res);
|
||||
other_in.pop_back();
|
||||
uint8_in[0] = col_res.get();
|
||||
}
|
||||
|
||||
/// This is possible if there is exactly one non-constant among the arguments, and it is of type UInt8.
|
||||
if (uint8_in[0] != col_res.get())
|
||||
vec_res.assign(uint8_in[0]->getData());
|
||||
|
Loading…
Reference in New Issue
Block a user