ClickHouse server version 20.8.9 revision 54438

Let's imagine some simple table structure:

```
CREATE TABLE users (
    `user_id` Int32
)
```

Modulo operator on **Int32** field with **150** argument returns negative result. This could have happened due to wrong type casting - result should be casted to **Int16** or **UInt8** instead of **Int8**.

```
SELECT 
    user_id % 150, 
    441746 % 150,
    toTypeName(user_id % 150),
    toTypeName(441746 % 150)
FROM users 
WHERE user_id = 441746
LIMIT 1
```

```
┌─modulo(user_id, 150)─┬─modulo(441746, 150)─┬─toTypeName(modulo(user_id, 150))─┬─toTypeName(modulo(441746, 150))─┐
│                -110  │                 146 │ Int8                             │ UInt8                           │
└──────────────────────┴─────────────────────┴──────────────────────────────────┴─────────────────────────────────┘
```
* UInt<x>,  UInt<y>   ->  UInt<max(x,y)>
  * Int<x>,   Int<y>    ->   Int<max(x,y)>
  * Float<x>, Float<y>  -> Float<max(x, y)>
  * UInt<x>,  Int<y>    ->   Int<max(x*2, y)>
  * Float<x>, [U]Int<y> -> Float<max(x, y*2)>
  * Decimal<x>, Decimal<y> -> Decimal<max(x,y)>
  * UUID, UUID          -> UUID
  * UInt64 ,  Int<x>    -> Error
  * Float<x>, [U]Int64  -> Error
  */
template <typename A, typename B>
struct ResultOfIf
{
    static constexpr bool has_float = std::is_floating_point_v<A> || std::is_floating_point_v<B>;
    static constexpr bool has_integer = is_integer_v<A> || is_integer_v<B>;
    static constexpr bool has_signed = is_signed_v<A> || is_signed_v<B>;
    static constexpr bool has_unsigned = !is_signed_v<A> || !is_signed_v<B>;
    static constexpr bool has_big_int = is_big_int_v<A> || is_big_int_v<B>;
    static constexpr size_t max_size_of_unsigned_integer = max(is_signed_v<A> ? 0 : sizeof(A), is_signed_v<B> ? 0 : sizeof(B));
    static constexpr size_t max_size_of_signed_integer = max(is_signed_v<A> ? sizeof(A) : 0, is_signed_v<B> ? sizeof(B) : 0);
    static constexpr size_t max_size_of_integer = max(is_integer_v<A> ? sizeof(A) : 0, is_integer_v<B> ? sizeof(B) : 0);
    static constexpr size_t max_size_of_float = max(std::is_floating_point_v<A> ? sizeof(A) : 0, std::is_floating_point_v<B> ? sizeof(B) : 0);
    using ConstructedType = typename Construct<has_signed, has_float,
        ((has_float && has_integer && max_size_of_integer >= max_size_of_float)
            || (has_signed && has_unsigned && max_size_of_unsigned_integer >= max_size_of_signed_integer))
                ? max(sizeof(A), sizeof(B)) * 2
                : max(sizeof(A), sizeof(B))>::Type;
    using ConstructedTypeWithoutUUID = std::conditional_t<std::is_same_v<A, UInt128> || std::is_same_v<B, UInt128>, Error, ConstructedType>;
    using ConstructedWithUUID = std::conditional_t<std::is_same_v<A, UInt128> && std::is_same_v<B, UInt128>, A, ConstructedTypeWithoutUUID>;
    using Type = std::conditional_t<!IsDecimalNumber<A> && !IsDecimalNumber<B>, ConstructedWithUUID,