mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
Some fixups
This commit is contained in:
parent
830acd3a89
commit
1628c2985d
@ -6,49 +6,90 @@ sidebar_label: Rounding
|
|||||||
|
|
||||||
# Rounding Functions
|
# 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.
|
Returns the largest rounded number less than or equal `x`.
|
||||||
`N` is an integer, optional parameter. By default it is zero, which means to round to an integer.
|
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.
|
||||||
`N` may be negative.
|
|
||||||
|
|
||||||
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.
|
If rounding causes an overflow (for example, `floor(-128, -1)`), the result is undefined.
|
||||||
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.
|
|
||||||
|
|
||||||
## 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**
|
**Syntax**
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
trunc(input, precision)
|
truncate(x[, N])
|
||||||
```
|
```
|
||||||
|
|
||||||
Alias: `truncate`.
|
Alias: `trunc`.
|
||||||
|
|
||||||
**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`.
|
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
Query:
|
Query:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
SELECT trunc(123.499, 1) as res;
|
SELECT truncate(123.499, 1) as res;
|
||||||
```
|
```
|
||||||
|
|
||||||
```response
|
```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.
|
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
|
``` sql
|
||||||
round(expression [, decimal_places])
|
round(x[, N])
|
||||||
```
|
```
|
||||||
|
|
||||||
**Arguments**
|
**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).
|
- `x` — A number to round. [Float*](../data-types/float.md), [Decimal*](../data-types/decimal.md), or [(U)Int*](../data-types/int-uint.md).
|
||||||
- `decimal-places` — The number of decimal places to round to.
|
- `N` — The number of decimal places to round to. Integer. Defaults to `0`.
|
||||||
- If `decimal-places > 0` then the function rounds the value to the right of the decimal point.
|
- If `N > 0`, the function rounds 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 `N < 0`, the function rounds 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.
|
- If `N = 0`, the function rounds to the next integer.
|
||||||
|
|
||||||
**Returned value:**
|
**Returned value:**
|
||||||
|
|
||||||
The rounded number of the same type as the input number.
|
A rounded number of the same type as `x`.
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
Example of usage with Float:
|
Example with `Float` inputs:
|
||||||
|
|
||||||
``` sql
|
```sql
|
||||||
SELECT number / 2 AS x, round(x) FROM system.numbers LIMIT 3;
|
SELECT number / 2 AS x, round(x) FROM system.numbers LIMIT 3;
|
||||||
```
|
```
|
||||||
|
|
||||||
``` text
|
```
|
||||||
┌───x─┬─round(divide(number, 2))─┐
|
┌───x─┬─round(divide(number, 2))─┐
|
||||||
│ 0 │ 0 │
|
│ 0 │ 0 │
|
||||||
│ 0.5 │ 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;
|
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)'))─┐
|
┌───x─┬─round(CAST(divide(number, 2), 'Decimal(10, 4)'))─┐
|
||||||
│ 0 │ 0 │
|
│ 0 │ 0 │
|
||||||
│ 0.5 │ 1 │
|
│ 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;
|
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)'))─┐
|
┌──────x─┬─round(CAST(divide(number, 2), 'Decimal(10, 4)'))─┐
|
||||||
│ 0.0000 │ 0.0000 │
|
│ 0.0000 │ 0.0000 │
|
||||||
│ 0.5000 │ 1.0000 │
|
│ 0.5000 │ 1.0000 │
|
||||||
@ -151,9 +195,15 @@ round(3.65, 1) = 3.6
|
|||||||
|
|
||||||
Rounds a number to a specified decimal position.
|
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.
|
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**
|
**Syntax**
|
||||||
|
|
||||||
``` sql
|
``` sql
|
||||||
roundBankers(expression [, decimal_places])
|
roundBankers(x [, N])
|
||||||
```
|
```
|
||||||
|
|
||||||
**Arguments**
|
**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).
|
- `N > 0` — The function rounds the number to the given position right of the decimal point. Example: `roundBankers(3.55, 1) = 3.6`.
|
||||||
- `decimal-places` — Decimal places. An integer number.
|
- `N < 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 the given position right of the decimal point. Example: `roundBankers(3.55, 1) = 3.6`.
|
- `N = 0` — The function rounds the number to an integer. In this case the argument can be omitted. Example: `roundBankers(2.5) = 2`.
|
||||||
- `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`.
|
- `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**
|
**Returned value**
|
||||||
|
|
||||||
@ -185,13 +239,13 @@ A value rounded by the banker’s rounding method.
|
|||||||
|
|
||||||
Query:
|
Query:
|
||||||
|
|
||||||
``` sql
|
```sql
|
||||||
SELECT number / 2 AS x, roundBankers(x, 0) AS b fROM system.numbers limit 10
|
SELECT number / 2 AS x, roundBankers(x, 0) AS b fROM system.numbers limit 10
|
||||||
```
|
```
|
||||||
|
|
||||||
Result:
|
Result:
|
||||||
|
|
||||||
``` text
|
```
|
||||||
┌───x─┬─b─┐
|
┌───x─┬─b─┐
|
||||||
│ 0 │ 0 │
|
│ 0 │ 0 │
|
||||||
│ 0.5 │ 0 │
|
│ 0.5 │ 0 │
|
||||||
@ -208,7 +262,7 @@ Result:
|
|||||||
|
|
||||||
Examples of Banker’s rounding:
|
Examples of Banker’s rounding:
|
||||||
|
|
||||||
``` text
|
```
|
||||||
roundBankers(0.4) = 0
|
roundBankers(0.4) = 0
|
||||||
roundBankers(-3.5) = -4
|
roundBankers(-3.5) = -4
|
||||||
roundBankers(4.5) = 4
|
roundBankers(4.5) = 4
|
||||||
|
@ -40,26 +40,22 @@ namespace ErrorCodes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Rounding Functions:
|
/// Rounding Functions:
|
||||||
* round(x, N) - rounding to nearest (N = 0 by default). Use banker's rounding for floating point numbers.
|
/// - 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.
|
/// - 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).
|
/// - floor(x, N) is the largest number <= x (N = 0 by default).
|
||||||
* ceil(x, N) is the smallest 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).
|
/// - 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/// 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
|
enum class ScaleMode : uint8_t
|
||||||
{
|
{
|
||||||
Positive, // round to a number with N decimal places after the decimal point
|
Positive, // round to a number with N decimal places after the decimal point
|
||||||
@ -75,7 +71,7 @@ enum class RoundingMode : uint8_t
|
|||||||
Ceil = _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC,
|
Ceil = _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC,
|
||||||
Trunc = _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC,
|
Trunc = _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC,
|
||||||
#else
|
#else
|
||||||
Round = 8, /// Values are correspond to above just in case.
|
Round = 8, /// Values correspond to above values, just in case.
|
||||||
Floor = 9,
|
Floor = 9,
|
||||||
Ceil = 10,
|
Ceil = 10,
|
||||||
Trunc = 11,
|
Trunc = 11,
|
||||||
@ -84,16 +80,21 @@ enum class RoundingMode : uint8_t
|
|||||||
|
|
||||||
enum class TieBreakingMode : uint8_t
|
enum class TieBreakingMode : uint8_t
|
||||||
{
|
{
|
||||||
Auto, // use banker's rounding for floating point numbers, round up otherwise
|
Auto, /// banker's rounding for floating point numbers, round up otherwise
|
||||||
Bankers, // use banker's rounding
|
Bankers, /// banker's rounding
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Vectorize : uint8_t
|
||||||
|
{
|
||||||
|
No,
|
||||||
|
Yes
|
||||||
};
|
};
|
||||||
|
|
||||||
/// For N, no more than the number of digits in the largest type.
|
/// For N, no more than the number of digits in the largest type.
|
||||||
using Scale = Int16;
|
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>
|
template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, TieBreakingMode tie_breaking_mode>
|
||||||
struct IntegerRoundingComputation
|
struct IntegerRoundingComputation
|
||||||
{
|
{
|
||||||
@ -150,7 +151,7 @@ struct IntegerRoundingComputation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
std::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE T compute(T x, T scale)
|
static ALWAYS_INLINE T compute(T x, T scale)
|
||||||
@ -164,10 +165,11 @@ struct IntegerRoundingComputation
|
|||||||
return computeImpl(x, scale);
|
return computeImpl(x, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
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)
|
if constexpr (sizeof(T) <= sizeof(scale) && scale_mode == ScaleMode::Negative)
|
||||||
{
|
{
|
||||||
@ -180,20 +182,23 @@ struct IntegerRoundingComputation
|
|||||||
*out = compute(*in, static_cast<T>(scale));
|
*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);
|
*out = compute(*in, scale);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T, bool is_vectorized = true>
|
template <typename T, Vectorize vectorize>
|
||||||
class BaseFloatRoundingComputation;
|
class FloatRoundingComputationBase;
|
||||||
|
|
||||||
#ifdef __SSE4_1__
|
#ifdef __SSE4_1__
|
||||||
|
|
||||||
|
/// Vectorized implementation for x86.
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class BaseFloatRoundingComputation<Float32, true>
|
class FloatRoundingComputationBase<Float32, Vectorize::Yes>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ScalarType = Float32;
|
using ScalarType = Float32;
|
||||||
@ -214,7 +219,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class BaseFloatRoundingComputation<Float64, true>
|
class FloatRoundingComputationBase<Float64, Vectorize::Yes>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ScalarType = Float64;
|
using ScalarType = Float64;
|
||||||
@ -236,7 +241,7 @@ public:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Implementation for ARM/columnar scale argument. Not vectorized.
|
/// Sequential implementation for ARM. Also used for scalar arguments.
|
||||||
|
|
||||||
inline float roundWithMode(float x, RoundingMode mode)
|
inline float roundWithMode(float x, RoundingMode mode)
|
||||||
{
|
{
|
||||||
@ -248,7 +253,7 @@ inline float roundWithMode(float x, RoundingMode mode)
|
|||||||
case RoundingMode::Trunc: return truncf(x);
|
case RoundingMode::Trunc: return truncf(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
std::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double roundWithMode(double x, RoundingMode mode)
|
inline double roundWithMode(double x, RoundingMode mode)
|
||||||
@ -261,11 +266,11 @@ inline double roundWithMode(double x, RoundingMode mode)
|
|||||||
case RoundingMode::Trunc: return trunc(x);
|
case RoundingMode::Trunc: return trunc(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
std::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class BaseFloatRoundingComputation<T, false>
|
class FloatRoundingComputationBase<T, Vectorize::No>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ScalarType = T;
|
using ScalarType = T;
|
||||||
@ -288,10 +293,10 @@ public:
|
|||||||
|
|
||||||
/** Implementation of low-level round-off functions for floating-point values.
|
/** Implementation of low-level round-off functions for floating-point values.
|
||||||
*/
|
*/
|
||||||
template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, bool is_vectorized>
|
template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, Vectorize vectorize>
|
||||||
class FloatRoundingComputation : public BaseFloatRoundingComputation<T, is_vectorized>
|
class FloatRoundingComputation : public FloatRoundingComputationBase<T, vectorize>
|
||||||
{
|
{
|
||||||
using Base = BaseFloatRoundingComputation<T, is_vectorized>;
|
using Base = FloatRoundingComputationBase<T, vectorize>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void compute(const T * __restrict in, const typename Base::VectorType & scale, T * __restrict out)
|
static void compute(const T * __restrict in, const typename Base::VectorType & scale, T * __restrict out)
|
||||||
@ -323,14 +328,14 @@ struct FloatRoundingImpl
|
|||||||
private:
|
private:
|
||||||
static_assert(!is_decimal<T>);
|
static_assert(!is_decimal<T>);
|
||||||
|
|
||||||
template <bool is_vectorized =
|
template <Vectorize vectorize =
|
||||||
#ifdef __SSE4_1__
|
#ifdef __SSE4_1__
|
||||||
true
|
Vectorize::Yes
|
||||||
#else
|
#else
|
||||||
false
|
Vectorize::Nos
|
||||||
#endif
|
#endif
|
||||||
>
|
>
|
||||||
using Op = FloatRoundingComputation<T, rounding_mode, scale_mode, is_vectorized>;
|
using Op = FloatRoundingComputation<T, rounding_mode, scale_mode, vectorize>;
|
||||||
using Data = std::array<T, Op<>::data_count>;
|
using Data = std::array<T, Op<>::data_count>;
|
||||||
using ColumnType = ColumnVector<T>;
|
using ColumnType = ColumnVector<T>;
|
||||||
using Container = typename ColumnType::Container;
|
using Container = typename ColumnType::Container;
|
||||||
@ -370,7 +375,7 @@ public:
|
|||||||
|
|
||||||
static void applyOne(const T* __restrict in, size_t scale, T* __restrict out)
|
static void applyOne(const T* __restrict in, size_t scale, T* __restrict out)
|
||||||
{
|
{
|
||||||
using ScalarOp = Op<false>;
|
using ScalarOp = Op<Vectorize::No>;
|
||||||
auto s = ScalarOp::prepare(scale);
|
auto s = ScalarOp::prepare(scale);
|
||||||
ScalarOp::compute(in, s, out);
|
ScalarOp::compute(in, s, out);
|
||||||
}
|
}
|
||||||
@ -485,8 +490,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Select the appropriate processing algorithm depending on the scale.
|
/// Select the appropriate processing algorithm depending on the scale.
|
||||||
*/
|
|
||||||
inline void validateScale(Int64 scale64)
|
inline void validateScale(Int64 scale64)
|
||||||
{
|
{
|
||||||
if (scale64 > std::numeric_limits<Scale>::max() || scale64 < std::numeric_limits<Scale>::min())
|
if (scale64 > std::numeric_limits<Scale>::max() || scale64 < std::numeric_limits<Scale>::min())
|
||||||
@ -495,7 +499,7 @@ inline void validateScale(Int64 scale64)
|
|||||||
|
|
||||||
inline Scale getScaleArg(const ColumnConst* scale_col)
|
inline Scale getScaleArg(const ColumnConst* scale_col)
|
||||||
{
|
{
|
||||||
const auto& scale_field = scale_col->getField();
|
const auto & scale_field = scale_col->getField();
|
||||||
|
|
||||||
Int64 scale64 = scale_field.get<Int64>();
|
Int64 scale64 = scale_field.get<Int64>();
|
||||||
validateScale(scale64);
|
validateScale(scale64);
|
||||||
@ -503,6 +507,7 @@ inline Scale getScaleArg(const ColumnConst* scale_col)
|
|||||||
return scale64;
|
return scale64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generic dispatcher
|
||||||
template <typename T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
template <typename T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||||
struct Dispatcher
|
struct Dispatcher
|
||||||
{
|
{
|
||||||
@ -512,44 +517,44 @@ struct Dispatcher
|
|||||||
IntegerRoundingImpl<T, rounding_mode, scale_mode, tie_breaking_mode>>;
|
IntegerRoundingImpl<T, rounding_mode, scale_mode, tie_breaking_mode>>;
|
||||||
|
|
||||||
template <typename ScaleType>
|
template <typename ScaleType>
|
||||||
static ColumnPtr apply(const IColumn * data_col, const IColumn * scale_col = nullptr)
|
static ColumnPtr apply(const IColumn * value_col, const IColumn * scale_col = nullptr)
|
||||||
{
|
{
|
||||||
const auto & col = checkAndGetColumn<ColumnVector<T>>(*data_col);
|
const auto & value_col_typed = checkAndGetColumn<ColumnVector<T>>(*value_col);
|
||||||
auto col_res = ColumnVector<T>::create();
|
auto col_res = ColumnVector<T>::create();
|
||||||
|
|
||||||
typename ColumnVector<T>::Container & vec_res = col_res->getData();
|
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 (!vec_res.empty())
|
||||||
{
|
{
|
||||||
using ColVecScale = ColumnVector<ScaleType>;
|
|
||||||
if (scale_col == nullptr || isColumnConst(*scale_col))
|
if (scale_col == nullptr || isColumnConst(*scale_col))
|
||||||
{
|
{
|
||||||
auto scale_arg = scale_col == nullptr ? 0 : getScaleArg(checkAndGetColumnConst<ColVecScale>(scale_col));
|
auto scale_arg = (scale_col == nullptr) ? 0 : getScaleArg(checkAndGetColumnConst<ColumnVector<ScaleType>>(scale_col));
|
||||||
if (scale_arg == 0)
|
if (scale_arg == 0)
|
||||||
{
|
{
|
||||||
size_t scale = 1;
|
size_t scale = 1;
|
||||||
FunctionRoundingImpl<ScaleMode::Zero>::apply(col.getData(), scale, vec_res);
|
FunctionRoundingImpl<ScaleMode::Zero>::apply(value_col_typed.getData(), scale, vec_res);
|
||||||
}
|
}
|
||||||
else if (scale_arg > 0)
|
else if (scale_arg > 0)
|
||||||
{
|
{
|
||||||
size_t scale = intExp10(scale_arg);
|
size_t scale = intExp10(scale_arg);
|
||||||
FunctionRoundingImpl<ScaleMode::Positive>::apply(col.getData(), scale, vec_res);
|
FunctionRoundingImpl<ScaleMode::Positive>::apply(value_col_typed.getData(), scale, vec_res);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t scale = intExp10(-scale_arg);
|
size_t scale = intExp10(-scale_arg);
|
||||||
FunctionRoundingImpl<ScaleMode::Negative>::apply(col.getData(), scale, vec_res);
|
FunctionRoundingImpl<ScaleMode::Negative>::apply(value_col_typed.getData(), scale, vec_res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (const auto scale_typed = checkAndGetColumn<ColVecScale>(scale_col))
|
/// Non-const scale argument:
|
||||||
|
else if (const auto * scale_col_typed = checkAndGetColumn<ColumnVector<ScaleType>>(scale_col))
|
||||||
{
|
{
|
||||||
const auto & in = col.getData();
|
const auto & value_data = value_col_typed.getData();
|
||||||
const auto & scale_data = scale_typed->getData();
|
const auto & scale_data = scale_col_typed->getData();
|
||||||
const size_t count = in.size();
|
const size_t rows = value_data.size();
|
||||||
|
|
||||||
const T * end_in = in.data() + count;
|
const T * end_in = value_data.data() + rows;
|
||||||
const T * __restrict p_in = in.data();
|
const T * __restrict p_in = value_data.data();
|
||||||
const ScaleType * __restrict p_scale = scale_data.data();
|
const ScaleType * __restrict p_scale = scale_data.data();
|
||||||
T * __restrict p_out = vec_res.data();
|
T * __restrict p_out = vec_res.data();
|
||||||
|
|
||||||
@ -585,36 +590,37 @@ struct Dispatcher
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Dispatcher for Decimal inputs
|
||||||
template <is_decimal T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
template <is_decimal T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||||
struct Dispatcher<T, rounding_mode, tie_breaking_mode>
|
struct Dispatcher<T, rounding_mode, tie_breaking_mode>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <typename ScaleType>
|
template <typename ScaleType>
|
||||||
static ColumnPtr apply(const IColumn * data_col, const IColumn* scale_col = nullptr)
|
static ColumnPtr apply(const IColumn * value_col, const IColumn* scale_col = nullptr)
|
||||||
{
|
{
|
||||||
const auto & col = checkAndGetColumn<ColumnDecimal<T>>(*data_col);
|
const auto & value_col_typed = checkAndGetColumn<ColumnDecimal<T>>(*value_col);
|
||||||
const typename ColumnDecimal<T>::Container & vec_src = col.getData();
|
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();
|
auto & vec_res = col_res->getData();
|
||||||
|
|
||||||
if (!vec_res.empty())
|
if (!vec_res.empty())
|
||||||
{
|
{
|
||||||
using ColVecScale = ColumnVector<ScaleType>;
|
|
||||||
if (scale_col == nullptr || isColumnConst(*scale_col))
|
if (scale_col == nullptr || isColumnConst(*scale_col))
|
||||||
{
|
{
|
||||||
auto scale_arg = scale_col == nullptr ? 0 : getScaleArg(checkAndGetColumnConst<ColVecScale>(scale_col));
|
auto scale_arg = scale_col == nullptr ? 0 : getScaleArg(checkAndGetColumnConst<ColumnVector<ScaleType>>(scale_col));
|
||||||
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::apply(col.getData(), col.getScale(), vec_res, scale_arg);
|
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::apply(value_col_typed.getData(), value_col_typed.getScale(), vec_res, scale_arg);
|
||||||
}
|
}
|
||||||
else if (const auto scale_typed = checkAndGetColumn<ColVecScale>(scale_col))
|
/// Non-cosnt scale argument
|
||||||
|
else if (const auto * scale_col_typed = checkAndGetColumn<ColumnVector<ScaleType>>(scale_col))
|
||||||
{
|
{
|
||||||
const auto & scale = scale_typed->getData();
|
const auto & scale = scale_col_typed->getData();
|
||||||
const size_t count = vec_src.size();
|
const size_t rows = vec_src.size();
|
||||||
|
|
||||||
using NativeType = typename T::NativeType;
|
using NativeType = typename T::NativeType;
|
||||||
const NativeType * __restrict p_in = reinterpret_cast<const NativeType *>(vec_src.data());
|
const NativeType * __restrict p_in = reinterpret_cast<const NativeType *>(vec_src.data());
|
||||||
const ScaleType * __restrict p_scale = scale.data();
|
const ScaleType * __restrict p_scale = scale.data();
|
||||||
const NativeType * end_in = p_in + count;
|
const NativeType * end_in = p_in + rows;
|
||||||
NativeType * __restrict p_out = reinterpret_cast<NativeType *>(vec_res.data());
|
NativeType * __restrict p_out = reinterpret_cast<NativeType *>(vec_res.data());
|
||||||
while (p_in < end_in)
|
while (p_in < end_in)
|
||||||
{
|
{
|
||||||
@ -622,7 +628,7 @@ public:
|
|||||||
validateScale(scale64);
|
validateScale(scale64);
|
||||||
Scale raw_scale = scale64;
|
Scale raw_scale = scale64;
|
||||||
|
|
||||||
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::applyOne(p_in, col.getScale(), p_out, raw_scale);
|
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::applyOne(p_in, value_col_typed.getScale(), p_out, raw_scale);
|
||||||
++p_in;
|
++p_in;
|
||||||
++p_scale;
|
++p_scale;
|
||||||
++p_out;
|
++p_out;
|
||||||
@ -634,9 +640,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A template for functions that round the value of an input parameter of type
|
/// Functions that round the value of an input parameter of type (U)Int8/16/32/64, Float32/64 or Decimal32/64/128.
|
||||||
* (U)Int8/16/32/64, Float32/64 or Decimal32/64/128, and accept an additional optional parameter (default is 0).
|
/// Accept an additional optional parameter (0 by default).
|
||||||
*/
|
|
||||||
template <typename Name, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
template <typename Name, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||||
class FunctionRounding : public IFunction
|
class FunctionRounding : public IFunction
|
||||||
{
|
{
|
||||||
@ -644,16 +649,12 @@ public:
|
|||||||
static constexpr auto name = Name::name;
|
static constexpr auto name = Name::name;
|
||||||
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionRounding>(); }
|
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionRounding>(); }
|
||||||
|
|
||||||
String getName() const override
|
String getName() const override { return name; }
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isVariadic() const override { return true; }
|
bool isVariadic() const override { return true; }
|
||||||
size_t getNumberOfArguments() const override { return 0; }
|
size_t getNumberOfArguments() const override { return 0; }
|
||||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
|
||||||
|
bool useDefaultImplementationForConstants() const override { return true; }
|
||||||
|
|
||||||
/// 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
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||||
{
|
{
|
||||||
if ((arguments.empty()) || (arguments.size() > 2))
|
if ((arguments.empty()) || (arguments.size() > 2))
|
||||||
@ -669,14 +670,12 @@ public:
|
|||||||
return arguments[0];
|
return arguments[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override { return true; }
|
|
||||||
|
|
||||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||||
{
|
{
|
||||||
const ColumnWithTypeAndName & data_column = arguments[0];
|
const ColumnWithTypeAndName & value_arg = arguments[0];
|
||||||
|
|
||||||
ColumnPtr res;
|
ColumnPtr res;
|
||||||
auto callData = [&](const auto & types) -> bool
|
auto call_data = [&](const auto & types) -> bool
|
||||||
{
|
{
|
||||||
using Types = std::decay_t<decltype(types)>;
|
using Types = std::decay_t<decltype(types)>;
|
||||||
using DataType = typename Types::RightType;
|
using DataType = typename Types::RightType;
|
||||||
@ -685,24 +684,24 @@ public:
|
|||||||
{
|
{
|
||||||
const ColumnWithTypeAndName & scale_column = arguments[1];
|
const ColumnWithTypeAndName & scale_column = arguments[1];
|
||||||
|
|
||||||
auto callScale = [&](const auto & scaleTypes) -> bool
|
auto call_scale = [&](const auto & scaleTypes) -> bool
|
||||||
{
|
{
|
||||||
using ScaleTypes = std::decay_t<decltype(scaleTypes)>;
|
using ScaleTypes = std::decay_t<decltype(scaleTypes)>;
|
||||||
using ScaleType = typename ScaleTypes::RightType;
|
using ScaleType = typename ScaleTypes::RightType;
|
||||||
|
|
||||||
if (isColumnConst(*data_column.column) && !isColumnConst(*scale_column.column))
|
if (isColumnConst(*value_arg.column) && !isColumnConst(*scale_column.column))
|
||||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Scale column must be const for const data 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>(data_column.column.get(), scale_column.column.get());
|
res = Dispatcher<DataType, rounding_mode, tie_breaking_mode>::template apply<ScaleType>(value_arg.column.get(), scale_column.column.get());
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
TypeIndex right_index = scale_column.type->getTypeId();
|
TypeIndex right_index = scale_column.type->getTypeId();
|
||||||
if (!callOnBasicType<void, true, false, false, false>(right_index, callScale))
|
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");
|
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Scale argument for rounding functions must have integer type");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
res = Dispatcher<DataType, rounding_mode, tie_breaking_mode>::template apply<int>(data_column.column.get());
|
res = Dispatcher<DataType, rounding_mode, tie_breaking_mode>::template apply<int>(value_arg.column.get());
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -715,9 +714,9 @@ public:
|
|||||||
throw Exception(ErrorCodes::CANNOT_SET_ROUNDING_MODE, "Cannot set floating point rounding mode");
|
throw Exception(ErrorCodes::CANNOT_SET_ROUNDING_MODE, "Cannot set floating point rounding mode");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TypeIndex left_index = data_column.type->getTypeId();
|
TypeIndex left_index = value_arg.type->getTypeId();
|
||||||
if (!callOnBasicType<void, true, true, true, false>(left_index, callData))
|
if (!callOnBasicType<void, true, true, true, false>(left_index, call_data))
|
||||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}", data_column.name, getName());
|
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}", value_arg.name, getName());
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -734,9 +733,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Rounds down to a number within explicitly specified array.
|
/// Rounds down to a number within explicitly specified array.
|
||||||
* If the value is less than the minimal bound - returns the minimal bound.
|
/// If the value is less than the minimal bound - returns the minimal bound.
|
||||||
*/
|
|
||||||
class FunctionRoundDown : public IFunction
|
class FunctionRoundDown : public IFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -744,7 +742,6 @@ public:
|
|||||||
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionRoundDown>(); }
|
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionRoundDown>(); }
|
||||||
|
|
||||||
String getName() const override { return name; }
|
String getName() const override { return name; }
|
||||||
|
|
||||||
bool isVariadic() const override { return false; }
|
bool isVariadic() const override { return false; }
|
||||||
size_t getNumberOfArguments() const override { return 2; }
|
size_t getNumberOfArguments() const override { return 2; }
|
||||||
bool useDefaultImplementationForConstants() const override { return true; }
|
bool useDefaultImplementationForConstants() const override { return true; }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
-- Regression test that functions round(), roundBankers(), floor(), ceil() and trunc() work with default 'scale' argument (= the 2nd argument)
|
-- 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 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 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 toUInt32(number) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||||
@ -7,13 +7,13 @@ SELECT toInt8(number - 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), t
|
|||||||
SELECT toInt16(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 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 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 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 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 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;
|
SELECT toFloat64((number - 10) / 10) AS x, round(x), roundBankers(x), floor(x), ceil(x), trunc(x) FROM system.numbers LIMIT 20;
|
||||||
|
|
||||||
-- Test that functions round(), roundBankers(), floor(), ceil() and trunc() accept non-const 'scale' argument
|
-- 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 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 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 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;
|
||||||
@ -41,9 +41,9 @@ SELECT toFloat64(number - 10) AS x, round(x, materialize(-2)), roundBankers(x, m
|
|||||||
|
|
||||||
SELECT toString('CHECKPOINT1');
|
SELECT toString('CHECKPOINT1');
|
||||||
|
|
||||||
DROP TABLE IF EXISTS tround;
|
DROP TABLE IF EXISTS tab;
|
||||||
|
|
||||||
CREATE TABLE tround (
|
CREATE TABLE tab (
|
||||||
id Int32,
|
id Int32,
|
||||||
scale Int16,
|
scale Int16,
|
||||||
u8 UInt8, u16 UInt16, u32 UInt32, u64 UInt64,
|
u8 UInt8, u16 UInt16, u32 UInt32, u64 UInt64,
|
||||||
@ -51,75 +51,72 @@ CREATE TABLE tround (
|
|||||||
f32 Float32, f64 Float64
|
f32 Float32, f64 Float64
|
||||||
) ENGINE = Memory;
|
) ENGINE = Memory;
|
||||||
|
|
||||||
INSERT INTO tround SELECT number , 0, number, number, number, number, number, number, number, number, number, number, FROM system.numbers LIMIT 20;
|
INSERT INTO tab SELECT number , 0, number, number, number, number, number, number, number, number, number, number, FROM system.numbers LIMIT 20;
|
||||||
INSERT INTO tround 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+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 tround SELECT number+40 , -1, number, number, number, number, number, number, number, number, number, number, 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 tround 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+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 tround SELECT number+80 , -2, number, number, number, number, number, number, number, number, number, number, 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 tround 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+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 tround 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+200, -number, 0, 0, 0, 0, 0, 0, 0, 0, 12345.6789, 12345.6789, FROM system.numbers LIMIT 10;
|
||||||
INSERT INTO tround SELECT number+210, -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 tround VALUES (300, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2.0, 2.0);
|
INSERT INTO tab VALUES (300, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2.0, 2.0);
|
||||||
INSERT INTO tround VALUES (301, 4, 20, 20, 20, 20, 20, 20, 20, 20, 20.0, 20.0);
|
INSERT INTO tab VALUES (301, 4, 20, 20, 20, 20, 20, 20, 20, 20, 20.0, 20.0);
|
||||||
INSERT INTO tround VALUES (302, 4, 200, 200, 200, 200, 200, 200, 200, 200, 200.0, 200.0);
|
INSERT INTO tab VALUES (302, 4, 200, 200, 200, 200, 200, 200, 200, 200, 200.0, 200.0);
|
||||||
INSERT INTO tround VALUES (303, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5.0, 5.0);
|
INSERT INTO tab VALUES (303, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5.0, 5.0);
|
||||||
INSERT INTO tround VALUES (304, 4, 50, 50, 50, 50, 50, 50, 50, 50, 50.0, 50.0);
|
INSERT INTO tab VALUES (304, 4, 50, 50, 50, 50, 50, 50, 50, 50, 50.0, 50.0);
|
||||||
INSERT INTO tround VALUES (305, 4, 500, 500, 500, 500, 500, 500, 500, 500, 500.0, 500.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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 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 tround ORDER BY id;
|
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 IF EXISTS tround;
|
DROP TABLE tab;
|
||||||
--
|
--
|
||||||
SELECT toString('CHECKPOINT2');
|
SELECT toString('CHECKPOINT2');
|
||||||
|
|
||||||
DROP TABLE IF EXISTS tround2;
|
DROP TABLE IF EXISTS tab;
|
||||||
|
|
||||||
CREATE TABLE tround2 (
|
CREATE TABLE tab (
|
||||||
id Int32,
|
id Int32,
|
||||||
scale Int16,
|
scale Int16,
|
||||||
d32 Decimal32(4), d64 Decimal64(4), d128 Decimal128(4), d256 Decimal256(4)
|
d32 Decimal32(4), d64 Decimal64(4), d128 Decimal128(4), d256 Decimal256(4)
|
||||||
) ENGINE = Memory;
|
) ENGINE = Memory;
|
||||||
|
|
||||||
INSERT INTO tround2 VALUES (1, 6, toDecimal32('42.42', 4), toDecimal64('42.42', 4), toDecimal128('42.42', 4), toDecimal256('42.42', 4));
|
INSERT INTO tab VALUES (1, 6, toDecimal32('42.42', 4), toDecimal64('42.42', 4), toDecimal128('42.42', 4), toDecimal256('42.42', 4));
|
||||||
INSERT INTO tround2 SELECT 2 , 6, cos(d32), cos(d64), cos(d128), cos(d256) FROM tround2 WHERE id = 1;
|
INSERT INTO tab SELECT 2 , 6, cos(d32), cos(d64), cos(d128), cos(d256) FROM tab WHERE id = 1;
|
||||||
INSERT INTO tround2 SELECT 3 , 6, sqrt(d32), sqrt(d64), sqrt(d128), sqrt(d256) FROM tround2 WHERE id = 1;
|
INSERT INTO tab SELECT 3 , 6, sqrt(d32), sqrt(d64), sqrt(d128), sqrt(d256) FROM tab WHERE id = 1;
|
||||||
INSERT INTO tround2 SELECT 4 , 6, lgamma(d32), lgamma(d64), lgamma(d128), lgamma(d256) FROM tround2 WHERE id = 1;
|
INSERT INTO tab SELECT 4 , 6, lgamma(d32), lgamma(d64), lgamma(d128), lgamma(d256) FROM tab WHERE id = 1;
|
||||||
INSERT INTO tround2 SELECT 5 , 6, tgamma(d32)/1e50, tgamma(d64)/1e50, tgamma(d128)/1e50, tgamma(d256)/1e50 FROM tround2 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 tround2 SELECT 6 , 8, sin(d32), sin(d64), sin(d128), sin(d256) FROM tround2 WHERE id = 1;
|
INSERT INTO tab SELECT 6 , 8, sin(d32), sin(d64), sin(d128), sin(d256) FROM tab WHERE id = 1;
|
||||||
INSERT INTO tround2 SELECT 7 , 8, cos(d32), cos(d64), cos(d128), cos(d256) FROM tround2 WHERE id = 1;
|
INSERT INTO tab SELECT 7 , 8, cos(d32), cos(d64), cos(d128), cos(d256) FROM tab WHERE id = 1;
|
||||||
INSERT INTO tround2 SELECT 8 , 8, log(d32), log(d64), log(d128), log(d256) FROM tround2 WHERE id = 1;
|
INSERT INTO tab SELECT 8 , 8, log(d32), log(d64), log(d128), log(d256) FROM tab WHERE id = 1;
|
||||||
INSERT INTO tround2 SELECT 9 , 8, log2(d32), log2(d64), log2(d128), log2(d256) FROM tround2 WHERE id = 1;
|
INSERT INTO tab SELECT 9 , 8, log2(d32), log2(d64), log2(d128), log2(d256) FROM tab WHERE id = 1;
|
||||||
INSERT INTO tround2 SELECT 10, 8, log10(d32), log10(d64), log10(d128), log10(d256) FROM tround2 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 tround2 ORDER BY id;
|
SELECT id, round(d32, scale), round(d64, scale), round(d128, scale), round(d256, scale) FROM tab ORDER BY id;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS tround2;
|
DROP TABLE tab;
|
||||||
|
|
||||||
SELECT round(1, 1);
|
SELECT round(1, 1);
|
||||||
SELECT round(materialize(1), materialize(1));
|
SELECT round(materialize(1), materialize(1));
|
||||||
SELECT round(1, materialize(1)); --{serverError ILLEGAL_COLUMN}
|
SELECT round(1, materialize(1)); --{serverError ILLEGAL_COLUMN}
|
||||||
SELECT round(materialize(1), 1);
|
SELECT round(materialize(1), 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user