⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 numeric.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
		else			res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);	}	PG_RETURN_NUMERIC(res);}Datumnumeric_uplus(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	Numeric		res;	res = (Numeric) palloc(num->varlen);	memcpy(res, num, num->varlen);	PG_RETURN_NUMERIC(res);}/* * numeric_sign() - * * returns -1 if the argument is less than 0, 0 if the argument is equal * to 0, and 1 if the argument is greater than zero. */Datumnumeric_sign(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	Numeric		res;	NumericVar	result;	/*	 * Handle NaN	 */	if (NUMERIC_IS_NAN(num))		PG_RETURN_NUMERIC(make_result(&const_nan));	init_var(&result);	/*	 * The packed format is known to be totally zero digit trimmed always.	 * So we can identify a ZERO by the fact that there are no digits at	 * all.	 */	if (num->varlen == NUMERIC_HDRSZ)		set_var_from_var(&const_zero, &result);	else	{		/*		 * And if there are some, we return a copy of ONE with the sign of		 * our argument		 */		set_var_from_var(&const_one, &result);		result.sign = NUMERIC_SIGN(num);	}	res = make_result(&result);	free_var(&result);	PG_RETURN_NUMERIC(res);}/* * numeric_round() - * *	Round a value to have 'scale' digits after the decimal point. *	We allow negative 'scale', implying rounding before the decimal *	point --- Oracle interprets rounding that way. */Datumnumeric_round(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	int32		scale = PG_GETARG_INT32(1);	Numeric		res;	NumericVar	arg;	/*	 * Handle NaN	 */	if (NUMERIC_IS_NAN(num))		PG_RETURN_NUMERIC(make_result(&const_nan));	/*	 * Limit the scale value to avoid possible overflow in calculations	 */	scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);	scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);	/*	 * Unpack the argument and round it at the proper digit position	 */	init_var(&arg);	set_var_from_num(num, &arg);	round_var(&arg, scale);	/* We don't allow negative output dscale */	if (scale < 0)		arg.dscale = 0;	/*	 * Return the rounded result	 */	res = make_result(&arg);	free_var(&arg);	PG_RETURN_NUMERIC(res);}/* * numeric_trunc() - * *	Truncate a value to have 'scale' digits after the decimal point. *	We allow negative 'scale', implying a truncation before the decimal *	point --- Oracle interprets truncation that way. */Datumnumeric_trunc(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	int32		scale = PG_GETARG_INT32(1);	Numeric		res;	NumericVar	arg;	/*	 * Handle NaN	 */	if (NUMERIC_IS_NAN(num))		PG_RETURN_NUMERIC(make_result(&const_nan));	/*	 * Limit the scale value to avoid possible overflow in calculations	 */	scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);	scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);	/*	 * Unpack the argument and truncate it at the proper digit position	 */	init_var(&arg);	set_var_from_num(num, &arg);	trunc_var(&arg, scale);	/* We don't allow negative output dscale */	if (scale < 0)		arg.dscale = 0;	/*	 * Return the truncated result	 */	res = make_result(&arg);	free_var(&arg);	PG_RETURN_NUMERIC(res);}/* * numeric_ceil() - * *	Return the smallest integer greater than or equal to the argument */Datumnumeric_ceil(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	Numeric		res;	NumericVar	result;	if (NUMERIC_IS_NAN(num))		PG_RETURN_NUMERIC(make_result(&const_nan));	init_var(&result);	set_var_from_num(num, &result);	ceil_var(&result, &result);	res = make_result(&result);	free_var(&result);	PG_RETURN_NUMERIC(res);}/* * numeric_floor() - * *	Return the largest integer equal to or less than the argument */Datumnumeric_floor(PG_FUNCTION_ARGS){	Numeric		num = PG_GETARG_NUMERIC(0);	Numeric		res;	NumericVar	result;	if (NUMERIC_IS_NAN(num))		PG_RETURN_NUMERIC(make_result(&const_nan));	init_var(&result);	set_var_from_num(num, &result);	floor_var(&result, &result);	res = make_result(&result);	free_var(&result);	PG_RETURN_NUMERIC(res);}/* ---------------------------------------------------------------------- * * Comparison functions * * Note: btree indexes need these routines not to leak memory; therefore, * be careful to free working copies of toasted datums.  Most places don't * need to be so careful. * ---------------------------------------------------------------------- */Datumnumeric_cmp(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	int			result;	result = cmp_numerics(num1, num2);	PG_FREE_IF_COPY(num1, 0);	PG_FREE_IF_COPY(num2, 1);	PG_RETURN_INT32(result);}Datumnumeric_eq(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	bool		result;	result = cmp_numerics(num1, num2) == 0;	PG_FREE_IF_COPY(num1, 0);	PG_FREE_IF_COPY(num2, 1);	PG_RETURN_BOOL(result);}Datumnumeric_ne(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	bool		result;	result = cmp_numerics(num1, num2) != 0;	PG_FREE_IF_COPY(num1, 0);	PG_FREE_IF_COPY(num2, 1);	PG_RETURN_BOOL(result);}Datumnumeric_gt(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	bool		result;	result = cmp_numerics(num1, num2) > 0;	PG_FREE_IF_COPY(num1, 0);	PG_FREE_IF_COPY(num2, 1);	PG_RETURN_BOOL(result);}Datumnumeric_ge(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	bool		result;	result = cmp_numerics(num1, num2) >= 0;	PG_FREE_IF_COPY(num1, 0);	PG_FREE_IF_COPY(num2, 1);	PG_RETURN_BOOL(result);}Datumnumeric_lt(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	bool		result;	result = cmp_numerics(num1, num2) < 0;	PG_FREE_IF_COPY(num1, 0);	PG_FREE_IF_COPY(num2, 1);	PG_RETURN_BOOL(result);}Datumnumeric_le(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	bool		result;	result = cmp_numerics(num1, num2) <= 0;	PG_FREE_IF_COPY(num1, 0);	PG_FREE_IF_COPY(num2, 1);	PG_RETURN_BOOL(result);}static intcmp_numerics(Numeric num1, Numeric num2){	int			result;	/*	 * We consider all NANs to be equal and larger than any non-NAN. This	 * is somewhat arbitrary; the important thing is to have a consistent	 * sort order.	 */	if (NUMERIC_IS_NAN(num1))	{		if (NUMERIC_IS_NAN(num2))			result = 0;			/* NAN = NAN */		else			result = 1;			/* NAN > non-NAN */	}	else if (NUMERIC_IS_NAN(num2))	{		result = -1;			/* non-NAN < NAN */	}	else	{		NumericVar	arg1;		NumericVar	arg2;		init_var(&arg1);		init_var(&arg2);		set_var_from_num(num1, &arg1);		set_var_from_num(num2, &arg2);		result = cmp_var(&arg1, &arg2);		free_var(&arg1);		free_var(&arg2);	}	return result;}/* ---------------------------------------------------------------------- * * Basic arithmetic functions * * ---------------------------------------------------------------------- *//* * numeric_add() - * *	Add two numerics */Datumnumeric_add(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	NumericVar	arg1;	NumericVar	arg2;	NumericVar	result;	Numeric		res;	/*	 * Handle NaN	 */	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))		PG_RETURN_NUMERIC(make_result(&const_nan));	/*	 * Unpack the values, let add_var() compute the result and return it.	 */	init_var(&arg1);	init_var(&arg2);	init_var(&result);	set_var_from_num(num1, &arg1);	set_var_from_num(num2, &arg2);	add_var(&arg1, &arg2, &result);	res = make_result(&result);	free_var(&arg1);	free_var(&arg2);	free_var(&result);	PG_RETURN_NUMERIC(res);}/* * numeric_sub() - * *	Subtract one numeric from another */Datumnumeric_sub(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	NumericVar	arg1;	NumericVar	arg2;	NumericVar	result;	Numeric		res;	/*	 * Handle NaN	 */	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))		PG_RETURN_NUMERIC(make_result(&const_nan));	/*	 * Unpack the values, let sub_var() compute the result and return it.	 */	init_var(&arg1);	init_var(&arg2);	init_var(&result);	set_var_from_num(num1, &arg1);	set_var_from_num(num2, &arg2);	sub_var(&arg1, &arg2, &result);	res = make_result(&result);	free_var(&arg1);	free_var(&arg2);	free_var(&result);	PG_RETURN_NUMERIC(res);}/* * numeric_mul() - * *	Calculate the product of two numerics */Datumnumeric_mul(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	NumericVar	arg1;	NumericVar	arg2;	NumericVar	result;	Numeric		res;	/*	 * Handle NaN	 */	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))		PG_RETURN_NUMERIC(make_result(&const_nan));	/*	 * Unpack the values, let mul_var() compute the result and return it.	 * Unlike add_var() and sub_var(), mul_var() will round its result. In	 * the case of numeric_mul(), which is invoked for the * operator on	 * numerics, we request exact representation for the product (rscale =	 * sum(dscale of arg1, dscale of arg2)).	 */	init_var(&arg1);	init_var(&arg2);	init_var(&result);	set_var_from_num(num1, &arg1);	set_var_from_num(num2, &arg2);	mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);	res = make_result(&result);	free_var(&arg1);	free_var(&arg2);	free_var(&result);	PG_RETURN_NUMERIC(res);}/* * numeric_div() - * *	Divide one numeric into another */Datumnumeric_div(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	NumericVar	arg1;	NumericVar	arg2;	NumericVar	result;	Numeric		res;	int			rscale;	/*	 * Handle NaN	 */	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))		PG_RETURN_NUMERIC(make_result(&const_nan));	/*	 * Unpack the arguments	 */	init_var(&arg1);	init_var(&arg2);	init_var(&result);	set_var_from_num(num1, &arg1);	set_var_from_num(num2, &arg2);	/*	 * Select scale for division result	 */	rscale = select_div_scale(&arg1, &arg2);	/*	 * Do the divide and return the result	 */	div_var(&arg1, &arg2, &result, rscale);	res = make_result(&result);	free_var(&arg1);	free_var(&arg2);	free_var(&result);	PG_RETURN_NUMERIC(res);}/* * numeric_mod() - * *	Calculate the modulo of two numerics */Datumnumeric_mod(PG_FUNCTION_ARGS){	Numeric		num1 = PG_GETARG_NUMERIC(0);	Numeric		num2 = PG_GETARG_NUMERIC(1);	Numeric		res;	NumericVar	arg1;	NumericVar	arg2;	NumericVar	result;	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))		PG_RETURN_NUMERIC(make_result(&const_nan));	init_var(&arg1);	init_var(&arg2);	init_var(&result);	set_var_from_num(num1, &arg1);	set_var_from_num(num2, &arg2);	mod_var(&arg1, &arg2, &result);	res = make_result(&result);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -