#pragma once #include #include #include namespace DB { /** Арифметические функции: +, -, *, /, %, * intDiv (целочисленное деление), унарный минус. * Битовые функции: |, &, ^, ~. */ template struct BinaryOperationImpl { typedef typename Op::ResultType ResultType; static void vector_vector(const PODArray & a, const PODArray & b, PODArray & c) { size_t size = a.size(); for (size_t i = 0; i < size; ++i) c[i] = Op::apply(a[i], b[i]); } static void vector_constant(const PODArray & a, B b, PODArray & c) { size_t size = a.size(); for (size_t i = 0; i < size; ++i) c[i] = Op::apply(a[i], b); } static void constant_vector(A a, const PODArray & b, PODArray & c) { size_t size = b.size(); for (size_t i = 0; i < size; ++i) c[i] = Op::apply(a, b[i]); } static void constant_constant(A a, B b, ResultType & c) { c = Op::apply(a, b); } }; template struct UnaryOperationImpl { typedef typename Op::ResultType ResultType; static void vector(const PODArray & a, PODArray & c) { size_t size = a.size(); for (size_t i = 0; i < size; ++i) c[i] = Op::apply(a[i]); } static void constant(A a, ResultType & c) { c = Op::apply(a); } }; template struct PlusImpl { typedef typename NumberTraits::ResultOfAdditionMultiplication::Type ResultType; static inline ResultType apply(A a, B b) { /// Далее везде, static_cast - чтобы не было неправильного результата в выражениях вида Int64 c = UInt32(a) * Int32(-1). return static_cast(a) + b; } }; template struct MultiplyImpl { typedef typename NumberTraits::ResultOfAdditionMultiplication::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) * b; } }; template struct MinusImpl { typedef typename NumberTraits::ResultOfSubtraction::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) - b; } }; template struct DivideFloatingImpl { typedef typename NumberTraits::ResultOfFloatingPointDivision::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) / b; } }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" template inline void throwIfDivisionLeadsToFPE(A a, B b) { /// Возможно, лучше вместо проверок использовать siglongjmp? if (unlikely(b == 0)) throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION); /// http://avva.livejournal.com/2548306.html if (unlikely(std::is_signed::value && std::is_signed::value && a == std::numeric_limits::min() && b == -1)) throw Exception("Division of minimal signed number by minus one", ErrorCodes::ILLEGAL_DIVISION); } #pragma GCC diagnostic pop template struct DivideIntegralImpl { typedef typename NumberTraits::ResultOfIntegerDivision::Type ResultType; static inline ResultType apply(A a, B b) { throwIfDivisionLeadsToFPE(a, b); return static_cast(a) / b; } }; template struct ModuloImpl { typedef typename NumberTraits::ResultOfModulo::Type ResultType; static inline ResultType apply(A a, B b) { throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger::Type(a), typename NumberTraits::ToInteger::Type(b)); return typename NumberTraits::ToInteger::Type(a) % typename NumberTraits::ToInteger::Type(b); } }; template struct BitAndImpl { typedef typename NumberTraits::ResultOfBit::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) & static_cast(b); } }; template struct BitOrImpl { typedef typename NumberTraits::ResultOfBit::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) | static_cast(b); } }; template struct BitXorImpl { typedef typename NumberTraits::ResultOfBit::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) ^ static_cast(b); } }; template struct BitShiftLeftImpl { typedef typename NumberTraits::ResultOfBit::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) << static_cast(b); } }; template struct BitShiftRightImpl { typedef typename NumberTraits::ResultOfBit::Type ResultType; static inline ResultType apply(A a, B b) { return static_cast(a) >> static_cast(b); } }; template struct NegateImpl { typedef typename NumberTraits::ResultOfNegate::Type ResultType; static inline ResultType apply(A a) { return -a; } }; template struct BitNotImpl { typedef typename NumberTraits::ResultOfBitNot::Type ResultType; static inline ResultType apply(A a) { return ~static_cast(a); } }; template