#pragma once #include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; } /** Functions are logical links: and, or, not, xor. * Accept any numeric types, return a UInt8 containing 0 or 1. */ template struct AndImpl { static inline bool isSaturable() { return true; } static inline bool isSaturatedValue(UInt8 a) { return !a; } static inline UInt8 apply(UInt8 a, B b) { return a && b; } }; template struct OrImpl { static inline bool isSaturable() { return true; } static inline bool isSaturatedValue(UInt8 a) { return a; } static inline UInt8 apply(UInt8 a, B b) { return a || b; } }; template struct XorImpl { static inline bool isSaturable() { return false; } static inline bool isSaturatedValue(UInt8 a) { return false; } static inline UInt8 apply(UInt8 a, B b) { return (!a) != (!b); } }; template struct NotImpl { using ResultType = UInt8; static inline UInt8 apply(A a) { return !a; } }; using UInt8Container = ColumnUInt8::Container_t; using UInt8ColumnPtrs = std::vector; template struct AssociativeOperationImpl { /// Erases the N last columns from `in` (if there are less, then all) and puts into `result` their combination. static void execute(UInt8ColumnPtrs & in, UInt8Container & result) { if (N > in.size()) { AssociativeOperationImpl::execute(in, result); return; } AssociativeOperationImpl operation(in); in.erase(in.end() - N, in.end()); size_t n = result.size(); for (size_t i = 0; i < n; ++i) { result[i] = operation.apply(i); } } const UInt8Container & vec; AssociativeOperationImpl continuation; /// Remembers the last N columns from `in`. AssociativeOperationImpl(UInt8ColumnPtrs & in) : vec(in[in.size() - N]->getData()), continuation(in) {} /// Returns a combination of values in the i-th row of all columns stored in the constructor. inline UInt8 apply(size_t i) const { if (Op::isSaturable()) { UInt8 a = vec[i]; return Op::isSaturatedValue(a) ? a : continuation.apply(i); } else { return Op::apply(vec[i], continuation.apply(i)); } } }; template struct AssociativeOperationImpl { static void execute(UInt8ColumnPtrs & in, UInt8Container & result) { throw Exception("Logical error: AssociativeOperationImpl::execute called", ErrorCodes::LOGICAL_ERROR); } const UInt8Container & vec; AssociativeOperationImpl(UInt8ColumnPtrs & in) : vec(in[in.size() - 1]->getData()) {} inline UInt8 apply(size_t i) const { return vec[i]; } }; template