282 lines
10 KiB
C
282 lines
10 KiB
C
/*
|
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
*
|
|
* openGauss is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
*
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PSL v2 for more details.
|
|
* ---------------------------------------------------------------------------------------
|
|
*
|
|
* biginteger.h
|
|
* Definitions for the big integer data type
|
|
*
|
|
* Big integer(int64/int128) is one implementation of numeric data
|
|
* type, the purpose is to increase speed of numeric operators.
|
|
*
|
|
* IDENTIFICATION
|
|
* src/include/utils/biginteger.h
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
*/
|
|
#ifndef SRC_INCLUDE_UTILS_BIGINTERGER_H_
|
|
#define SRC_INCLUDE_UTILS_BIGINTERGER_H_
|
|
|
|
#include "postgres.h"
|
|
#include "knl/knl_variable.h"
|
|
#include "c.h"
|
|
#include "catalog/pg_type.h"
|
|
#include "fmgr.h"
|
|
#include "vecexecutor/vectorbatch.h"
|
|
#include "utils/array.h"
|
|
#include "utils/numeric.h"
|
|
#include "utils/numeric_gs.h"
|
|
|
|
/*
|
|
* int32 integer:
|
|
* int32 value must in [-2147483648, 2147483647]
|
|
* abs(int32_value) < 10^11, so the max dscale of int32 can represent is 10.
|
|
*
|
|
* int64 integer:
|
|
* int64 value must in [-9223372036854775808, 9223372036854775807]
|
|
* abs(int64_value) < 10^20, so the max dscale of int64 can represent is 19.
|
|
*
|
|
* int128 integer:
|
|
* int128 value must in [-170141183460469231731687303715884105728,
|
|
* 170141183460469231731687303715884105727]
|
|
* abs(int128_value) < 10^40, so the max dscale of int128 can represent is
|
|
* 39, but some numbers with 39 digits can't be stored by int128, so just
|
|
* choose 38 instead because one number with 38 digits must can be stored
|
|
* by int128.
|
|
*/
|
|
#define MAXINT32DIGIT 10
|
|
#define MAXINT64DIGIT 19
|
|
#define MAXINT128DIGIT 38
|
|
|
|
/* the flag of failed dscale encoding */
|
|
#define FAILED_DSCALE_ENCODING -1
|
|
|
|
/* the value of 10^18, it is used for print int128 data */
|
|
#define P10_INT64 1000000000000000000LL /* 18 zeroes */
|
|
|
|
/* this macro represents the first dimension index of BiAggFunMatrix */
|
|
#define BI_AGG_ADD 0
|
|
#define BI_AGG_SMALLER 1
|
|
#define BI_AGG_LARGER 2
|
|
|
|
/*
|
|
* determine whether one num can convert to int64 or int128 by the
|
|
* num's scale, this macro is used for both executor and storage modules.
|
|
*/
|
|
#define CAN_CONVERT_BI64(whole_scale) ((whole_scale) <= (MAXINT64DIGIT - 1))
|
|
#define CAN_CONVERT_BI128(whole_scale) ((whole_scale) <= MAXINT128DIGIT)
|
|
|
|
/* jduge whether int64 data can be transformed to int8 */
|
|
#define INT64_INT8_EQ(data) ((data) == (int64)((int8)(data)))
|
|
|
|
/* jduge whether int64 data can be transformed to int16 */
|
|
#define INT64_INT16_EQ(data) ((data) == (int64)((int16)(data)))
|
|
|
|
/* jduge whether int64 data can be transformed to int32 */
|
|
#define INT64_INT32_EQ(data) ((data) == (int64)((int32)(data)))
|
|
|
|
/* jduge whether int128 data can be transformed to int64 */
|
|
#define INT128_INT64_EQ(data) ((data) == (int128)((int64)(data)))
|
|
|
|
/*
|
|
* align two int64 vals by dscale, multipler is factorial of 10.
|
|
* set ScaleMultipler[i] = 10^i, i is between 0 and 18.
|
|
* 10^19 is out of int64 bound, so set ScaleMultipler[19] to 0.
|
|
*/
|
|
extern const int64 ScaleMultipler[20];
|
|
|
|
/*
|
|
* fast compare whether the result of arg * ScaleMultipler[i]
|
|
* is out of int64 bound.
|
|
* Int64MultiOutOfBound[i] = INT64_MIN / ScaleMultipler[i]
|
|
*/
|
|
extern const int64 Int64MultiOutOfBound[20];
|
|
|
|
/*
|
|
* @Description: calculates the factorial of 10, align two int128
|
|
* vals by dscale, multipler is factorial of 10, set
|
|
* values[i] = 10^i, i is between 0 and 38.
|
|
* @IN scale: the scale'th power
|
|
* @Return: the factorial of 10
|
|
*/
|
|
inline int128 getScaleMultiplier(int scale)
|
|
{
|
|
Assert(scale >= 0 && scale <= MAXINT128DIGIT);
|
|
static const int128 values[] = {static_cast<int128>(1LL),
|
|
static_cast<int128>(10LL),
|
|
static_cast<int128>(100LL),
|
|
static_cast<int128>(1000LL),
|
|
static_cast<int128>(10000LL),
|
|
static_cast<int128>(100000LL),
|
|
static_cast<int128>(1000000LL),
|
|
static_cast<int128>(10000000LL),
|
|
static_cast<int128>(100000000LL),
|
|
static_cast<int128>(1000000000LL),
|
|
static_cast<int128>(10000000000LL),
|
|
static_cast<int128>(100000000000LL),
|
|
static_cast<int128>(1000000000000LL),
|
|
static_cast<int128>(10000000000000LL),
|
|
static_cast<int128>(100000000000000LL),
|
|
static_cast<int128>(1000000000000000LL),
|
|
static_cast<int128>(10000000000000000LL),
|
|
static_cast<int128>(100000000000000000LL),
|
|
static_cast<int128>(1000000000000000000LL),
|
|
static_cast<int128>(1000000000000000000LL) * 10LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100LL,
|
|
static_cast<int128>(1000000000000000000LL) * 1000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 10000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 1000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 10000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 1000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 10000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 1000000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 10000000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 1000000000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 10000000000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000000000000000LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000000000000000LL * 10LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000000000000000LL * 100LL,
|
|
static_cast<int128>(1000000000000000000LL) * 100000000000000000LL * 1000LL};
|
|
return values[scale];
|
|
}
|
|
|
|
/*
|
|
* @Description: fast compare whether the result of arg * getScaleMultiplier(i)
|
|
* is out of int128 bound. getScaleQuotient(i) equals to
|
|
* INT128_MIN / getScaleMultiplier(i)
|
|
* @IN scale: num between 0 and MAXINT128DIGIT
|
|
* @Return: values[scale]
|
|
*/
|
|
inline int128 getScaleQuotient(int scale)
|
|
{
|
|
Assert(scale >= 0 && scale <= MAXINT128DIGIT);
|
|
static const int128 values[] = {INT128_MIN,
|
|
INT128_MIN / getScaleMultiplier(1),
|
|
INT128_MIN / getScaleMultiplier(2),
|
|
INT128_MIN / getScaleMultiplier(3),
|
|
INT128_MIN / getScaleMultiplier(4),
|
|
INT128_MIN / getScaleMultiplier(5),
|
|
INT128_MIN / getScaleMultiplier(6),
|
|
INT128_MIN / getScaleMultiplier(7),
|
|
INT128_MIN / getScaleMultiplier(8),
|
|
INT128_MIN / getScaleMultiplier(9),
|
|
INT128_MIN / getScaleMultiplier(10),
|
|
INT128_MIN / getScaleMultiplier(11),
|
|
INT128_MIN / getScaleMultiplier(12),
|
|
INT128_MIN / getScaleMultiplier(13),
|
|
INT128_MIN / getScaleMultiplier(14),
|
|
INT128_MIN / getScaleMultiplier(15),
|
|
INT128_MIN / getScaleMultiplier(16),
|
|
INT128_MIN / getScaleMultiplier(17),
|
|
INT128_MIN / getScaleMultiplier(18),
|
|
INT128_MIN / getScaleMultiplier(19),
|
|
INT128_MIN / getScaleMultiplier(20),
|
|
INT128_MIN / getScaleMultiplier(21),
|
|
INT128_MIN / getScaleMultiplier(22),
|
|
INT128_MIN / getScaleMultiplier(23),
|
|
INT128_MIN / getScaleMultiplier(24),
|
|
INT128_MIN / getScaleMultiplier(25),
|
|
INT128_MIN / getScaleMultiplier(26),
|
|
INT128_MIN / getScaleMultiplier(27),
|
|
INT128_MIN / getScaleMultiplier(28),
|
|
INT128_MIN / getScaleMultiplier(29),
|
|
INT128_MIN / getScaleMultiplier(30),
|
|
INT128_MIN / getScaleMultiplier(31),
|
|
INT128_MIN / getScaleMultiplier(32),
|
|
INT128_MIN / getScaleMultiplier(33),
|
|
INT128_MIN / getScaleMultiplier(34),
|
|
INT128_MIN / getScaleMultiplier(35),
|
|
INT128_MIN / getScaleMultiplier(36),
|
|
INT128_MIN / getScaleMultiplier(37),
|
|
INT128_MIN / getScaleMultiplier(38)};
|
|
return values[scale];
|
|
}
|
|
|
|
/*
|
|
* big integer common operators, we implement corresponding
|
|
* functions of big integer for higher performance.
|
|
*/
|
|
enum biop {
|
|
BIADD = 0, // +
|
|
BISUB, // -
|
|
BIMUL, // *
|
|
BIDIV, // /
|
|
BIEQ, // =
|
|
BINEQ, // !=
|
|
BILE, // <=
|
|
BILT, // <
|
|
BIGE, // >=
|
|
BIGT, // >
|
|
BICMP // > || == || <
|
|
};
|
|
|
|
/*
|
|
* when adjust scale for two big integer(int64 or int128) data,
|
|
* determine the result whether out of bound.
|
|
*/
|
|
enum BiAdjustScale { BI_AJUST_TRUE = 0, BI_LEFT_OUT_OF_BOUND, BI_RIGHT_OUT_OF_BOUND };
|
|
|
|
/*
|
|
* this struct is used for numeric agg function.
|
|
* use vechashtable::CopyVarP to decrease memory application.
|
|
*/
|
|
struct bictl {
|
|
Datum store_pos;
|
|
MemoryContext context;
|
|
};
|
|
|
|
/*
|
|
* Function to compute two big integer data(int64 or int128);
|
|
* include four operations and comparison operations.
|
|
*/
|
|
typedef Datum (*biopfun)(Numeric larg, Numeric rarg, bictl* ctl);
|
|
|
|
/*
|
|
* three dimensional arrays: BiFunMatrix
|
|
* this array is used for fast locate the corresponding operation
|
|
* functions by operator and type(int64 or int128)
|
|
*/
|
|
extern const biopfun BiFunMatrix[11][2][2];
|
|
|
|
/*
|
|
* three dimensional arrays: BiAggFunMatrix
|
|
* this array is used for fast locate the corresponding agg
|
|
* functions by operator and type(int64 or int128)
|
|
*/
|
|
extern const biopfun BiAggFunMatrix[3][2][2];
|
|
|
|
/* convert big integer data to numeric */
|
|
extern Numeric bitonumeric(Datum arg);
|
|
/* convert int(int1/int2/int4/int8) to big integer type */
|
|
extern Datum int1_numeric_bi(PG_FUNCTION_ARGS);
|
|
extern Datum int2_numeric_bi(PG_FUNCTION_ARGS);
|
|
extern Datum int4_numeric_bi(PG_FUNCTION_ARGS);
|
|
extern Datum int8_numeric_bi(PG_FUNCTION_ARGS);
|
|
/* hash function for big integer(int64/int128/numeric) */
|
|
extern Datum hash_bi(PG_FUNCTION_ARGS);
|
|
/* replace numeric hash function and equal function for VecHashAgg/VecHashJoin Node */
|
|
extern void replace_numeric_hash_to_bi(int numCols, FmgrInfo* hashFunctions);
|
|
/* bi64 and bi128 output function */
|
|
Datum bi64_out(int64 data, int scale);
|
|
Datum bi128_out(int128 data, int scale);
|
|
|
|
Datum Simplebi64div64(Numeric larg, Numeric rarg);
|
|
|
|
void Int128GetVal(bool is_int128, int128* val, Numeric* arg);
|
|
|
|
#endif /* SRC_INCLUDE_UTILS_BIGINTERGER_H_ */
|