mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge pull request #64798 from arenadata/ADQM-1892
Support non-const scale arguments in rounding functions
This commit is contained in:
commit
5c7f600d74
@ -6,49 +6,90 @@ sidebar_label: Rounding
|
||||
|
||||
# Rounding Functions
|
||||
|
||||
## floor(x\[, N\])
|
||||
## floor
|
||||
|
||||
Returns the largest round number that is less than or equal to `x`. A round number is a multiple of 1/10N, or the nearest number of the appropriate data type if 1 / 10N isn’t exact.
|
||||
‘N’ is an integer constant, optional parameter. By default it is zero, which means to round to an integer.
|
||||
‘N’ may be negative.
|
||||
Returns the largest rounded number less than or equal `x`.
|
||||
A rounded number is a multiple of 1 / 10 * N, or the nearest number of the appropriate data type if 1 / 10 * N isn’t exact.
|
||||
|
||||
Examples: `floor(123.45, 1) = 123.4, floor(123.45, -1) = 120.`
|
||||
Integer arguments may be rounded with negative `N` argument, with non-negative `N` the function returns `x`, i.e. does nothing.
|
||||
|
||||
`x` is any numeric type. The result is a number of the same type.
|
||||
For integer arguments, it makes sense to round with a negative `N` value (for non-negative `N`, the function does not do anything).
|
||||
If rounding causes overflow (for example, floor(-128, -1)), an implementation-specific result is returned.
|
||||
If rounding causes an overflow (for example, `floor(-128, -1)`), the result is undefined.
|
||||
|
||||
## ceil(x\[, N\]), ceiling(x\[, N\])
|
||||
**Syntax**
|
||||
|
||||
Returns the smallest round number that is greater than or equal to `x`. In every other way, it is the same as the `floor` function (see above).
|
||||
``` sql
|
||||
floor(x[, N])
|
||||
```
|
||||
|
||||
## trunc(x\[, N\]), truncate(x\[, N\])
|
||||
**Parameters**
|
||||
|
||||
Returns the round number with largest absolute value that has an absolute value less than or equal to `x`‘s. In every other way, it is the same as the ’floor’ function (see above).
|
||||
- `x` - The value to round. [Float*](../data-types/float.md), [Decimal*](../data-types/decimal.md), or [(U)Int*](../data-types/int-uint.md).
|
||||
- `N` . [(U)Int*](../data-types/int-uint.md). The default is zero, which means rounding to an integer. Can be negative.
|
||||
|
||||
**Returned value**
|
||||
|
||||
A rounded number of the same type as `x`.
|
||||
|
||||
**Examples**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT floor(123.45, 1) AS rounded
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
┌─rounded─┐
|
||||
│ 123.4 │
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT floor(123.45, -1)
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```
|
||||
┌─rounded─┐
|
||||
│ 120 │
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
## ceiling
|
||||
|
||||
Like `floor` but returns the smallest rounded number greater than or equal `x`.
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
ceiling(x[, N])
|
||||
```
|
||||
|
||||
Alias: `ceil`
|
||||
|
||||
## truncate
|
||||
|
||||
Like `floor` but returns the rounded number with largest absolute value that has an absolute value less than or equal to `x`‘s.
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
trunc(input, precision)
|
||||
truncate(x[, N])
|
||||
```
|
||||
|
||||
Alias: `truncate`.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `input`: A numeric type ([Float](../data-types/float.md), [Decimal](../data-types/decimal.md) or [Integer](../data-types/int-uint.md)).
|
||||
- `precision`: An [Integer](../data-types/int-uint.md) type.
|
||||
|
||||
**Returned value**
|
||||
|
||||
- A data type of `input`.
|
||||
Alias: `trunc`.
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT trunc(123.499, 1) as res;
|
||||
SELECT truncate(123.499, 1) as res;
|
||||
```
|
||||
|
||||
```response
|
||||
@ -57,37 +98,40 @@ SELECT trunc(123.499, 1) as res;
|
||||
└───────┘
|
||||
```
|
||||
|
||||
## round(x\[, N\])
|
||||
## round
|
||||
|
||||
Rounds a value to a specified number of decimal places.
|
||||
|
||||
The function returns the nearest number of the specified order. In case when given number has equal distance to surrounding numbers, the function uses banker’s rounding for float number types and rounds away from zero for the other number types (Decimal).
|
||||
The function returns the nearest number of the specified order.
|
||||
If the input value has equal distance to two neighboring numbers, the function uses banker’s rounding for [Float*](../data-types/float.md) inputs and rounds away from zero for the other number types ([Decimal*](../data-types/decimal.md).
|
||||
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
round(expression [, decimal_places])
|
||||
round(x[, N])
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `expression` — A number to be rounded. Can be any [expression](../../sql-reference/syntax.md#syntax-expressions) returning the numeric [data type](../data-types/index.md#data_types).
|
||||
- `decimal-places` — An integer value.
|
||||
- If `decimal-places > 0` then the function rounds the value to the right of the decimal point.
|
||||
- If `decimal-places < 0` then the function rounds the value to the left of the decimal point.
|
||||
- If `decimal-places = 0` then the function rounds the value to integer. In this case the argument can be omitted.
|
||||
- `x` — A number to round. [Float*](../data-types/float.md), [Decimal*](../data-types/decimal.md), or [(U)Int*](../data-types/int-uint.md).
|
||||
- `N` — The number of decimal places to round to. Integer. Defaults to `0`.
|
||||
- If `N > 0`, the function rounds to the right of the decimal point.
|
||||
- If `N < 0`, the function rounds to the left of the decimal point.
|
||||
- If `N = 0`, the function rounds to the next integer.
|
||||
|
||||
**Returned value:**
|
||||
|
||||
The rounded number of the same type as the input number.
|
||||
A rounded number of the same type as `x`.
|
||||
|
||||
**Examples**
|
||||
|
||||
Example of usage with Float:
|
||||
Example with `Float` inputs:
|
||||
|
||||
``` sql
|
||||
```sql
|
||||
SELECT number / 2 AS x, round(x) FROM system.numbers LIMIT 3;
|
||||
```
|
||||
|
||||
``` text
|
||||
```
|
||||
┌───x─┬─round(divide(number, 2))─┐
|
||||
│ 0 │ 0 │
|
||||
│ 0.5 │ 0 │
|
||||
@ -95,13 +139,13 @@ SELECT number / 2 AS x, round(x) FROM system.numbers LIMIT 3;
|
||||
└─────┴──────────────────────────┘
|
||||
```
|
||||
|
||||
Example of usage with Decimal:
|
||||
Example with `Decimal` inputs:
|
||||
|
||||
``` sql
|
||||
```sql
|
||||
SELECT cast(number / 2 AS Decimal(10,4)) AS x, round(x) FROM system.numbers LIMIT 3;
|
||||
```
|
||||
|
||||
``` text
|
||||
```
|
||||
┌───x─┬─round(CAST(divide(number, 2), 'Decimal(10, 4)'))─┐
|
||||
│ 0 │ 0 │
|
||||
│ 0.5 │ 1 │
|
||||
@ -109,14 +153,14 @@ SELECT cast(number / 2 AS Decimal(10,4)) AS x, round(x) FROM system.numbers LIM
|
||||
└─────┴──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
If you want to keep the trailing zeros, you need to enable `output_format_decimal_trailing_zeros`
|
||||
To retain trailing zeros, enable setting `output_format_decimal_trailing_zeros`:
|
||||
|
||||
``` sql
|
||||
```sql
|
||||
SELECT cast(number / 2 AS Decimal(10,4)) AS x, round(x) FROM system.numbers LIMIT 3 settings output_format_decimal_trailing_zeros=1;
|
||||
|
||||
```
|
||||
|
||||
``` text
|
||||
```
|
||||
┌──────x─┬─round(CAST(divide(number, 2), 'Decimal(10, 4)'))─┐
|
||||
│ 0.0000 │ 0.0000 │
|
||||
│ 0.5000 │ 1.0000 │
|
||||
@ -151,9 +195,15 @@ round(3.65, 1) = 3.6
|
||||
|
||||
Rounds a number to a specified decimal position.
|
||||
|
||||
- If the rounding number is halfway between two numbers, the function uses banker’s rounding. Banker's rounding is a method of rounding fractional numbers. When the rounding number is halfway between two numbers, it's rounded to the nearest even digit at the specified decimal position. For example: 3.5 rounds up to 4, 2.5 rounds down to 2. It's the default rounding method for floating point numbers defined in [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest). The [round](#rounding_functions-round) function performs the same rounding for floating point numbers. The `roundBankers` function also rounds integers the same way, for example, `roundBankers(45, -1) = 40`.
|
||||
If the rounding number is halfway between two numbers, the function uses banker’s rounding.
|
||||
Banker's rounding is a method of rounding fractional numbers
|
||||
When the rounding number is halfway between two numbers, it's rounded to the nearest even digit at the specified decimal position.
|
||||
For example: 3.5 rounds up to 4, 2.5 rounds down to 2.
|
||||
It's the default rounding method for floating point numbers defined in [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest).
|
||||
The [round](#rounding_functions-round) function performs the same rounding for floating point numbers.
|
||||
The `roundBankers` function also rounds integers the same way, for example, `roundBankers(45, -1) = 40`.
|
||||
|
||||
- In other cases, the function rounds numbers to the nearest integer.
|
||||
In other cases, the function rounds numbers to the nearest integer.
|
||||
|
||||
Using banker’s rounding, you can reduce the effect that rounding numbers has on the results of summing or subtracting these numbers.
|
||||
|
||||
@ -166,16 +216,20 @@ For example, sum numbers 1.5, 2.5, 3.5, 4.5 with different rounding:
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
roundBankers(expression [, decimal_places])
|
||||
roundBankers(x [, N])
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `expression` — A number to be rounded. Can be any [expression](../../sql-reference/syntax.md#syntax-expressions) returning the numeric [data type](../data-types/index.md#data_types).
|
||||
- `decimal-places` — Decimal places. An integer number.
|
||||
- `decimal-places > 0` — The function rounds the number to the given position right of the decimal point. Example: `roundBankers(3.55, 1) = 3.6`.
|
||||
- `decimal-places < 0` — The function rounds the number to the given position left of the decimal point. Example: `roundBankers(24.55, -1) = 20`.
|
||||
- `decimal-places = 0` — The function rounds the number to an integer. In this case the argument can be omitted. Example: `roundBankers(2.5) = 2`.
|
||||
- `N > 0` — The function rounds the number to the given position right of the decimal point. Example: `roundBankers(3.55, 1) = 3.6`.
|
||||
- `N < 0` — The function rounds the number to the given position left of the decimal point. Example: `roundBankers(24.55, -1) = 20`.
|
||||
- `N = 0` — The function rounds the number to an integer. In this case the argument can be omitted. Example: `roundBankers(2.5) = 2`.
|
||||
|
||||
- `x` — A number to round. [Float*](../data-types/float.md), [Decimal*](../data-types/decimal.md), or [(U)Int*](../data-types/int-uint.md).
|
||||
- `N` — The number of decimal places to round to. Integer. Defaults to `0`.
|
||||
- If `N > 0`, the function rounds to the right of the decimal point.
|
||||
- If `N < 0`, the function rounds to the left of the decimal point.
|
||||
- If `N = 0`, the function rounds to the next integer.
|
||||
|
||||
**Returned value**
|
||||
|
||||
@ -185,13 +239,13 @@ A value rounded by the banker’s rounding method.
|
||||
|
||||
Query:
|
||||
|
||||
``` sql
|
||||
```sql
|
||||
SELECT number / 2 AS x, roundBankers(x, 0) AS b fROM system.numbers limit 10
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
``` text
|
||||
```
|
||||
┌───x─┬─b─┐
|
||||
│ 0 │ 0 │
|
||||
│ 0.5 │ 0 │
|
||||
@ -208,7 +262,7 @@ Result:
|
||||
|
||||
Examples of Banker’s rounding:
|
||||
|
||||
``` text
|
||||
```
|
||||
roundBankers(0.4) = 0
|
||||
roundBankers(-3.5) = -4
|
||||
roundBankers(4.5) = 4
|
||||
@ -264,7 +318,7 @@ Result:
|
||||
|
||||
## roundDuration
|
||||
|
||||
Accepts a number. If the number is less than one, it returns `0`. Otherwise, it rounds the number down to numbers from the set of commonly used durations: `1, 10, 30, 60, 120, 180, 240, 300, 600, 1200, 1800, 3600, 7200, 18000, 36000`.
|
||||
Accepts a number. If the number is less than one, it returns `0`. Otherwise, it rounds the number down to numbers from the set of commonly used durations: `1, 10, 30, 60, 120, 180, 240, 300, 600, 1200, 1800, 3600, 7200, 18000, 36000`.
|
||||
|
||||
**Syntax**
|
||||
|
||||
|
@ -10,7 +10,7 @@ sidebar_label: "Функции округления"
|
||||
|
||||
Возвращает наибольшее круглое число, которое меньше или равно, чем x.
|
||||
Круглым называется число, кратное 1 / 10N или ближайшее к нему число соответствующего типа данных, если 1 / 10N не представимо точно.
|
||||
N - целочисленная константа, не обязательный параметр. По умолчанию - ноль, что означает - округлять до целого числа.
|
||||
N - целочисленный аргумент, не обязательный параметр. По умолчанию - ноль, что означает - округлять до целого числа.
|
||||
N может быть отрицательным.
|
||||
|
||||
Примеры: `floor(123.45, 1) = 123.4, floor(123.45, -1) = 120.`
|
||||
|
@ -31,7 +31,6 @@ namespace DB
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||
extern const int ARGUMENT_OUT_OF_BOUND;
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
@ -40,26 +39,22 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
/** Rounding Functions:
|
||||
* round(x, N) - rounding to nearest (N = 0 by default). Use banker's rounding for floating point numbers.
|
||||
* roundBankers(x, N) - rounding to nearest (N = 0 by default). Use banker's rounding for all numbers.
|
||||
* floor(x, N) is the largest number <= x (N = 0 by default).
|
||||
* ceil(x, N) is the smallest number >= x (N = 0 by default).
|
||||
* trunc(x, N) - is the largest by absolute value number that is not greater than x by absolute value (N = 0 by default).
|
||||
*
|
||||
* The value of the parameter N (scale):
|
||||
* - N > 0: round to the number with N decimal places after the decimal point
|
||||
* - N < 0: round to an integer with N zero characters
|
||||
* - N = 0: round to an integer
|
||||
*
|
||||
* Type of the result is the type of argument.
|
||||
* For integer arguments, when passing negative scale, overflow can occur.
|
||||
* In that case, the behavior is implementation specific.
|
||||
*/
|
||||
/// Rounding Functions:
|
||||
/// - round(x, N) - rounding to nearest (N = 0 by default). Use banker's rounding for floating point numbers.
|
||||
/// - roundBankers(x, N) - rounding to nearest (N = 0 by default). Use banker's rounding for all numbers.
|
||||
/// - floor(x, N) is the largest number <= x (N = 0 by default).
|
||||
/// - ceil(x, N) is the smallest number >= x (N = 0 by default).
|
||||
/// - trunc(x, N) - is the largest by absolute value number that is not greater than x by absolute value (N = 0 by default).
|
||||
|
||||
/// The value of the parameter N (scale):
|
||||
/// - N > 0: round to the number with N decimal places after the decimal point
|
||||
/// - N < 0: round to an integer with N zero characters
|
||||
/// - N = 0: round to an integer
|
||||
|
||||
/** This parameter controls the behavior of the rounding functions.
|
||||
*/
|
||||
/// Type of the result is the type of argument.
|
||||
/// For integer arguments, when passing negative scale, overflow can occur. In that case, the behavior is undefined.
|
||||
|
||||
/// Controls the behavior of the rounding functions.
|
||||
enum class ScaleMode : uint8_t
|
||||
{
|
||||
Positive, // round to a number with N decimal places after the decimal point
|
||||
@ -75,7 +70,7 @@ enum class RoundingMode : uint8_t
|
||||
Ceil = _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC,
|
||||
Trunc = _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC,
|
||||
#else
|
||||
Round = 8, /// Values are correspond to above just in case.
|
||||
Round = 8, /// Values correspond to above values, just in case.
|
||||
Floor = 9,
|
||||
Ceil = 10,
|
||||
Trunc = 11,
|
||||
@ -84,16 +79,21 @@ enum class RoundingMode : uint8_t
|
||||
|
||||
enum class TieBreakingMode : uint8_t
|
||||
{
|
||||
Auto, // use banker's rounding for floating point numbers, round up otherwise
|
||||
Bankers, // use banker's rounding
|
||||
Auto, /// banker's rounding for floating point numbers, round up otherwise
|
||||
Bankers, /// banker's rounding
|
||||
};
|
||||
|
||||
enum class Vectorize : uint8_t
|
||||
{
|
||||
No,
|
||||
Yes
|
||||
};
|
||||
|
||||
/// For N, no more than the number of digits in the largest type.
|
||||
using Scale = Int16;
|
||||
|
||||
|
||||
/** Rounding functions for integer values.
|
||||
*/
|
||||
/// Rounding functions for integer values.
|
||||
template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, TieBreakingMode tie_breaking_mode>
|
||||
struct IntegerRoundingComputation
|
||||
{
|
||||
@ -149,6 +149,8 @@ struct IntegerRoundingComputation
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE T compute(T x, T scale)
|
||||
@ -161,9 +163,12 @@ struct IntegerRoundingComputation
|
||||
case ScaleMode::Negative:
|
||||
return computeImpl(x, scale);
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void compute(const T * __restrict in, size_t scale, T * __restrict out) requires std::integral<T>
|
||||
static ALWAYS_INLINE void compute(const T * __restrict in, size_t scale, T * __restrict out)
|
||||
requires std::integral<T>
|
||||
{
|
||||
if constexpr (sizeof(T) <= sizeof(scale) && scale_mode == ScaleMode::Negative)
|
||||
{
|
||||
@ -176,20 +181,23 @@ struct IntegerRoundingComputation
|
||||
*out = compute(*in, static_cast<T>(scale));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void compute(const T * __restrict in, T scale, T * __restrict out) requires(!std::integral<T>)
|
||||
static ALWAYS_INLINE void compute(const T * __restrict in, T scale, T * __restrict out)
|
||||
requires(!std::integral<T>)
|
||||
{
|
||||
*out = compute(*in, scale);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, Vectorize vectorize>
|
||||
class FloatRoundingComputationBase;
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
|
||||
template <typename T>
|
||||
class BaseFloatRoundingComputation;
|
||||
/// Vectorized implementation for x86.
|
||||
|
||||
template <>
|
||||
class BaseFloatRoundingComputation<Float32>
|
||||
class FloatRoundingComputationBase<Float32, Vectorize::Yes>
|
||||
{
|
||||
public:
|
||||
using ScalarType = Float32;
|
||||
@ -210,7 +218,7 @@ public:
|
||||
};
|
||||
|
||||
template <>
|
||||
class BaseFloatRoundingComputation<Float64>
|
||||
class FloatRoundingComputationBase<Float64, Vectorize::Yes>
|
||||
{
|
||||
public:
|
||||
using ScalarType = Float64;
|
||||
@ -230,9 +238,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
/// Implementation for ARM. Not vectorized.
|
||||
/// Sequential implementation for ARM. Also used for scalar arguments.
|
||||
|
||||
inline float roundWithMode(float x, RoundingMode mode)
|
||||
{
|
||||
@ -243,6 +251,8 @@ inline float roundWithMode(float x, RoundingMode mode)
|
||||
case RoundingMode::Ceil: return ceilf(x);
|
||||
case RoundingMode::Trunc: return truncf(x);
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
inline double roundWithMode(double x, RoundingMode mode)
|
||||
@ -254,10 +264,12 @@ inline double roundWithMode(double x, RoundingMode mode)
|
||||
case RoundingMode::Ceil: return ceil(x);
|
||||
case RoundingMode::Trunc: return trunc(x);
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class BaseFloatRoundingComputation
|
||||
class FloatRoundingComputationBase<T, Vectorize::No>
|
||||
{
|
||||
public:
|
||||
using ScalarType = T;
|
||||
@ -277,15 +289,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/** Implementation of low-level round-off functions for floating-point values.
|
||||
*/
|
||||
template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode>
|
||||
class FloatRoundingComputation : public BaseFloatRoundingComputation<T>
|
||||
template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, Vectorize vectorize>
|
||||
class FloatRoundingComputation : public FloatRoundingComputationBase<T, vectorize>
|
||||
{
|
||||
using Base = BaseFloatRoundingComputation<T>;
|
||||
using Base = FloatRoundingComputationBase<T, vectorize>;
|
||||
|
||||
public:
|
||||
static void compute(const T * __restrict in, const typename Base::VectorType & scale, T * __restrict out)
|
||||
@ -317,15 +327,22 @@ struct FloatRoundingImpl
|
||||
private:
|
||||
static_assert(!is_decimal<T>);
|
||||
|
||||
using Op = FloatRoundingComputation<T, rounding_mode, scale_mode>;
|
||||
using Data = std::array<T, Op::data_count>;
|
||||
template <Vectorize vectorize =
|
||||
#ifdef __SSE4_1__
|
||||
Vectorize::Yes
|
||||
#else
|
||||
Vectorize::No
|
||||
#endif
|
||||
>
|
||||
using Op = FloatRoundingComputation<T, rounding_mode, scale_mode, vectorize>;
|
||||
using Data = std::array<T, Op<>::data_count>;
|
||||
using ColumnType = ColumnVector<T>;
|
||||
using Container = typename ColumnType::Container;
|
||||
|
||||
public:
|
||||
static NO_INLINE void apply(const Container & in, size_t scale, Container & out)
|
||||
{
|
||||
auto mm_scale = Op::prepare(scale);
|
||||
auto mm_scale = Op<>::prepare(scale);
|
||||
|
||||
const size_t data_count = std::tuple_size<Data>();
|
||||
|
||||
@ -337,7 +354,7 @@ public:
|
||||
|
||||
while (p_in < limit)
|
||||
{
|
||||
Op::compute(p_in, mm_scale, p_out);
|
||||
Op<>::compute(p_in, mm_scale, p_out);
|
||||
p_in += data_count;
|
||||
p_out += data_count;
|
||||
}
|
||||
@ -350,10 +367,17 @@ public:
|
||||
size_t tail_size_bytes = (end_in - p_in) * sizeof(*p_in);
|
||||
|
||||
memcpy(&tmp_src, p_in, tail_size_bytes);
|
||||
Op::compute(reinterpret_cast<T *>(&tmp_src), mm_scale, reinterpret_cast<T *>(&tmp_dst));
|
||||
Op<>::compute(reinterpret_cast<T *>(&tmp_src), mm_scale, reinterpret_cast<T *>(&tmp_dst));
|
||||
memcpy(p_out, &tmp_dst, tail_size_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void applyOne(T in, size_t scale, T& out)
|
||||
{
|
||||
using ScalarOp = Op<Vectorize::No>;
|
||||
auto s = ScalarOp::prepare(scale);
|
||||
ScalarOp::compute(&in, s, &out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, TieBreakingMode tie_breaking_mode>
|
||||
@ -409,6 +433,11 @@ public:
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unexpected 'scale' parameter passed to function");
|
||||
}
|
||||
}
|
||||
|
||||
static void applyOne(T in, size_t scale, T& out)
|
||||
{
|
||||
Op::compute(&in, scale, &out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -444,11 +473,40 @@ public:
|
||||
memcpy(out.data(), in.data(), in.size() * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
static void applyOne(NativeType in, UInt32 in_scale, NativeType& out, Scale scale_arg)
|
||||
{
|
||||
scale_arg = in_scale - scale_arg;
|
||||
if (scale_arg > 0)
|
||||
{
|
||||
auto scale = intExp10OfSize<NativeType>(scale_arg);
|
||||
Op::compute(&in, scale, &out);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&out, &in, sizeof(T));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Select the appropriate processing algorithm depending on the scale.
|
||||
inline void validateScale(Int64 scale64)
|
||||
{
|
||||
if (scale64 > std::numeric_limits<Scale>::max() || scale64 < std::numeric_limits<Scale>::min())
|
||||
throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "Scale argument for rounding function is too large");
|
||||
}
|
||||
|
||||
/** Select the appropriate processing algorithm depending on the scale.
|
||||
*/
|
||||
inline Scale getScaleArg(const ColumnConst* scale_col)
|
||||
{
|
||||
const auto & scale_field = scale_col->getField();
|
||||
|
||||
Int64 scale64 = scale_field.get<Int64>();
|
||||
validateScale(scale64);
|
||||
|
||||
return scale64;
|
||||
}
|
||||
|
||||
/// Generic dispatcher
|
||||
template <typename T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||
struct Dispatcher
|
||||
{
|
||||
@ -457,30 +515,65 @@ struct Dispatcher
|
||||
FloatRoundingImpl<T, rounding_mode, scale_mode>,
|
||||
IntegerRoundingImpl<T, rounding_mode, scale_mode, tie_breaking_mode>>;
|
||||
|
||||
static ColumnPtr apply(const IColumn * col_general, Scale scale_arg)
|
||||
template <typename ScaleType>
|
||||
static ColumnPtr apply(const IColumn * value_col, const IColumn * scale_col = nullptr)
|
||||
{
|
||||
const auto & col = checkAndGetColumn<ColumnVector<T>>(*col_general);
|
||||
const auto & value_col_typed = checkAndGetColumn<ColumnVector<T>>(*value_col);
|
||||
auto col_res = ColumnVector<T>::create();
|
||||
|
||||
typename ColumnVector<T>::Container & vec_res = col_res->getData();
|
||||
vec_res.resize(col.getData().size());
|
||||
vec_res.resize(value_col_typed.getData().size());
|
||||
|
||||
if (!vec_res.empty())
|
||||
{
|
||||
if (scale_arg == 0)
|
||||
if (scale_col == nullptr || isColumnConst(*scale_col))
|
||||
{
|
||||
size_t scale = 1;
|
||||
FunctionRoundingImpl<ScaleMode::Zero>::apply(col.getData(), scale, vec_res);
|
||||
auto scale_arg = (scale_col == nullptr) ? 0 : getScaleArg(checkAndGetColumnConst<ColumnVector<ScaleType>>(scale_col));
|
||||
if (scale_arg == 0)
|
||||
{
|
||||
size_t scale = 1;
|
||||
FunctionRoundingImpl<ScaleMode::Zero>::apply(value_col_typed.getData(), scale, vec_res);
|
||||
}
|
||||
else if (scale_arg > 0)
|
||||
{
|
||||
size_t scale = intExp10(scale_arg);
|
||||
FunctionRoundingImpl<ScaleMode::Positive>::apply(value_col_typed.getData(), scale, vec_res);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t scale = intExp10(-scale_arg);
|
||||
FunctionRoundingImpl<ScaleMode::Negative>::apply(value_col_typed.getData(), scale, vec_res);
|
||||
}
|
||||
}
|
||||
else if (scale_arg > 0)
|
||||
/// Non-const scale argument:
|
||||
else if (const auto * scale_col_typed = checkAndGetColumn<ColumnVector<ScaleType>>(scale_col))
|
||||
{
|
||||
size_t scale = intExp10(scale_arg);
|
||||
FunctionRoundingImpl<ScaleMode::Positive>::apply(col.getData(), scale, vec_res);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t scale = intExp10(-scale_arg);
|
||||
FunctionRoundingImpl<ScaleMode::Negative>::apply(col.getData(), scale, vec_res);
|
||||
const auto & value_data = value_col_typed.getData();
|
||||
const auto & scale_data = scale_col_typed->getData();
|
||||
const size_t rows = value_data.size();
|
||||
|
||||
for (size_t i = 0; i < rows; ++i)
|
||||
{
|
||||
Int64 scale64 = scale_data[i];
|
||||
validateScale(scale64);
|
||||
Scale raw_scale = scale64;
|
||||
|
||||
if (raw_scale == 0)
|
||||
{
|
||||
size_t scale = 1;
|
||||
FunctionRoundingImpl<ScaleMode::Zero>::applyOne(value_data[i], scale, vec_res[i]);
|
||||
}
|
||||
else if (raw_scale > 0)
|
||||
{
|
||||
size_t scale = intExp10(raw_scale);
|
||||
FunctionRoundingImpl<ScaleMode::Positive>::applyOne(value_data[i], scale, vec_res[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t scale = intExp10(-raw_scale);
|
||||
FunctionRoundingImpl<ScaleMode::Negative>::applyOne(value_data[i], scale, vec_res[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -488,28 +581,51 @@ struct Dispatcher
|
||||
}
|
||||
};
|
||||
|
||||
/// Dispatcher for Decimal inputs
|
||||
template <is_decimal T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||
struct Dispatcher<T, rounding_mode, tie_breaking_mode>
|
||||
{
|
||||
public:
|
||||
static ColumnPtr apply(const IColumn * col_general, Scale scale_arg)
|
||||
template <typename ScaleType>
|
||||
static ColumnPtr apply(const IColumn * value_col, const IColumn * scale_col = nullptr)
|
||||
{
|
||||
const auto & col = checkAndGetColumn<ColumnDecimal<T>>(*col_general);
|
||||
const typename ColumnDecimal<T>::Container & vec_src = col.getData();
|
||||
const auto & value_col_typed = checkAndGetColumn<ColumnDecimal<T>>(*value_col);
|
||||
const typename ColumnDecimal<T>::Container & vec_src = value_col_typed.getData();
|
||||
|
||||
auto col_res = ColumnDecimal<T>::create(vec_src.size(), col.getScale());
|
||||
auto col_res = ColumnDecimal<T>::create(vec_src.size(), value_col_typed.getScale());
|
||||
auto & vec_res = col_res->getData();
|
||||
|
||||
if (!vec_res.empty())
|
||||
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::apply(col.getData(), col.getScale(), vec_res, scale_arg);
|
||||
{
|
||||
if (scale_col == nullptr || isColumnConst(*scale_col))
|
||||
{
|
||||
auto scale_arg = scale_col == nullptr ? 0 : getScaleArg(checkAndGetColumnConst<ColumnVector<ScaleType>>(scale_col));
|
||||
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::apply(value_col_typed.getData(), value_col_typed.getScale(), vec_res, scale_arg);
|
||||
}
|
||||
/// Non-const scale argument
|
||||
else if (const auto * scale_col_typed = checkAndGetColumn<ColumnVector<ScaleType>>(scale_col))
|
||||
{
|
||||
const auto & scale = scale_col_typed->getData();
|
||||
const size_t rows = vec_src.size();
|
||||
|
||||
for (size_t i = 0; i < rows; ++i)
|
||||
{
|
||||
Int64 scale64 = scale[i];
|
||||
validateScale(scale64);
|
||||
Scale raw_scale = scale64;
|
||||
|
||||
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::applyOne(value_col_typed.getElement(i), value_col_typed.getScale(),
|
||||
reinterpret_cast<ColumnDecimal<T>::NativeT&>(col_res->getElement(i)), raw_scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return col_res;
|
||||
}
|
||||
};
|
||||
|
||||
/** A template for functions that round the value of an input parameter of type
|
||||
* (U)Int8/16/32/64, Float32/64 or Decimal32/64/128, and accept an additional optional parameter (default is 0).
|
||||
*/
|
||||
/// Functions that round the value of an input parameter of type (U)Int8/16/32/64, Float32/64 or Decimal32/64/128.
|
||||
/// Accept an additional optional parameter of type (U)Int8/16/32/64 (0 by default).
|
||||
template <typename Name, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||
class FunctionRounding : public IFunction
|
||||
{
|
||||
@ -517,75 +633,58 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionRounding>(); }
|
||||
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
String getName() const override { return name; }
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
|
||||
|
||||
/// Get result types by argument types. If the function does not apply to these arguments, throw an exception.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if ((arguments.empty()) || (arguments.size() > 2))
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
|
||||
"Number of arguments for function {} doesn't match: passed {}, should be 1 or 2.",
|
||||
getName(), arguments.size());
|
||||
|
||||
for (const auto & type : arguments)
|
||||
if (!isNumber(type))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}",
|
||||
arguments[0]->getName(), getName());
|
||||
|
||||
return arguments[0];
|
||||
}
|
||||
|
||||
static Scale getScaleArg(const ColumnsWithTypeAndName & arguments)
|
||||
{
|
||||
if (arguments.size() == 2)
|
||||
{
|
||||
const IColumn & scale_column = *arguments[1].column;
|
||||
if (!isColumnConst(scale_column))
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Scale argument for rounding functions must be constant");
|
||||
|
||||
Field scale_field = assert_cast<const ColumnConst &>(scale_column).getField();
|
||||
if (scale_field.getType() != Field::Types::UInt64
|
||||
&& scale_field.getType() != Field::Types::Int64)
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Scale argument for rounding functions must have integer type");
|
||||
|
||||
Int64 scale64 = scale_field.get<Int64>();
|
||||
if (scale64 > std::numeric_limits<Scale>::max()
|
||||
|| scale64 < std::numeric_limits<Scale>::min())
|
||||
throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "Scale argument for rounding function is too large");
|
||||
|
||||
return scale64;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
FunctionArgumentDescriptors mandatory_args{
|
||||
{"x", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isNumber), nullptr, "A number to round"},
|
||||
};
|
||||
FunctionArgumentDescriptors optional_args{
|
||||
{"N", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isNativeInteger), nullptr, "The number of decimal places to round to"},
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args);
|
||||
|
||||
return arguments[0].type;
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnWithTypeAndName & column = arguments[0];
|
||||
Scale scale_arg = getScaleArg(arguments);
|
||||
const ColumnWithTypeAndName & value_arg = arguments[0];
|
||||
|
||||
ColumnPtr res;
|
||||
auto call = [&](const auto & types) -> bool
|
||||
auto call_data = [&](const auto & types) -> bool
|
||||
{
|
||||
using Types = std::decay_t<decltype(types)>;
|
||||
using DataType = typename Types::LeftType;
|
||||
using DataType = typename Types::RightType;
|
||||
|
||||
if constexpr (IsDataTypeNumber<DataType> || IsDataTypeDecimal<DataType>)
|
||||
if (arguments.size() > 1)
|
||||
{
|
||||
using FieldType = typename DataType::FieldType;
|
||||
res = Dispatcher<FieldType, rounding_mode, tie_breaking_mode>::apply(column.column.get(), scale_arg);
|
||||
const ColumnWithTypeAndName & scale_column = arguments[1];
|
||||
|
||||
auto call_scale = [&](const auto & scaleTypes) -> bool
|
||||
{
|
||||
using ScaleTypes = std::decay_t<decltype(scaleTypes)>;
|
||||
using ScaleType = typename ScaleTypes::RightType;
|
||||
|
||||
if (isColumnConst(*value_arg.column) && !isColumnConst(*scale_column.column))
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Scale column must be const for const data column");
|
||||
|
||||
res = Dispatcher<DataType, rounding_mode, tie_breaking_mode>::template apply<ScaleType>(value_arg.column.get(), scale_column.column.get());
|
||||
return true;
|
||||
};
|
||||
|
||||
TypeIndex right_index = scale_column.type->getTypeId();
|
||||
if (!callOnBasicType<void, true, false, false, false>(right_index, call_scale))
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Scale argument for rounding functions must have integer type");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
res = Dispatcher<DataType, rounding_mode, tie_breaking_mode>::template apply<int>(value_arg.column.get());
|
||||
return true;
|
||||
};
|
||||
|
||||
#if !defined(__SSE4_1__)
|
||||
@ -597,10 +696,9 @@ public:
|
||||
throw Exception(ErrorCodes::CANNOT_SET_ROUNDING_MODE, "Cannot set floating point rounding mode");
|
||||
#endif
|
||||
|
||||
if (!callOnIndexAndDataType<void>(column.type->getTypeId(), call))
|
||||
{
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}", column.name, getName());
|
||||
}
|
||||
TypeIndex left_index = value_arg.type->getTypeId();
|
||||
if (!callOnBasicType<void, true, true, true, false>(left_index, call_data))
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}", value_arg.name, getName());
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -617,9 +715,8 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** Rounds down to a number within explicitly specified array.
|
||||
* If the value is less than the minimal bound - returns the minimal bound.
|
||||
*/
|
||||
/// Rounds down to a number within explicitly specified array.
|
||||
/// If the value is less than the minimal bound - returns the minimal bound.
|
||||
class FunctionRoundDown : public IFunction
|
||||
{
|
||||
public:
|
||||
@ -627,7 +724,6 @@ public:
|
||||
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionRoundDown>(); }
|
||||
|
||||
String getName() const override { return name; }
|
||||
|
||||
bool isVariadic() const override { return false; }
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
2165
tests/queries/0_stateless/03165_round_scale_as_column.reference
Normal file
2165
tests/queries/0_stateless/03165_round_scale_as_column.reference
Normal file
File diff suppressed because it is too large
Load Diff
123
tests/queries/0_stateless/03165_round_scale_as_column.sql
Normal file
123
tests/queries/0_stateless/03165_round_scale_as_column.sql
Normal file
@ -0,0 +1,123 @@
|
||||
-- Tests functions round(), roundBankers(), floor(), ceil() and trunc() with default 'scale' argument
|
||||
SELECT toUInt8(number) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt16(number) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt32(number) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt64(number) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt8(number - 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt16(number - 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt32(number - 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt64(number - 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
|
||||
SELECT toFloat32(number - 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat64(number - 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat32((number - 10) / 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat64((number - 10) / 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||
|
||||
-- Functions round(), roundBankers(), floor(), ceil() and trunc() accept non-const 'scale' arguments
|
||||
SELECT toFloat32((number - 10) / 10) AS x, round(x, materialize(1)), roundBankers(x, materialize(1)), floor(x, materialize(1)), ceil(x, materialize(1)), trunc(x, materialize(1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat64((number - 10) / 10) AS x, round(x, materialize(1)), roundBankers(x, materialize(1)), floor(x, materialize(1)), ceil(x, materialize(1)), trunc(x, materialize(1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt8(number) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt16(number) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt32(number) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt64(number) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
|
||||
SELECT toInt8(number - 10) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt16(number - 10) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt32(number - 10) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt64(number - 10) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat32(number - 10) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat64(number - 10) AS x, round(x, materialize(-1)), roundBankers(x, materialize(-1)), floor(x, materialize(-1)), ceil(x, materialize(-1)), trunc(x, materialize(-1)) FROM system.numbers LIMIT 20;
|
||||
|
||||
SELECT toUInt8(number) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt16(number) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt32(number) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toUInt64(number) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt8(number - 10) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt16(number - 10) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt32(number - 10) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toInt64(number - 10) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat32(number - 10) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
SELECT toFloat64(number - 10) AS x, round(x, materialize(-2)), roundBankers(x, materialize(-2)), floor(x, materialize(-2)), ceil(x, materialize(-2)), trunc(x, materialize(-2)) FROM system.numbers LIMIT 20;
|
||||
|
||||
SELECT toString('CHECKPOINT1');
|
||||
|
||||
DROP TABLE IF EXISTS tab;
|
||||
|
||||
CREATE TABLE tab (
|
||||
id Int32,
|
||||
scale Int16,
|
||||
u8 UInt8, u16 UInt16, u32 UInt32, u64 UInt64,
|
||||
i8 Int8, i16 Int16, i32 Int32, i64 Int64,
|
||||
f32 Float32, f64 Float64
|
||||
) ENGINE = Memory;
|
||||
|
||||
INSERT INTO tab SELECT number , 0, number, number, number, number, number, number, number, number, number, number, FROM system.numbers LIMIT 20;
|
||||
INSERT INTO tab SELECT number+20 , 0, number+10, number+10, number+10, number+10, number-10, number-10, number-10, number-10, (toFloat32(number)-10)/10, (toFloat64(number)-10)/10, FROM system.numbers LIMIT 20;
|
||||
INSERT INTO tab SELECT number+40 , -1, number, number, number, number, number, number, number, number, number, number, FROM system.numbers LIMIT 20;
|
||||
INSERT INTO tab SELECT number+60 , -1, number+10, number+10, number+10, number+10, number-10, number-10, number-10, number-10, (toFloat32(number)-10)/10, (toFloat64(number)-10)/10, FROM system.numbers LIMIT 20;
|
||||
INSERT INTO tab SELECT number+80 , -2, number, number, number, number, number, number, number, number, number, number, FROM system.numbers LIMIT 20;
|
||||
INSERT INTO tab SELECT number+100, -2, number+10, number+10, number+10, number+10, number-10, number-10, number-10, number-10, (toFloat32(number)-10)/10, (toFloat64(number)-10)/10, FROM system.numbers LIMIT 20;
|
||||
|
||||
INSERT INTO tab SELECT number+200, -number, 0, 0, 0, 0, 0, 0, 0, 0, 12345.6789, 12345.6789, FROM system.numbers LIMIT 10;
|
||||
INSERT INTO tab SELECT number+210, -number, 0, 0, 0, 0, 0, 0, 0, 0, 12345.6789, 12345.6789, FROM system.numbers LIMIT 10;
|
||||
|
||||
INSERT INTO tab VALUES (300, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2.0, 2.0);
|
||||
INSERT INTO tab VALUES (301, 4, 20, 20, 20, 20, 20, 20, 20, 20, 20.0, 20.0);
|
||||
INSERT INTO tab VALUES (302, 4, 200, 200, 200, 200, 200, 200, 200, 200, 200.0, 200.0);
|
||||
INSERT INTO tab VALUES (303, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5.0, 5.0);
|
||||
INSERT INTO tab VALUES (304, 4, 50, 50, 50, 50, 50, 50, 50, 50, 50.0, 50.0);
|
||||
INSERT INTO tab VALUES (305, 4, 500, 500, 500, 500, 500, 500, 500, 500, 500.0, 500.0);
|
||||
|
||||
SELECT toString('id u8 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, u8 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id u16 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, u16 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id u32 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, u32 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id u64 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, u64 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id i8 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, i8 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id i16 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, i16 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id i32 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, i32 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id i64 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, i64 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id f32 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, f32 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
SELECT toString('id f64 scale round(u8, scale) roundBankers(x, scale) floor(x, scale) ceil(x, scale) trunc(x, scale)');
|
||||
SELECT id, f64 AS x, scale, round(x, scale), roundBankers(x, scale), floor(x, scale), ceil(x, scale), trunc(x, scale) FROM tab ORDER BY id;
|
||||
|
||||
DROP TABLE tab;
|
||||
--
|
||||
SELECT toString('CHECKPOINT2');
|
||||
|
||||
DROP TABLE IF EXISTS tab;
|
||||
|
||||
CREATE TABLE tab (
|
||||
id Int32,
|
||||
scale Int16,
|
||||
d32 Decimal32(4), d64 Decimal64(4), d128 Decimal128(4), d256 Decimal256(4)
|
||||
) ENGINE = Memory;
|
||||
|
||||
INSERT INTO tab VALUES (1, 6, toDecimal32('42.42', 4), toDecimal64('42.42', 4), toDecimal128('42.42', 4), toDecimal256('42.42', 4));
|
||||
INSERT INTO tab SELECT 2 , 6, cos(d32), cos(d64), cos(d128), cos(d256) FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 3 , 6, sqrt(d32), sqrt(d64), sqrt(d128), sqrt(d256) FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 4 , 6, lgamma(d32), lgamma(d64), lgamma(d128), lgamma(d256) FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 5 , 6, tgamma(d32)/1e50, tgamma(d64)/1e50, tgamma(d128)/1e50, tgamma(d256)/1e50 FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 6 , 8, sin(d32), sin(d64), sin(d128), sin(d256) FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 7 , 8, cos(d32), cos(d64), cos(d128), cos(d256) FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 8 , 8, log(d32), log(d64), log(d128), log(d256) FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 9 , 8, log2(d32), log2(d64), log2(d128), log2(d256) FROM tab WHERE id = 1;
|
||||
INSERT INTO tab SELECT 10, 8, log10(d32), log10(d64), log10(d128), log10(d256) FROM tab WHERE id = 1;
|
||||
|
||||
SELECT id, round(d32, scale), round(d64, scale), round(d128, scale), round(d256, scale) FROM tab ORDER BY id;
|
||||
|
||||
DROP TABLE tab;
|
||||
|
||||
SELECT round(1, 1);
|
||||
SELECT round(materialize(1), materialize(1));
|
||||
SELECT round(1, materialize(1)); --{serverError ILLEGAL_COLUMN}
|
||||
SELECT round(materialize(1), 1);
|
||||
SELECT materialize(10.1) AS x, ceil(x, toUInt256(123)); --{serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
Loading…
Reference in New Issue
Block a user