Introduced intExp functions; using it where appropriate; make them available in SQL [#CLICKHOUSE-3].

This commit is contained in:
Alexey Milovidov 2017-12-22 02:46:34 +03:00
parent 46c733ec11
commit 74f191dfd3
8 changed files with 173 additions and 6 deletions

View File

@ -26,6 +26,8 @@ generate_function_register(Arithmetic
FunctionBitTestAll
FunctionGCD
FunctionLCM
FunctionIntExp2
FunctionIntExp10
)
generate_function_register(Array

View File

@ -16,6 +16,7 @@
#include <IO/WriteHelpers.h>
#include <Interpreters/ExpressionActions.h>
#include <ext/range.h>
#include <common/intExp.h>
#include <boost/math/common_factor.hpp>
@ -453,6 +454,29 @@ struct LCMImpl
}
};
template <typename A>
struct IntExp2Impl
{
using ResultType = UInt64;
static inline ResultType apply(A a)
{
return intExp2(a);
}
};
template <typename A>
struct IntExp10Impl
{
using ResultType = UInt64;
static inline ResultType apply(A a)
{
return intExp10(a);
}
};
/// this one is just for convenience
template <bool B, typename T1, typename T2> using If = typename std::conditional<B, T1, T2>::type;
/// these ones for better semantics
@ -1013,6 +1037,8 @@ struct NameLeast { static constexpr auto name = "least"; };
struct NameGreatest { static constexpr auto name = "greatest"; };
struct NameGCD { static constexpr auto name = "gcd"; };
struct NameLCM { static constexpr auto name = "lcm"; };
struct NameIntExp2 { static constexpr auto name = "intExp2"; };
struct NameIntExp10 { static constexpr auto name = "intExp10"; };
using FunctionPlus = FunctionBinaryArithmetic<PlusImpl, NamePlus>;
using FunctionMinus = FunctionBinaryArithmetic<MinusImpl, NameMinus>;
@ -1036,6 +1062,10 @@ using FunctionLeast = FunctionBinaryArithmetic<LeastImpl, NameLeast>;
using FunctionGreatest = FunctionBinaryArithmetic<GreatestImpl, NameGreatest>;
using FunctionGCD = FunctionBinaryArithmetic<GCDImpl, NameGCD>;
using FunctionLCM = FunctionBinaryArithmetic<LCMImpl, NameLCM>;
/// Assumed to be injective for the purpose of query optimization, but in fact it is not injective because of possible overflow.
using FunctionIntExp2 = FunctionUnaryArithmetic<IntExp2Impl, NameIntExp2, true>;
using FunctionIntExp10 = FunctionUnaryArithmetic<IntExp10Impl, NameIntExp10, true>;
/// Monotonicity properties for some functions.
@ -1072,6 +1102,36 @@ template <> struct FunctionUnaryArithmeticMonotonicity<NameBitNot>
}
};
template <> struct FunctionUnaryArithmeticMonotonicity<NameIntExp2>
{
static bool has() { return true; }
static IFunction::Monotonicity get(const Field & left, const Field & right)
{
Float64 left_float = left.isNull() ? -std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), left);
Float64 right_float = right.isNull() ? std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), right);
if (left_float < 0 || right_float > 63)
return {};
return { true };
}
};
template <> struct FunctionUnaryArithmeticMonotonicity<NameIntExp10>
{
static bool has() { return true; }
static IFunction::Monotonicity get(const Field & left, const Field & right)
{
Float64 left_float = left.isNull() ? -std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), left);
Float64 right_float = right.isNull() ? std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), right);
if (left_float < 0 || right_float > 19)
return {};
return { true };
}
};
}
/// Optimizations for integer division by a constant.

View File

@ -1,4 +1,4 @@
#include <common/exp10.h>
#include <common/intExp.h>
#include <Parsers/CommonParsers.h>
#include <Parsers/ParserSampleRatio.h>
@ -48,13 +48,13 @@ static bool parseDecimal(const char * pos, const char * end, ASTSampleRatio::Rat
return false;
}
res.numerator = num_before * exp10(number_of_digits_after_point) + num_after;
res.denominator = exp10(number_of_digits_after_point);
res.numerator = num_before * intExp10(number_of_digits_after_point) + num_after;
res.denominator = intExp10(number_of_digits_after_point);
if (exponent > 0)
res.numerator *= exp10(exponent);
res.numerator *= intExp10(exponent);
if (exponent < 0)
res.denominator *= exp10(-exponent);
res.denominator *= intExp10(-exponent);
/// NOTE You do not need to remove the common power of ten from the numerator and denominator.
return true;

View File

@ -1 +1 @@
SELECT number, exp10(number) FROM system.numbers LIMIT 310;
SELECT number, exp10(number) FROM system.numbers LIMIT 310;

View File

@ -0,0 +1,70 @@
1 1 1 1 1 1
2 2 1 10 10 1
4 4 1 100 100 1
8 8 1 1000 1000 1
16 16 1 10000 10000 1
32 32 1 100000 100000 1
64 64 1 1000000 1000000 1
128 128 1 10000000 10000000 1
256 256 1 100000000 100000000 1
512 512 1 1000000000 1000000000 1
1024 1024 1 10000000000 10000000000 1
2048 2048 1 100000000000 100000000000 1
4096 4096 1 1000000000000 1000000000000 1
8192 8192 1 10000000000000 10000000000000 1
16384 16384 1 100000000000000 100000000000000 1
32768 32768 1 1000000000000000 1000000000000000 1
65536 65536 1 10000000000000000 10000000000000000 1
131072 131072 1 100000000000000000 100000000000000000 1
262144 262144 1 1000000000000000000 1000000000000000000 1
524288 524288 1 10000000000000000000 10000000000000000000 1
1048576 1048576 1 100000000000000000000 18446744073709551615 0
2097152 2097152 1 1e21 18446744073709551615 0
4194304 4194304 1 1e22 18446744073709551615 0
8388608 8388608 1 1e23 18446744073709551615 0
16777216 16777216 1 1e24 18446744073709551615 0
33554432 33554432 1 1e25 18446744073709551615 0
67108864 67108864 1 1e26 18446744073709551615 0
134217728 134217728 1 1e27 18446744073709551615 0
268435456 268435456 1 1e28 18446744073709551615 0
536870912 536870912 1 1e29 18446744073709551615 0
1073741824 1073741824 1 1e30 18446744073709551615 0
2147483648 2147483648 1 1e31 18446744073709551615 0
4294967296 4294967296 1 1e32 18446744073709551615 0
8589934592 8589934592 1 1e33 18446744073709551615 0
17179869184 17179869184 1 1e34 18446744073709551615 0
34359738368 34359738368 1 1e35 18446744073709551615 0
68719476736 68719476736 1 1e36 18446744073709551615 0
137438953472 137438953472 1 1e37 18446744073709551615 0
274877906944 274877906944 1 1e38 18446744073709551615 0
549755813888 549755813888 1 1e39 18446744073709551615 0
1099511627776 1099511627776 1 1e40 18446744073709551615 0
2199023255552 2199023255552 1 1e41 18446744073709551615 0
4398046511104 4398046511104 1 1e42 18446744073709551615 0
8796093022208 8796093022208 1 1e43 18446744073709551615 0
17592186044416 17592186044416 1 1e44 18446744073709551615 0
35184372088832 35184372088832 1 1e45 18446744073709551615 0
70368744177664 70368744177664 1 1e46 18446744073709551615 0
140737488355328 140737488355328 1 1e47 18446744073709551615 0
281474976710656 281474976710656 1 1e48 18446744073709551615 0
562949953421312 562949953421312 1 1e49 18446744073709551615 0
1125899906842624 1125899906842624 1 1e50 18446744073709551615 0
2251799813685248 2251799813685248 1 1e51 18446744073709551615 0
4503599627370496 4503599627370496 1 1e52 18446744073709551615 0
9007199254740992 9007199254740992 1 1e53 18446744073709551615 0
18014398509481984 18014398509481984 1 1e54 18446744073709551615 0
36028797018963970 36028797018963968 1 1e55 18446744073709551615 0
72057594037927940 72057594037927936 1 1e56 18446744073709551615 0
144115188075855870 144115188075855872 1 1e57 18446744073709551615 0
288230376151711740 288230376151711744 1 1e58 18446744073709551615 0
576460752303423500 576460752303423488 1 1e59 18446744073709551615 0
1152921504606847000 1152921504606846976 1 1e60 18446744073709551615 0
2305843009213694000 2305843009213693952 1 1e61 18446744073709551615 0
4611686018427388000 4611686018427387904 1 1e62 18446744073709551615 0
9223372036854776000 9223372036854775808 1 1e63 18446744073709551615 0
18446744073709552000 1 0 1e64 18446744073709551615 0
36893488147419103000 2 0 1e65 18446744073709551615 0
73786976294838210000 4 0 1e66 18446744073709551615 0
147573952589676410000 8 0 1e67 18446744073709551615 0
295147905179352830000 16 0 1e68 18446744073709551615 0
590295810358705700000 32 0 1e69 18446744073709551615 0

View File

@ -0,0 +1 @@
SELECT exp2(number) AS e2d, intExp2(number) AS e2i, e2d = e2i AS e2eq, exp10(number) AS e10d, intExp10(number) AS e10i, e10d = e10i AS e10eq FROM system.numbers LIMIT 70;

View File

@ -34,6 +34,7 @@ add_library (common
include/common/LocalDateTime.h
include/common/ErrorHandlers.h
include/common/exp10.h
include/common/intExp.h
include/common/mremap.h
include/common/likely.h
include/common/logger_useful.h

View File

@ -0,0 +1,33 @@
#pragma once
#include <cstdint>
#include <limits>
/// On overlow, the function returns unspecified value.
inline uint64_t intExp2(int x)
{
return 1ULL << x;
}
inline uint64_t intExp10(int x)
{
if (x < 0)
return 0;
if (x > 19)
return std::numeric_limits<uint64_t>::max();
static const uint64_t table[20] =
{
1ULL, 10ULL, 100ULL,
1000ULL, 10000ULL, 100000ULL,
1000000ULL, 10000000ULL, 100000000ULL,
1000000000ULL, 10000000000ULL, 100000000000ULL,
1000000000000ULL, 10000000000000ULL, 100000000000000ULL,
1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
1000000000000000000ULL, 10000000000000000000ULL
};
return table[x];
}