Upon further review, I've updated the patch. This avoids possible name
conflicts with other functions. See attached.

On Sat, Feb 8, 2025 at 3:24 PM Ed Behn <e...@behn.us> wrote:

> I've created a patch (attached) to implement the changes discussed below.
>
> This change moves the definition of the NumericVar structure to numeric.h.
> Function definitions for functions used to work with NumericVar are also
> moved to the header as are definitions of functions used to convert
> NumericVar to Numeric. (Numeric is used to store numeric and decimal types.)
>
> All of this is so that third-party libraries can access numeric and
> decimal values without having to access the opaque Numeric structure.
>
> There is actually no new code. Code is simply moved from numeric.c to
> numeric.h.
>
> This is a patch against branch master.
>
> This successfully compiles and is tested with regression tests.
>
> Also attached is a code sample that uses the change.
>
> Please provide feedback. I'm planning to submit this for the March
> commitfest.
>
>            -Ed
>
> On Wed, Sep 18, 2024 at 9:50 AM Robert Haas <robertmh...@gmail.com> wrote:
>
>> On Sat, Sep 14, 2024 at 2:10 PM Ed Behn <e...@behn.us> wrote:
>> >     Was there a resolution of this? I'm wondering if it is worth it for
>> me to submit a PR for the next commitfest.
>>
>> Well, it seems like what you want is different than what I want, and
>> what Tom wants is different from both of us. I'd like there to be a
>> way forward here but at the moment I'm not quite sure what it is.
>>
>> --
>> Robert Haas
>> EDB: http://www.enterprisedb.com
>>
>
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 40dcbc7b671..ec5e4b5ee32 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -45,65 +45,11 @@
 
 /* ----------
  * Uncomment the following to enable compilation of dump_numeric()
- * and dump_var() and to get a dump of any result produced by make_result().
+ * and dump_var() and to get a dump of any result produced by numeric_make_result().
  * ----------
 #define NUMERIC_DEBUG
  */
 
-
-/* ----------
- * Local data types
- *
- * Numeric values are represented in a base-NBASE floating point format.
- * Each "digit" ranges from 0 to NBASE-1.  The type NumericDigit is signed
- * and wide enough to store a digit.  We assume that NBASE*NBASE can fit in
- * an int.  Although the purely calculational routines could handle any even
- * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
- * in NBASE a power of ten, so that I/O conversions and decimal rounding
- * are easy.  Also, it's actually more efficient if NBASE is rather less than
- * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
- * postpone processing carries.
- *
- * Values of NBASE other than 10000 are considered of historical interest only
- * and are no longer supported in any sense; no mechanism exists for the client
- * to discover the base, so every client supporting binary mode expects the
- * base-10000 format.  If you plan to change this, also note the numeric
- * abbreviation code, which assumes NBASE=10000.
- * ----------
- */
-
-#if 0
-#define NBASE		10
-#define HALF_NBASE	5
-#define DEC_DIGITS	1			/* decimal digits per NBASE digit */
-#define MUL_GUARD_DIGITS	4	/* these are measured in NBASE digits */
-#define DIV_GUARD_DIGITS	8
-
-typedef signed char NumericDigit;
-#endif
-
-#if 0
-#define NBASE		100
-#define HALF_NBASE	50
-#define DEC_DIGITS	2			/* decimal digits per NBASE digit */
-#define MUL_GUARD_DIGITS	3	/* these are measured in NBASE digits */
-#define DIV_GUARD_DIGITS	6
-
-typedef signed char NumericDigit;
-#endif
-
-#if 1
-#define NBASE		10000
-#define HALF_NBASE	5000
-#define DEC_DIGITS	4			/* decimal digits per NBASE digit */
-#define MUL_GUARD_DIGITS	2	/* these are measured in NBASE digits */
-#define DIV_GUARD_DIGITS	4
-
-typedef int16 NumericDigit;
-#endif
-
-#define NBASE_SQR	(NBASE * NBASE)
-
 /*
  * The Numeric type as stored on disk.
  *
@@ -252,75 +198,6 @@ struct NumericData
 	 | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
 	: ((n)->choice.n_long.n_weight))
 
-/*
- * Maximum weight of a stored Numeric value (based on the use of int16 for the
- * weight in NumericLong).  Note that intermediate values held in NumericVar
- * and NumericSumAccum variables may have much larger weights.
- */
-#define NUMERIC_WEIGHT_MAX			PG_INT16_MAX
-
-/* ----------
- * NumericVar is the format we use for arithmetic.  The digit-array part
- * is the same as the NumericData storage format, but the header is more
- * complex.
- *
- * The value represented by a NumericVar is determined by the sign, weight,
- * ndigits, and digits[] array.  If it is a "special" value (NaN or Inf)
- * then only the sign field matters; ndigits should be zero, and the weight
- * and dscale fields are ignored.
- *
- * Note: the first digit of a NumericVar's value is assumed to be multiplied
- * by NBASE ** weight.  Another way to say it is that there are weight+1
- * digits before the decimal point.  It is possible to have weight < 0.
- *
- * buf points at the physical start of the palloc'd digit buffer for the
- * NumericVar.  digits points at the first digit in actual use (the one
- * with the specified weight).  We normally leave an unused digit or two
- * (preset to zeroes) between buf and digits, so that there is room to store
- * a carry out of the top digit without reallocating space.  We just need to
- * decrement digits (and increment weight) to make room for the carry digit.
- * (There is no such extra space in a numeric value stored in the database,
- * only in a NumericVar in memory.)
- *
- * If buf is NULL then the digit buffer isn't actually palloc'd and should
- * not be freed --- see the constants below for an example.
- *
- * dscale, or display scale, is the nominal precision expressed as number
- * of digits after the decimal point (it must always be >= 0 at present).
- * dscale may be more than the number of physically stored fractional digits,
- * implying that we have suppressed storage of significant trailing zeroes.
- * It should never be less than the number of stored digits, since that would
- * imply hiding digits that are present.  NOTE that dscale is always expressed
- * in *decimal* digits, and so it may correspond to a fractional number of
- * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
- *
- * rscale, or result scale, is the target precision for a computation.
- * Like dscale it is expressed as number of *decimal* digits after the decimal
- * point, and is always >= 0 at present.
- * Note that rscale is not stored in variables --- it's figured on-the-fly
- * from the dscales of the inputs.
- *
- * While we consistently use "weight" to refer to the base-NBASE weight of
- * a numeric value, it is convenient in some scale-related calculations to
- * make use of the base-10 weight (ie, the approximate log10 of the value).
- * To avoid confusion, such a decimal-units weight is called a "dweight".
- *
- * NB: All the variable-level functions are written in a style that makes it
- * possible to give one and the same variable as argument and destination.
- * This is feasible because the digit buffer is separate from the variable.
- * ----------
- */
-typedef struct NumericVar
-{
-	int			ndigits;		/* # of digits in digits[] - can be 0! */
-	int			weight;			/* weight of first digit */
-	int			sign;			/* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
-	int			dscale;			/* display scale */
-	NumericDigit *buf;			/* start of palloc'd space for digits[] */
-	NumericDigit *digits;		/* base-NBASE digits */
-} NumericVar;
-
-
 /* ----------
  * Data for generate_series
  * ----------
@@ -491,8 +368,6 @@ static void dump_var(const char *str, NumericVar *var);
 			 pfree(buf); \
 	} while (0)
 
-#define init_var(v)		memset(v, 0, sizeof(NumericVar))
-
 #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
 	(num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
 #define NUMERIC_NDIGITS(num) \
@@ -502,10 +377,6 @@ static void dump_var(const char *str, NumericVar *var);
 	(weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
 	(weight) >= NUMERIC_SHORT_WEIGHT_MIN)
 
-static void alloc_var(NumericVar *var, int ndigits);
-static void free_var(NumericVar *var);
-static void zero_var(NumericVar *var);
-
 static bool set_var_from_str(const char *str, const char *cp,
 							 NumericVar *dest, const char **endptr,
 							 Node *escontext);
@@ -514,9 +385,6 @@ static bool set_var_from_non_decimal_integer_str(const char *str,
 												 int base, NumericVar *dest,
 												 const char **endptr,
 												 Node *escontext);
-static void set_var_from_num(Numeric num, NumericVar *dest);
-static void init_var_from_num(Numeric num, NumericVar *dest);
-static void set_var_from_var(const NumericVar *value, NumericVar *dest);
 static char *get_str_from_var(const NumericVar *var);
 static char *get_str_from_var_sci(const NumericVar *var, int rscale);
 
@@ -524,8 +392,6 @@ static void numericvar_serialize(StringInfo buf, const NumericVar *var);
 static void numericvar_deserialize(StringInfo buf, NumericVar *var);
 
 static Numeric duplicate_numeric(Numeric num);
-static Numeric make_result(const NumericVar *var);
-static Numeric make_result_opt_error(const NumericVar *var, bool *have_error);
 
 static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
 static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
@@ -687,17 +553,17 @@ numeric_in(PG_FUNCTION_ARGS)
 		 */
 		if (pg_strncasecmp(numstart, "NaN", 3) == 0)
 		{
-			res = make_result(&const_nan);
+			res = numeric_make_result(&const_nan);
 			cp = numstart + 3;
 		}
 		else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
 		{
-			res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
+			res = numeric_make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
 			cp += 8;
 		}
 		else if (pg_strncasecmp(cp, "inf", 3) == 0)
 		{
-			res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
+			res = numeric_make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
 			cp += 3;
 		}
 		else
@@ -787,7 +653,7 @@ numeric_in(PG_FUNCTION_ARGS)
 		if (!apply_typmod(&value, typmod, escontext))
 			PG_RETURN_NULL();
 
-		res = make_result_opt_error(&value, &have_error);
+		res = numeric_make_result_opt_error(&value, &have_error);
 
 		if (have_error)
 			ereturn(escontext, (Datum) 0,
@@ -1130,7 +996,7 @@ numeric_recv(PG_FUNCTION_ARGS)
 	 * extra code (about as much as trunc_var involves), and it might cause
 	 * client compatibility issues.  Be careful not to apply trunc_var to
 	 * special values, as it could do the wrong thing; we don't need it
-	 * anyway, since make_result will ignore all but the sign field.
+	 * anyway, since make_result_numericvar will ignore all but the sign field.
 	 *
 	 * After doing that, be sure to check the typmod restriction.
 	 */
@@ -1141,12 +1007,12 @@ numeric_recv(PG_FUNCTION_ARGS)
 
 		(void) apply_typmod(&value, typmod, NULL);
 
-		res = make_result(&value);
+		res = numeric_make_result(&value);
 	}
 	else
 	{
 		/* apply_typmod_special wants us to make the Numeric first */
-		res = make_result(&value);
+		res = numeric_make_result(&value);
 
 		(void) apply_typmod_special(res, typmod, NULL);
 	}
@@ -1313,7 +1179,7 @@ numeric		(PG_FUNCTION_ARGS)
 
 	set_var_from_num(num, &var);
 	(void) apply_typmod(&var, typmod, NULL);
-	new = make_result(&var);
+	new = numeric_make_result(&var);
 
 	free_var(&var);
 
@@ -1515,16 +1381,16 @@ numeric_sign(PG_FUNCTION_ARGS)
 	 * Handle NaN (infinities can be handled normally)
 	 */
 	if (NUMERIC_IS_NAN(num))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 
 	switch (numeric_sign_internal(num))
 	{
 		case 0:
-			PG_RETURN_NUMERIC(make_result(&const_zero));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 		case 1:
-			PG_RETURN_NUMERIC(make_result(&const_one));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_one));
 		case -1:
-			PG_RETURN_NUMERIC(make_result(&const_minus_one));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_minus_one));
 	}
 
 	Assert(false);
@@ -1579,7 +1445,7 @@ numeric_round(PG_FUNCTION_ARGS)
 	/*
 	 * Return the rounded result
 	 */
-	res = make_result(&arg);
+	res = numeric_make_result(&arg);
 
 	free_var(&arg);
 	PG_RETURN_NUMERIC(res);
@@ -1631,7 +1497,7 @@ numeric_trunc(PG_FUNCTION_ARGS)
 	/*
 	 * Return the truncated result
 	 */
-	res = make_result(&arg);
+	res = numeric_make_result(&arg);
 
 	free_var(&arg);
 	PG_RETURN_NUMERIC(res);
@@ -1659,7 +1525,7 @@ numeric_ceil(PG_FUNCTION_ARGS)
 	init_var_from_num(num, &result);
 	ceil_var(&result, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 	free_var(&result);
 
 	PG_RETURN_NUMERIC(res);
@@ -1687,7 +1553,7 @@ numeric_floor(PG_FUNCTION_ARGS)
 	init_var_from_num(num, &result);
 	floor_var(&result, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 	free_var(&result);
 
 	PG_RETURN_NUMERIC(res);
@@ -1811,7 +1677,7 @@ generate_series_step_numeric(PG_FUNCTION_ARGS)
 		(fctx->step.sign == NUMERIC_NEG &&
 		 cmp_var(&fctx->current, &fctx->stop) >= 0))
 	{
-		Numeric		result = make_result(&fctx->current);
+		Numeric		result = numeric_make_result(&fctx->current);
 
 		/* switch to memory context appropriate for iteration calculation */
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
@@ -2995,26 +2861,26 @@ numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 	{
 		if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-			return make_result(&const_nan);
+			return numeric_make_result(&const_nan);
 		if (NUMERIC_IS_PINF(num1))
 		{
 			if (NUMERIC_IS_NINF(num2))
-				return make_result(&const_nan); /* Inf + -Inf */
+				return numeric_make_result(&const_nan); /* Inf + -Inf */
 			else
-				return make_result(&const_pinf);
+				return numeric_make_result(&const_pinf);
 		}
 		if (NUMERIC_IS_NINF(num1))
 		{
 			if (NUMERIC_IS_PINF(num2))
-				return make_result(&const_nan); /* -Inf + Inf */
+				return numeric_make_result(&const_nan); /* -Inf + Inf */
 			else
-				return make_result(&const_ninf);
+				return numeric_make_result(&const_ninf);
 		}
 		/* by here, num1 must be finite, so num2 is not */
 		if (NUMERIC_IS_PINF(num2))
-			return make_result(&const_pinf);
+			return numeric_make_result(&const_pinf);
 		Assert(NUMERIC_IS_NINF(num2));
-		return make_result(&const_ninf);
+		return numeric_make_result(&const_ninf);
 	}
 
 	/*
@@ -3026,7 +2892,7 @@ numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	init_var(&result);
 	add_var(&arg1, &arg2, &result);
 
-	res = make_result_opt_error(&result, have_error);
+	res = numeric_make_result_opt_error(&result, have_error);
 
 	free_var(&result);
 
@@ -3073,26 +2939,26 @@ numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 	{
 		if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-			return make_result(&const_nan);
+			return numeric_make_result(&const_nan);
 		if (NUMERIC_IS_PINF(num1))
 		{
 			if (NUMERIC_IS_PINF(num2))
-				return make_result(&const_nan); /* Inf - Inf */
+				return numeric_make_result(&const_nan); /* Inf - Inf */
 			else
-				return make_result(&const_pinf);
+				return numeric_make_result(&const_pinf);
 		}
 		if (NUMERIC_IS_NINF(num1))
 		{
 			if (NUMERIC_IS_NINF(num2))
-				return make_result(&const_nan); /* -Inf - -Inf */
+				return numeric_make_result(&const_nan); /* -Inf - -Inf */
 			else
-				return make_result(&const_ninf);
+				return numeric_make_result(&const_ninf);
 		}
 		/* by here, num1 must be finite, so num2 is not */
 		if (NUMERIC_IS_PINF(num2))
-			return make_result(&const_ninf);
+			return numeric_make_result(&const_ninf);
 		Assert(NUMERIC_IS_NINF(num2));
-		return make_result(&const_pinf);
+		return numeric_make_result(&const_pinf);
 	}
 
 	/*
@@ -3104,7 +2970,7 @@ numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	init_var(&result);
 	sub_var(&arg1, &arg2, &result);
 
-	res = make_result_opt_error(&result, have_error);
+	res = numeric_make_result_opt_error(&result, have_error);
 
 	free_var(&result);
 
@@ -3151,17 +3017,17 @@ numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 	{
 		if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-			return make_result(&const_nan);
+			return numeric_make_result(&const_nan);
 		if (NUMERIC_IS_PINF(num1))
 		{
 			switch (numeric_sign_internal(num2))
 			{
 				case 0:
-					return make_result(&const_nan); /* Inf * 0 */
+					return numeric_make_result(&const_nan); /* Inf * 0 */
 				case 1:
-					return make_result(&const_pinf);
+					return numeric_make_result(&const_pinf);
 				case -1:
-					return make_result(&const_ninf);
+					return numeric_make_result(&const_ninf);
 			}
 			Assert(false);
 		}
@@ -3170,11 +3036,11 @@ numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
 			switch (numeric_sign_internal(num2))
 			{
 				case 0:
-					return make_result(&const_nan); /* -Inf * 0 */
+					return numeric_make_result(&const_nan); /* -Inf * 0 */
 				case 1:
-					return make_result(&const_ninf);
+					return numeric_make_result(&const_ninf);
 				case -1:
-					return make_result(&const_pinf);
+					return numeric_make_result(&const_pinf);
 			}
 			Assert(false);
 		}
@@ -3184,11 +3050,11 @@ numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
 			switch (numeric_sign_internal(num1))
 			{
 				case 0:
-					return make_result(&const_nan); /* 0 * Inf */
+					return numeric_make_result(&const_nan); /* 0 * Inf */
 				case 1:
-					return make_result(&const_pinf);
+					return numeric_make_result(&const_pinf);
 				case -1:
-					return make_result(&const_ninf);
+					return numeric_make_result(&const_ninf);
 			}
 			Assert(false);
 		}
@@ -3196,11 +3062,11 @@ numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
 		switch (numeric_sign_internal(num1))
 		{
 			case 0:
-				return make_result(&const_nan); /* 0 * -Inf */
+				return numeric_make_result(&const_nan); /* 0 * -Inf */
 			case 1:
-				return make_result(&const_ninf);
+				return numeric_make_result(&const_ninf);
 			case -1:
-				return make_result(&const_pinf);
+				return numeric_make_result(&const_pinf);
 		}
 		Assert(false);
 	}
@@ -3225,7 +3091,7 @@ numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	if (result.dscale > NUMERIC_DSCALE_MAX)
 		round_var(&result, NUMERIC_DSCALE_MAX);
 
-	res = make_result_opt_error(&result, have_error);
+	res = numeric_make_result_opt_error(&result, have_error);
 
 	free_var(&result);
 
@@ -3276,11 +3142,11 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 	{
 		if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-			return make_result(&const_nan);
+			return numeric_make_result(&const_nan);
 		if (NUMERIC_IS_PINF(num1))
 		{
 			if (NUMERIC_IS_SPECIAL(num2))
-				return make_result(&const_nan); /* Inf / [-]Inf */
+				return numeric_make_result(&const_nan); /* Inf / [-]Inf */
 			switch (numeric_sign_internal(num2))
 			{
 				case 0:
@@ -3294,16 +3160,16 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
 							 errmsg("division by zero")));
 					break;
 				case 1:
-					return make_result(&const_pinf);
+					return numeric_make_result(&const_pinf);
 				case -1:
-					return make_result(&const_ninf);
+					return numeric_make_result(&const_ninf);
 			}
 			Assert(false);
 		}
 		if (NUMERIC_IS_NINF(num1))
 		{
 			if (NUMERIC_IS_SPECIAL(num2))
-				return make_result(&const_nan); /* -Inf / [-]Inf */
+				return numeric_make_result(&const_nan); /* -Inf / [-]Inf */
 			switch (numeric_sign_internal(num2))
 			{
 				case 0:
@@ -3317,9 +3183,9 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
 							 errmsg("division by zero")));
 					break;
 				case 1:
-					return make_result(&const_ninf);
+					return numeric_make_result(&const_ninf);
 				case -1:
-					return make_result(&const_pinf);
+					return numeric_make_result(&const_pinf);
 			}
 			Assert(false);
 		}
@@ -3330,7 +3196,7 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
 		 * otherwise throw an underflow error.  But the numeric type doesn't
 		 * really do underflow, so let's just return zero.
 		 */
-		return make_result(&const_zero);
+		return numeric_make_result(&const_zero);
 	}
 
 	/*
@@ -3360,7 +3226,7 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	 */
 	div_var(&arg1, &arg2, &result, rscale, true, true);
 
-	res = make_result_opt_error(&result, have_error);
+	res = numeric_make_result_opt_error(&result, have_error);
 
 	free_var(&result);
 
@@ -3389,11 +3255,11 @@ numeric_div_trunc(PG_FUNCTION_ARGS)
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 	{
 		if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-			PG_RETURN_NUMERIC(make_result(&const_nan));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 		if (NUMERIC_IS_PINF(num1))
 		{
 			if (NUMERIC_IS_SPECIAL(num2))
-				PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
+				PG_RETURN_NUMERIC(numeric_make_result(&const_nan)); /* Inf / [-]Inf */
 			switch (numeric_sign_internal(num2))
 			{
 				case 0:
@@ -3402,16 +3268,16 @@ numeric_div_trunc(PG_FUNCTION_ARGS)
 							 errmsg("division by zero")));
 					break;
 				case 1:
-					PG_RETURN_NUMERIC(make_result(&const_pinf));
+					PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 				case -1:
-					PG_RETURN_NUMERIC(make_result(&const_ninf));
+					PG_RETURN_NUMERIC(numeric_make_result(&const_ninf));
 			}
 			Assert(false);
 		}
 		if (NUMERIC_IS_NINF(num1))
 		{
 			if (NUMERIC_IS_SPECIAL(num2))
-				PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
+				PG_RETURN_NUMERIC(numeric_make_result(&const_nan)); /* -Inf / [-]Inf */
 			switch (numeric_sign_internal(num2))
 			{
 				case 0:
@@ -3420,9 +3286,9 @@ numeric_div_trunc(PG_FUNCTION_ARGS)
 							 errmsg("division by zero")));
 					break;
 				case 1:
-					PG_RETURN_NUMERIC(make_result(&const_ninf));
+					PG_RETURN_NUMERIC(numeric_make_result(&const_ninf));
 				case -1:
-					PG_RETURN_NUMERIC(make_result(&const_pinf));
+					PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 			}
 			Assert(false);
 		}
@@ -3433,7 +3299,7 @@ numeric_div_trunc(PG_FUNCTION_ARGS)
 		 * otherwise throw an underflow error.  But the numeric type doesn't
 		 * really do underflow, so let's just return zero.
 		 */
-		PG_RETURN_NUMERIC(make_result(&const_zero));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 	}
 
 	/*
@@ -3449,7 +3315,7 @@ numeric_div_trunc(PG_FUNCTION_ARGS)
 	 */
 	div_var(&arg1, &arg2, &result, 0, false, true);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -3501,7 +3367,7 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
 	{
 		if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-			return make_result(&const_nan);
+			return numeric_make_result(&const_nan);
 		if (NUMERIC_IS_INF(num1))
 		{
 			if (numeric_sign_internal(num2) == 0)
@@ -3516,7 +3382,7 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
 						 errmsg("division by zero")));
 			}
 			/* Inf % any nonzero = NaN */
-			return make_result(&const_nan);
+			return numeric_make_result(&const_nan);
 		}
 		/* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
 		return duplicate_numeric(num1);
@@ -3538,7 +3404,7 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
 
 	mod_var(&arg1, &arg2, &result);
 
-	res = make_result_opt_error(&result, NULL);
+	res = numeric_make_result_opt_error(&result, NULL);
 
 	free_var(&result);
 
@@ -3571,7 +3437,7 @@ numeric_inc(PG_FUNCTION_ARGS)
 
 	add_var(&arg, &const_one, &arg);
 
-	res = make_result(&arg);
+	res = numeric_make_result(&arg);
 
 	free_var(&arg);
 
@@ -3650,7 +3516,7 @@ numeric_gcd(PG_FUNCTION_ARGS)
 	 * cases.
 	 */
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 
 	/*
 	 * Unpack the arguments
@@ -3665,7 +3531,7 @@ numeric_gcd(PG_FUNCTION_ARGS)
 	 */
 	gcd_var(&arg1, &arg2, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -3693,7 +3559,7 @@ numeric_lcm(PG_FUNCTION_ARGS)
 	 * cases.
 	 */
 	if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 
 	/*
 	 * Unpack the arguments
@@ -3725,7 +3591,7 @@ numeric_lcm(PG_FUNCTION_ARGS)
 
 	result.dscale = Max(arg1.dscale, arg2.dscale);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -3752,7 +3618,7 @@ numeric_fac(PG_FUNCTION_ARGS)
 				 errmsg("factorial of a negative number is undefined")));
 	if (num <= 1)
 	{
-		res = make_result(&const_one);
+		res = numeric_make_result(&const_one);
 		PG_RETURN_NUMERIC(res);
 	}
 	/* Fail immediately if the result would overflow */
@@ -3776,7 +3642,7 @@ numeric_fac(PG_FUNCTION_ARGS)
 		mul_var(&result, &fact, &result, 0);
 	}
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&fact);
 	free_var(&result);
@@ -3849,7 +3715,7 @@ numeric_sqrt(PG_FUNCTION_ARGS)
 	 */
 	sqrt_var(&arg, &result, rscale);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -3879,7 +3745,7 @@ numeric_exp(PG_FUNCTION_ARGS)
 	{
 		/* Per POSIX, exp(-Inf) is zero */
 		if (NUMERIC_IS_NINF(num))
-			PG_RETURN_NUMERIC(make_result(&const_zero));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 		/* For NAN or PINF, just duplicate the input */
 		PG_RETURN_NUMERIC(duplicate_numeric(num));
 	}
@@ -3916,7 +3782,7 @@ numeric_exp(PG_FUNCTION_ARGS)
 	 */
 	exp_var(&arg, &result, rscale);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -3965,7 +3831,7 @@ numeric_ln(PG_FUNCTION_ARGS)
 
 	ln_var(&arg, &result, rscale);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -3997,7 +3863,7 @@ numeric_log(PG_FUNCTION_ARGS)
 					sign2;
 
 		if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
-			PG_RETURN_NUMERIC(make_result(&const_nan));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 		/* fail on negative inputs including -Inf, as log_var would */
 		sign1 = numeric_sign_internal(num1);
 		sign2 = numeric_sign_internal(num2);
@@ -4014,13 +3880,13 @@ numeric_log(PG_FUNCTION_ARGS)
 		{
 			/* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
 			if (NUMERIC_IS_PINF(num2))
-				PG_RETURN_NUMERIC(make_result(&const_nan));
+				PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 			/* log(Inf, finite-positive) is zero (we don't throw underflow) */
-			PG_RETURN_NUMERIC(make_result(&const_zero));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 		}
 		Assert(NUMERIC_IS_PINF(num2));
 		/* log(finite-positive, Inf) is Inf */
-		PG_RETURN_NUMERIC(make_result(&const_pinf));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 	}
 
 	/*
@@ -4036,7 +3902,7 @@ numeric_log(PG_FUNCTION_ARGS)
 	 */
 	log_var(&arg1, &arg2, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -4077,9 +3943,9 @@ numeric_power(PG_FUNCTION_ARGS)
 			{
 				init_var_from_num(num2, &arg2);
 				if (cmp_var(&arg2, &const_zero) == 0)
-					PG_RETURN_NUMERIC(make_result(&const_one));
+					PG_RETURN_NUMERIC(numeric_make_result(&const_one));
 			}
-			PG_RETURN_NUMERIC(make_result(&const_nan));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 		}
 		if (NUMERIC_IS_NAN(num2))
 		{
@@ -4087,9 +3953,9 @@ numeric_power(PG_FUNCTION_ARGS)
 			{
 				init_var_from_num(num1, &arg1);
 				if (cmp_var(&arg1, &const_one) == 0)
-					PG_RETURN_NUMERIC(make_result(&const_one));
+					PG_RETURN_NUMERIC(numeric_make_result(&const_one));
 			}
-			PG_RETURN_NUMERIC(make_result(&const_nan));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 		}
 		/* At least one input is infinite, but error rules still apply */
 		sign1 = numeric_sign_internal(num1);
@@ -4112,14 +3978,14 @@ numeric_power(PG_FUNCTION_ARGS)
 		{
 			init_var_from_num(num1, &arg1);
 			if (cmp_var(&arg1, &const_one) == 0)
-				PG_RETURN_NUMERIC(make_result(&const_one));
+				PG_RETURN_NUMERIC(numeric_make_result(&const_one));
 		}
 
 		/*
 		 * For any value of x, if y is [-]0, 1.0 shall be returned.
 		 */
 		if (sign2 == 0)
-			PG_RETURN_NUMERIC(make_result(&const_one));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_one));
 
 		/*
 		 * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
@@ -4128,7 +3994,7 @@ numeric_power(PG_FUNCTION_ARGS)
 		 * distinguish these two cases.)
 		 */
 		if (sign1 == 0 && sign2 > 0)
-			PG_RETURN_NUMERIC(make_result(&const_zero));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 
 		/*
 		 * If x is -1, and y is [-]Inf, 1.0 shall be returned.
@@ -4151,14 +4017,14 @@ numeric_power(PG_FUNCTION_ARGS)
 			{
 				init_var_from_num(num1, &arg1);
 				if (cmp_var(&arg1, &const_minus_one) == 0)
-					PG_RETURN_NUMERIC(make_result(&const_one));
+					PG_RETURN_NUMERIC(numeric_make_result(&const_one));
 				arg1.sign = NUMERIC_POS;	/* now arg1 = abs(x) */
 				abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
 			}
 			if (abs_x_gt_one == (sign2 > 0))
-				PG_RETURN_NUMERIC(make_result(&const_pinf));
+				PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 			else
-				PG_RETURN_NUMERIC(make_result(&const_zero));
+				PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 		}
 
 		/*
@@ -4169,9 +4035,9 @@ numeric_power(PG_FUNCTION_ARGS)
 		if (NUMERIC_IS_PINF(num1))
 		{
 			if (sign2 > 0)
-				PG_RETURN_NUMERIC(make_result(&const_pinf));
+				PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 			else
-				PG_RETURN_NUMERIC(make_result(&const_zero));
+				PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 		}
 
 		Assert(NUMERIC_IS_NINF(num1));
@@ -4182,7 +4048,7 @@ numeric_power(PG_FUNCTION_ARGS)
 		 * (Again, we need not distinguish these two cases.)
 		 */
 		if (sign2 < 0)
-			PG_RETURN_NUMERIC(make_result(&const_zero));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_zero));
 
 		/*
 		 * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
@@ -4191,9 +4057,9 @@ numeric_power(PG_FUNCTION_ARGS)
 		init_var_from_num(num2, &arg2);
 		if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
 			(arg2.digits[arg2.ndigits - 1] & 1))
-			PG_RETURN_NUMERIC(make_result(&const_ninf));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_ninf));
 		else
-			PG_RETURN_NUMERIC(make_result(&const_pinf));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 	}
 
 	/*
@@ -4224,7 +4090,7 @@ numeric_power(PG_FUNCTION_ARGS)
 	 */
 	power_var(&arg1, &arg2, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -4333,7 +4199,7 @@ numeric_trim_scale(PG_FUNCTION_ARGS)
 
 	init_var_from_num(num, &result);
 	result.dscale = get_min_scale(&result);
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 	free_var(&result);
 
 	PG_RETURN_NUMERIC(res);
@@ -4382,7 +4248,7 @@ random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
 
 	random_var(state, &rmin_var, &rmax_var, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -4407,7 +4273,7 @@ int64_to_numeric(int64 val)
 
 	int64_to_numericvar(val, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -4496,7 +4362,7 @@ int64_div_fast_to_numeric(int64 val1, int log10val2)
 	result.weight -= w;
 	result.dscale = rscale;
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -4717,14 +4583,14 @@ float8_numeric(PG_FUNCTION_ARGS)
 	const char *endptr;
 
 	if (isnan(val))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 
 	if (isinf(val))
 	{
 		if (val < 0)
-			PG_RETURN_NUMERIC(make_result(&const_ninf));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_ninf));
 		else
-			PG_RETURN_NUMERIC(make_result(&const_pinf));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 	}
 
 	snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
@@ -4734,7 +4600,7 @@ float8_numeric(PG_FUNCTION_ARGS)
 	/* Assume we need not worry about leading/trailing spaces */
 	(void) set_var_from_str(buf, buf, &result, &endptr, NULL);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -4811,14 +4677,14 @@ float4_numeric(PG_FUNCTION_ARGS)
 	const char *endptr;
 
 	if (isnan(val))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 
 	if (isinf(val))
 	{
 		if (val < 0)
-			PG_RETURN_NUMERIC(make_result(&const_ninf));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_ninf));
 		else
-			PG_RETURN_NUMERIC(make_result(&const_pinf));
+			PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 	}
 
 	snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
@@ -4828,7 +4694,7 @@ float4_numeric(PG_FUNCTION_ARGS)
 	/* Assume we need not worry about leading/trailing spaces */
 	(void) set_var_from_str(buf, buf, &result, &endptr, NULL);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -6202,7 +6068,7 @@ numeric_poly_sum(PG_FUNCTION_ARGS)
 
 	int128_to_numericvar(state->sumX, &result);
 
-	res = make_result(&result);
+	res = numeric_make_result(&result);
 
 	free_var(&result);
 
@@ -6232,7 +6098,7 @@ numeric_poly_avg(PG_FUNCTION_ARGS)
 	int128_to_numericvar(state->sumX, &result);
 
 	countd = NumericGetDatum(int64_to_numeric(state->N));
-	sumd = NumericGetDatum(make_result(&result));
+	sumd = NumericGetDatum(numeric_make_result(&result));
 
 	free_var(&result);
 
@@ -6257,21 +6123,21 @@ numeric_avg(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 
 	if (state->NaNcount > 0)	/* there was at least one NaN input */
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 
 	/* adding plus and minus infinities gives NaN */
 	if (state->pInfcount > 0 && state->nInfcount > 0)
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 	if (state->pInfcount > 0)
-		PG_RETURN_NUMERIC(make_result(&const_pinf));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 	if (state->nInfcount > 0)
-		PG_RETURN_NUMERIC(make_result(&const_ninf));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_ninf));
 
 	N_datum = NumericGetDatum(int64_to_numeric(state->N));
 
 	init_var(&sumX_var);
 	accum_sum_final(&state->sumX, &sumX_var);
-	sumX_datum = NumericGetDatum(make_result(&sumX_var));
+	sumX_datum = NumericGetDatum(numeric_make_result(&sumX_var));
 	free_var(&sumX_var);
 
 	PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
@@ -6291,19 +6157,19 @@ numeric_sum(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 
 	if (state->NaNcount > 0)	/* there was at least one NaN input */
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 
 	/* adding plus and minus infinities gives NaN */
 	if (state->pInfcount > 0 && state->nInfcount > 0)
-		PG_RETURN_NUMERIC(make_result(&const_nan));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_nan));
 	if (state->pInfcount > 0)
-		PG_RETURN_NUMERIC(make_result(&const_pinf));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_pinf));
 	if (state->nInfcount > 0)
-		PG_RETURN_NUMERIC(make_result(&const_ninf));
+		PG_RETURN_NUMERIC(numeric_make_result(&const_ninf));
 
 	init_var(&sumX_var);
 	accum_sum_final(&state->sumX, &sumX_var);
-	result = make_result(&sumX_var);
+	result = numeric_make_result(&sumX_var);
 	free_var(&sumX_var);
 
 	PG_RETURN_NUMERIC(result);
@@ -6357,7 +6223,7 @@ numeric_stddev_internal(NumericAggState *state,
 	 * float8 functions, any infinity input produces NaN output.
 	 */
 	if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
-		return make_result(&const_nan);
+		return numeric_make_result(&const_nan);
 
 	/* OK, normal calculation applies */
 	init_var(&vN);
@@ -6381,7 +6247,7 @@ numeric_stddev_internal(NumericAggState *state,
 	if (cmp_var(&vsumX2, &const_zero) <= 0)
 	{
 		/* Watch out for roundoff error producing a negative numerator */
-		res = make_result(&const_zero);
+		res = numeric_make_result(&const_zero);
 	}
 	else
 	{
@@ -6394,7 +6260,7 @@ numeric_stddev_internal(NumericAggState *state,
 		if (!variance)
 			sqrt_var(&vsumX, &vsumX, rscale);	/* stddev */
 
-		res = make_result(&vsumX);
+		res = numeric_make_result(&vsumX);
 	}
 
 	free_var(&vNminus1);
@@ -7067,7 +6933,7 @@ dump_var(const char *str, NumericVar *var)
  *
  *	Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
  */
-static void
+void
 alloc_var(NumericVar *var, int ndigits)
 {
 	digitbuf_free(var->buf);
@@ -7083,7 +6949,7 @@ alloc_var(NumericVar *var, int ndigits)
  *
  *	Return the digit buffer of a variable to the free pool
  */
-static void
+void
 free_var(NumericVar *var)
 {
 	digitbuf_free(var->buf);
@@ -7099,7 +6965,7 @@ free_var(NumericVar *var)
  *	Set a variable to ZERO.
  *	Note: its dscale is not touched.
  */
-static void
+void
 zero_var(NumericVar *var)
 {
 	digitbuf_free(var->buf);
@@ -7221,8 +7087,8 @@ set_var_from_str(const char *str, const char *cp,
 		 * INT_MAX/2 due to the MaxAllocSize limit on string length, so
 		 * constraining the exponent similarly should be enough to prevent
 		 * integer overflow in this function.  If the value is too large to
-		 * fit in storage format, make_result() will complain about it later;
-		 * for consistency use the same ereport errcode/text as make_result().
+		 * fit in storage format, numeric_make_result() will complain about it later;
+		 * for consistency use the same ereport errcode/text as numeric_make_result().
 		 */
 
 		/* exponent sign */
@@ -7534,7 +7400,7 @@ invalid_syntax:
  *
  *	Convert the packed db format into a variable
  */
-static void
+void
 set_var_from_num(Numeric num, NumericVar *dest)
 {
 	int			ndigits;
@@ -7565,7 +7431,7 @@ set_var_from_num(Numeric num, NumericVar *dest)
  *	propagate to the original Numeric! It's OK to use it as the destination
  *	argument of one of the calculational functions, though.
  */
-static void
+void
 init_var_from_num(Numeric num, NumericVar *dest)
 {
 	dest->ndigits = NUMERIC_NDIGITS(num);
@@ -7582,7 +7448,7 @@ init_var_from_num(Numeric num, NumericVar *dest)
  *
  *	Copy one variable into another
  */
-static void
+void
 set_var_from_var(const NumericVar *value, NumericVar *dest)
 {
 	NumericDigit *newbuf;
@@ -7888,7 +7754,7 @@ duplicate_numeric(Numeric num)
 }
 
 /*
- * make_result_opt_error() -
+ * numeric_make_result_opt_error() -
  *
  *	Create the packed db numeric format in palloc()'d memory from
  *	a variable.  This will handle NaN and Infinity cases.
@@ -7896,8 +7762,8 @@ duplicate_numeric(Numeric num)
  *	If "have_error" isn't NULL, on overflow *have_error is set to true and
  *	NULL is returned.  This is helpful when caller needs to handle errors.
  */
-static Numeric
-make_result_opt_error(const NumericVar *var, bool *have_error)
+Numeric
+numeric_make_result_opt_error(const NumericVar *var, bool *have_error)
 {
 	Numeric		result;
 	NumericDigit *digits = var->digits;
@@ -7927,7 +7793,7 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
 		result->choice.n_header = sign;
 		/* the header word is all we need */
 
-		dump_numeric("make_result()", result);
+		dump_numeric("numeric_make_result()", result);
 		return result;
 	}
 
@@ -7995,20 +7861,20 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
 		}
 	}
 
-	dump_numeric("make_result()", result);
+	dump_numeric("numeric_make_result()", result);
 	return result;
 }
 
 
 /*
- * make_result() -
+ * numeric_make_result() -
  *
- *	An interface to make_result_opt_error() without "have_error" argument.
+ *	An interface to numeric_make_result_opt_error() without "have_error" argument.
  */
-static Numeric
-make_result(const NumericVar *var)
+Numeric
+numeric_make_result(const NumericVar *var)
 {
-	return make_result_opt_error(var, NULL);
+	return numeric_make_result_opt_error(var, NULL);
 }
 
 
diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h
index 9e79fc376cb..4a290577abd 100644
--- a/src/include/utils/numeric.h
+++ b/src/include/utils/numeric.h
@@ -42,6 +42,59 @@
 
 #define NUMERIC_MAX_RESULT_SCALE	(NUMERIC_MAX_PRECISION * 2)
 
+/* ----------
+ * Local data types
+ *
+ * Numeric values are represented in a base-NBASE floating point format.
+ * Each "digit" ranges from 0 to NBASE-1.  The type NumericDigit is signed
+ * and wide enough to store a digit.  We assume that NBASE*NBASE can fit in
+ * an int.  Although the purely calculational routines could handle any even
+ * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
+ * in NBASE a power of ten, so that I/O conversions and decimal rounding
+ * are easy.  Also, it's actually more efficient if NBASE is rather less than
+ * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
+ * postpone processing carries.
+ *
+ * Values of NBASE other than 10000 are considered of historical interest only
+ * and are no longer supported in any sense; no mechanism exists for the client
+ * to discover the base, so every client supporting binary mode expects the
+ * base-10000 format.  If you plan to change this, also note the numeric
+ * abbreviation code, which assumes NBASE=10000.
+ * ----------
+ */
+
+#if 0
+#define NBASE		10
+#define HALF_NBASE	5
+#define DEC_DIGITS	1			/* decimal digits per NBASE digit */
+#define MUL_GUARD_DIGITS	4	/* these are measured in NBASE digits */
+#define DIV_GUARD_DIGITS	8
+
+typedef signed char NumericDigit;
+#endif
+
+#if 0
+#define NBASE		100
+#define HALF_NBASE	50
+#define DEC_DIGITS	2			/* decimal digits per NBASE digit */
+#define MUL_GUARD_DIGITS	3	/* these are measured in NBASE digits */
+#define DIV_GUARD_DIGITS	6
+
+typedef signed char NumericDigit;
+#endif
+
+#if 1
+#define NBASE		10000
+#define HALF_NBASE	5000
+#define DEC_DIGITS	4			/* decimal digits per NBASE digit */
+#define MUL_GUARD_DIGITS	2	/* these are measured in NBASE digits */
+#define DIV_GUARD_DIGITS	4
+
+typedef int16 NumericDigit;
+#endif
+
+#define NBASE_SQR	(NBASE * NBASE)
+
 /*
  * For inherently inexact calculations such as division and square root,
  * we try to get at least this many significant digits; the idea is to
@@ -49,6 +102,84 @@
  */
 #define NUMERIC_MIN_SIG_DIGITS		16
 
+/*
+ * sign field of NumericVar
+ */
+
+#define NUMERIC_POS      0x0000
+#define NUMERIC_NEG      0x4000
+#define NUMERIC_NAN      0xC000
+#define NUMERIC_PINF     0xD000
+#define NUMERIC_NINF     0xF000
+
+/*
+ * Maximum weight of a stored Numeric value (based on the use of int16 for the
+ * weight in NumericLong).  Note that intermediate values held in NumericVar
+ * and NumericSumAccum variables may have much larger weights.
+ */
+ #define NUMERIC_WEIGHT_MAX			PG_INT16_MAX
+
+/* ----------
+ * NumericVar is the format we use for arithmetic.  The digit-array part
+ * is the same as the NumericData storage format, but the header is more
+ * complex.
+ *
+ * The value represented by a NumericVar is determined by the sign, weight,
+ * ndigits, and digits[] array.  If it is a "special" value (NaN or Inf)
+ * then only the sign field matters; ndigits should be zero, and the weight
+ * and dscale fields are ignored.
+ *
+ * Note: the first digit of a NumericVar's value is assumed to be multiplied
+ * by NBASE ** weight.  Another way to say it is that there are weight+1
+ * digits before the decimal point.  It is possible to have weight < 0.
+ *
+ * buf points at the physical start of the palloc'd digit buffer for the
+ * NumericVar.  digits points at the first digit in actual use (the one
+ * with the specified weight).  We normally leave an unused digit or two
+ * (preset to zeroes) between buf and digits, so that there is room to store
+ * a carry out of the top digit without reallocating space.  We just need to
+ * decrement digits (and increment weight) to make room for the carry digit.
+ * (There is no such extra space in a numeric value stored in the database,
+ * only in a NumericVar in memory.)
+ *
+ * If buf is NULL then the digit buffer isn't actually palloc'd and should
+ * not be freed --- see the constants below for an example.
+ *
+ * dscale, or display scale, is the nominal precision expressed as number
+ * of digits after the decimal point (it must always be >= 0 at present).
+ * dscale may be more than the number of physically stored fractional digits,
+ * implying that we have suppressed storage of significant trailing zeroes.
+ * It should never be less than the number of stored digits, since that would
+ * imply hiding digits that are present.  NOTE that dscale is always expressed
+ * in *decimal* digits, and so it may correspond to a fractional number of
+ * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
+ *
+ * rscale, or result scale, is the target precision for a computation.
+ * Like dscale it is expressed as number of *decimal* digits after the decimal
+ * point, and is always >= 0 at present.
+ * Note that rscale is not stored in variables --- it's figured on-the-fly
+ * from the dscales of the inputs.
+ *
+ * While we consistently use "weight" to refer to the base-NBASE weight of
+ * a numeric value, it is convenient in some scale-related calculations to
+ * make use of the base-10 weight (ie, the approximate log10 of the value).
+ * To avoid confusion, such a decimal-units weight is called a "dweight".
+ *
+ * NB: All the variable-level functions are written in a style that makes it
+ * possible to give one and the same variable as argument and destination.
+ * This is feasible because the digit buffer is separate from the variable.
+ * ----------
+ */
+typedef struct NumericVar
+{
+	int			ndigits;		/* # of digits in digits[] - can be 0! */
+	int			weight;			/* weight of first digit */
+	int			sign;			/* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
+	int			dscale;			/* display scale */
+	NumericDigit *buf;			/* start of palloc'd space for digits[] */
+	NumericDigit *digits;		/* base-NBASE digits */
+} NumericVar;
+
 /* The actual contents of Numeric are private to numeric.c */
 struct NumericData;
 typedef struct NumericData *Numeric;
@@ -79,9 +210,22 @@ NumericGetDatum(Numeric X)
 #define PG_GETARG_NUMERIC_COPY(n) DatumGetNumericCopy(PG_GETARG_DATUM(n))
 #define PG_RETURN_NUMERIC(x)	  return NumericGetDatum(x)
 
+#define init_var(v)		memset(v, 0, sizeof(NumericVar))
+
 /*
  * Utility functions in numeric.c
  */
+extern void alloc_var(NumericVar *var, int ndigits);
+extern void free_var(NumericVar *var);
+extern void zero_var(NumericVar *var);
+
+extern void set_var_from_num(Numeric num, NumericVar *dest);
+extern void init_var_from_num(Numeric num, NumericVar *dest);
+extern void set_var_from_var(const NumericVar *value, NumericVar *dest);
+
+extern Numeric numeric_make_result(const NumericVar *var);
+extern Numeric numeric_make_result_opt_error(const NumericVar *var, bool *have_error);
+
 extern bool numeric_is_nan(Numeric num);
 extern bool numeric_is_inf(Numeric num);
 extern int32 numeric_maximum_size(int32 typmod);

Reply via email to