#pragma once #include #include #include #include #include #include #include #include #include namespace DB { /** Позволяет получить тип результата применения функций +, -, *, /, %, div (целочисленное деление). * Правила отличаются от используемых в C++. */ namespace NumberTraits { typedef boost::mpl::false_ Unsigned; typedef boost::mpl::true_ Signed; typedef boost::mpl::false_ Integer; typedef boost::mpl::true_ Floating; typedef boost::mpl::int_<8> Bits8; typedef boost::mpl::int_<16> Bits16; typedef boost::mpl::int_<32> Bits32; typedef boost::mpl::int_<64> Bits64; template struct Next; template <> struct Next { typedef Bits16 Type; }; template <> struct Next { typedef Bits32 Type; }; template <> struct Next { typedef Bits64 Type; }; template <> struct Next { typedef Bits64 Type; }; template struct Traits; template <> struct Traits { typedef Unsigned Sign; typedef Integer Floatness; typedef Bits8 Bits; }; template <> struct Traits { typedef Unsigned Sign; typedef Integer Floatness; typedef Bits16 Bits; }; template <> struct Traits { typedef Unsigned Sign; typedef Integer Floatness; typedef Bits32 Bits; }; template <> struct Traits { typedef Unsigned Sign; typedef Integer Floatness; typedef Bits64 Bits; }; template <> struct Traits { typedef Signed Sign; typedef Integer Floatness; typedef Bits8 Bits; }; template <> struct Traits { typedef Signed Sign; typedef Integer Floatness; typedef Bits16 Bits; }; template <> struct Traits { typedef Signed Sign; typedef Integer Floatness; typedef Bits32 Bits; }; template <> struct Traits { typedef Signed Sign; typedef Integer Floatness; typedef Bits64 Bits; }; template <> struct Traits { typedef Signed Sign; typedef Floating Floatness; typedef Bits32 Bits; }; template <> struct Traits { typedef Signed Sign; typedef Floating Floatness; typedef Bits64 Bits; }; template struct Construct; template <> struct Construct { typedef UInt8 Type; }; template <> struct Construct { typedef UInt16 Type; }; template <> struct Construct { typedef UInt32 Type; }; template <> struct Construct { typedef UInt64 Type; }; template <> struct Construct { typedef Float32 Type; }; template <> struct Construct { typedef Float32 Type; }; template <> struct Construct { typedef Float32 Type; }; template <> struct Construct { typedef Float64 Type; }; template <> struct Construct { typedef Int8 Type; }; template <> struct Construct { typedef Int16 Type; }; template <> struct Construct { typedef Int32 Type; }; template <> struct Construct { typedef Int64 Type; }; template <> struct Construct { typedef Float32 Type; }; template <> struct Construct { typedef Float32 Type; }; template <> struct Construct { typedef Float32 Type; }; template <> struct Construct { typedef Float64 Type; }; /** Результат сложения или умножения вычисляется по следующим правилам: * - если один из аргументов с плавающей запятой, то результат - с плавающей запятой, иначе - целый; * - если одно из аргументов со знаком, то результат - со знаком, иначе - без знака; * - результат содержит больше бит (не только значащих), чем максимум в аргументах * (например, UInt8 + Int32 = Int64). */ template struct ResultOfAdditionMultiplication { typedef typename Construct< typename boost::mpl::or_::Sign, typename Traits::Sign>::type, typename boost::mpl::or_::Floatness, typename Traits::Floatness>::type, typename Next::Bits, typename Traits::Bits>::type>::Type>::Type Type; }; template struct ResultOfSubtraction { typedef typename Construct< typename boost::mpl::if_< typename boost::mpl::and_< typename boost::mpl::not_::Sign>, typename boost::mpl::not_::Floatness>, typename boost::mpl::not_::Floatness>, typename boost::mpl::greater::Bits, typename Traits::Bits> >, Unsigned, Signed>::type, typename boost::mpl::or_::Floatness, typename Traits::Floatness>::type, typename boost::mpl::if_< typename boost::mpl::and_< typename boost::mpl::not_::Sign>, typename boost::mpl::not_::Sign>, typename boost::mpl::not_::Floatness>, typename boost::mpl::not_::Floatness>, typename boost::mpl::greater::Bits, typename Traits::Bits> >, typename Traits::Bits, typename Next::Bits, typename Traits::Bits>::type>::Type>::type>::Type Type; }; /** При делении всегда получается число с плавающей запятой. */ template struct ResultOfFloatingPointDivision { typedef typename Construct< Signed, Floating, typename Next::Bits, typename Traits::Bits>::type>::Type>::Type Type; }; /** При целочисленном делении получается число, битность которого равна делимому. */ template struct ResultOfIntegerDivision { typedef typename Construct< typename boost::mpl::or_::Sign, typename Traits::Sign>::type, typename boost::mpl::or_::Floatness, typename Traits::Floatness>::type, typename Traits::Bits>::Type Type; }; /** При взятии остатка получается число, битность которого равна делителю. */ template struct ResultOfModulo { typedef typename Construct< typename boost::mpl::or_::Sign, typename Traits::Sign>::type, typename boost::mpl::or_::Floatness, typename Traits::Floatness>::type, typename Traits::Bits>::Type Type; }; } }