1 /* src/interfaces/ecpg/pgtypeslib/numeric.c */
2 
3 #include "postgres_fe.h"
4 #include <ctype.h>
5 #include <float.h>
6 #include <limits.h>
7 
8 #include "extern.h"
9 #include "pgtypes_error.h"
10 
11 #define Max(x, y)				((x) > (y) ? (x) : (y))
12 #define Min(x, y)				((x) < (y) ? (x) : (y))
13 
14 #define init_var(v)				memset(v,0,sizeof(numeric))
15 
16 #define digitbuf_alloc(size) ((NumericDigit *) pgtypes_alloc(size))
17 #define digitbuf_free(buf)		\
18 	   do { \
19 				 if ((buf) != NULL) \
20 						  free(buf); \
21 		  } while (0)
22 
23 #include "pgtypes_numeric.h"
24 
25 #if 0
26 /* ----------
27  * apply_typmod() -
28  *
29  *	Do bounds checking and rounding according to the attributes
30  *	typmod field.
31  * ----------
32  */
33 static int
34 apply_typmod(numeric *var, long typmod)
35 {
36 	int			precision;
37 	int			scale;
38 	int			maxweight;
39 	int			i;
40 
41 	/* Do nothing if we have a default typmod (-1) */
42 	if (typmod < (long) (VARHDRSZ))
43 		return 0;
44 
45 	typmod -= VARHDRSZ;
46 	precision = (typmod >> 16) & 0xffff;
47 	scale = typmod & 0xffff;
48 	maxweight = precision - scale;
49 
50 	/* Round to target scale */
51 	i = scale + var->weight + 1;
52 	if (i >= 0 && var->ndigits > i)
53 	{
54 		int			carry = (var->digits[i] > 4) ? 1 : 0;
55 
56 		var->ndigits = i;
57 
58 		while (carry)
59 		{
60 			carry += var->digits[--i];
61 			var->digits[i] = carry % 10;
62 			carry /= 10;
63 		}
64 
65 		if (i < 0)
66 		{
67 			var->digits--;
68 			var->ndigits++;
69 			var->weight++;
70 		}
71 	}
72 	else
73 		var->ndigits = Max(0, Min(i, var->ndigits));
74 
75 	/*
76 	 * Check for overflow - note we can't do this before rounding, because
77 	 * rounding could raise the weight.  Also note that the var's weight could
78 	 * be inflated by leading zeroes, which will be stripped before storage
79 	 * but perhaps might not have been yet. In any case, we must recognize a
80 	 * true zero, whose weight doesn't mean anything.
81 	 */
82 	if (var->weight >= maxweight)
83 	{
84 		/* Determine true weight; and check for all-zero result */
85 		int			tweight = var->weight;
86 
87 		for (i = 0; i < var->ndigits; i++)
88 		{
89 			if (var->digits[i])
90 				break;
91 			tweight--;
92 		}
93 
94 		if (tweight >= maxweight && i < var->ndigits)
95 		{
96 			errno = PGTYPES_NUM_OVERFLOW;
97 			return -1;
98 		}
99 	}
100 
101 	var->rscale = scale;
102 	var->dscale = scale;
103 	return 0;
104 }
105 #endif
106 
107 /* ----------
108  *	alloc_var() -
109  *
110  *	 Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
111  * ----------
112  */
113 static int
alloc_var(numeric * var,int ndigits)114 alloc_var(numeric *var, int ndigits)
115 {
116 	digitbuf_free(var->buf);
117 	var->buf = digitbuf_alloc(ndigits + 1);
118 	if (var->buf == NULL)
119 		return -1;
120 	var->buf[0] = 0;
121 	var->digits = var->buf + 1;
122 	var->ndigits = ndigits;
123 	return 0;
124 }
125 
126 numeric *
PGTYPESnumeric_new(void)127 PGTYPESnumeric_new(void)
128 {
129 	numeric    *var;
130 
131 	if ((var = (numeric *) pgtypes_alloc(sizeof(numeric))) == NULL)
132 		return NULL;
133 
134 	if (alloc_var(var, 0) < 0)
135 	{
136 		free(var);
137 		return NULL;
138 	}
139 
140 	return var;
141 }
142 
143 decimal *
PGTYPESdecimal_new(void)144 PGTYPESdecimal_new(void)
145 {
146 	decimal    *var;
147 
148 	if ((var = (decimal *) pgtypes_alloc(sizeof(decimal))) == NULL)
149 		return NULL;
150 
151 	memset(var, 0, sizeof(decimal));
152 
153 	return var;
154 }
155 
156 /* ----------
157  * set_var_from_str()
158  *
159  *	Parse a string and put the number into a variable
160  * ----------
161  */
162 static int
set_var_from_str(char * str,char ** ptr,numeric * dest)163 set_var_from_str(char *str, char **ptr, numeric *dest)
164 {
165 	bool		have_dp = false;
166 	int			i = 0;
167 
168 	errno = 0;
169 	*ptr = str;
170 	while (*(*ptr))
171 	{
172 		if (!isspace((unsigned char) *(*ptr)))
173 			break;
174 		(*ptr)++;
175 	}
176 
177 	if (pg_strncasecmp(*ptr, "NaN", 3) == 0)
178 	{
179 		*ptr += 3;
180 		dest->sign = NUMERIC_NAN;
181 
182 		/* Should be nothing left but spaces */
183 		while (*(*ptr))
184 		{
185 			if (!isspace((unsigned char) *(*ptr)))
186 			{
187 				errno = PGTYPES_NUM_BAD_NUMERIC;
188 				return -1;
189 			}
190 			(*ptr)++;
191 		}
192 
193 		return 0;
194 	}
195 
196 	if (alloc_var(dest, strlen((*ptr))) < 0)
197 		return -1;
198 	dest->weight = -1;
199 	dest->dscale = 0;
200 	dest->sign = NUMERIC_POS;
201 
202 	switch (*(*ptr))
203 	{
204 		case '+':
205 			dest->sign = NUMERIC_POS;
206 			(*ptr)++;
207 			break;
208 
209 		case '-':
210 			dest->sign = NUMERIC_NEG;
211 			(*ptr)++;
212 			break;
213 	}
214 
215 	if (*(*ptr) == '.')
216 	{
217 		have_dp = true;
218 		(*ptr)++;
219 	}
220 
221 	if (!isdigit((unsigned char) *(*ptr)))
222 	{
223 		errno = PGTYPES_NUM_BAD_NUMERIC;
224 		return -1;
225 	}
226 
227 	while (*(*ptr))
228 	{
229 		if (isdigit((unsigned char) *(*ptr)))
230 		{
231 			dest->digits[i++] = *(*ptr)++ - '0';
232 			if (!have_dp)
233 				dest->weight++;
234 			else
235 				dest->dscale++;
236 		}
237 		else if (*(*ptr) == '.')
238 		{
239 			if (have_dp)
240 			{
241 				errno = PGTYPES_NUM_BAD_NUMERIC;
242 				return -1;
243 			}
244 			have_dp = true;
245 			(*ptr)++;
246 		}
247 		else
248 			break;
249 	}
250 	dest->ndigits = i;
251 
252 	/* Handle exponent, if any */
253 	if (*(*ptr) == 'e' || *(*ptr) == 'E')
254 	{
255 		long		exponent;
256 		char	   *endptr;
257 
258 		(*ptr)++;
259 		exponent = strtol(*ptr, &endptr, 10);
260 		if (endptr == (*ptr))
261 		{
262 			errno = PGTYPES_NUM_BAD_NUMERIC;
263 			return -1;
264 		}
265 		(*ptr) = endptr;
266 		if (exponent >= INT_MAX / 2 || exponent <= -(INT_MAX / 2))
267 		{
268 			errno = PGTYPES_NUM_BAD_NUMERIC;
269 			return -1;
270 		}
271 		dest->weight += (int) exponent;
272 		dest->dscale -= (int) exponent;
273 		if (dest->dscale < 0)
274 			dest->dscale = 0;
275 	}
276 
277 	/* Should be nothing left but spaces */
278 	while (*(*ptr))
279 	{
280 		if (!isspace((unsigned char) *(*ptr)))
281 		{
282 			errno = PGTYPES_NUM_BAD_NUMERIC;
283 			return -1;
284 		}
285 		(*ptr)++;
286 	}
287 
288 	/* Strip any leading zeroes */
289 	while (dest->ndigits > 0 && *(dest->digits) == 0)
290 	{
291 		(dest->digits)++;
292 		(dest->weight)--;
293 		(dest->ndigits)--;
294 	}
295 	if (dest->ndigits == 0)
296 		dest->weight = 0;
297 
298 	dest->rscale = dest->dscale;
299 	return 0;
300 }
301 
302 
303 /* ----------
304  * get_str_from_var() -
305  *
306  *	Convert a var to text representation (guts of numeric_out).
307  *	CAUTION: var's contents may be modified by rounding!
308  * ----------
309  */
310 static char *
get_str_from_var(numeric * var,int dscale)311 get_str_from_var(numeric *var, int dscale)
312 {
313 	char	   *str;
314 	char	   *cp;
315 	int			i;
316 	int			d;
317 
318 	if (var->sign == NUMERIC_NAN)
319 	{
320 		str = (char *) pgtypes_alloc(4);
321 		if (str == NULL)
322 			return NULL;
323 		sprintf(str, "NaN");
324 		return str;
325 	}
326 
327 	/*
328 	 * Check if we must round up before printing the value and do so.
329 	 */
330 	i = dscale + var->weight + 1;
331 	if (i >= 0 && var->ndigits > i)
332 	{
333 		int			carry = (var->digits[i] > 4) ? 1 : 0;
334 
335 		var->ndigits = i;
336 
337 		while (carry)
338 		{
339 			carry += var->digits[--i];
340 			var->digits[i] = carry % 10;
341 			carry /= 10;
342 		}
343 
344 		if (i < 0)
345 		{
346 			var->digits--;
347 			var->ndigits++;
348 			var->weight++;
349 		}
350 	}
351 	else
352 		var->ndigits = Max(0, Min(i, var->ndigits));
353 
354 	/*
355 	 * Allocate space for the result
356 	 */
357 	if ((str = (char *) pgtypes_alloc(Max(0, dscale) + Max(0, var->weight) + 4)) == NULL)
358 		return NULL;
359 	cp = str;
360 
361 	/*
362 	 * Output a dash for negative values
363 	 */
364 	if (var->sign == NUMERIC_NEG)
365 		*cp++ = '-';
366 
367 	/*
368 	 * Output all digits before the decimal point
369 	 */
370 	i = Max(var->weight, 0);
371 	d = 0;
372 
373 	while (i >= 0)
374 	{
375 		if (i <= var->weight && d < var->ndigits)
376 			*cp++ = var->digits[d++] + '0';
377 		else
378 			*cp++ = '0';
379 		i--;
380 	}
381 
382 	/*
383 	 * If requested, output a decimal point and all the digits that follow it.
384 	 */
385 	if (dscale > 0)
386 	{
387 		*cp++ = '.';
388 		while (i >= -dscale)
389 		{
390 			if (i <= var->weight && d < var->ndigits)
391 				*cp++ = var->digits[d++] + '0';
392 			else
393 				*cp++ = '0';
394 			i--;
395 		}
396 	}
397 
398 	/*
399 	 * terminate the string and return it
400 	 */
401 	*cp = '\0';
402 	return str;
403 }
404 
405 numeric *
PGTYPESnumeric_from_asc(char * str,char ** endptr)406 PGTYPESnumeric_from_asc(char *str, char **endptr)
407 {
408 	numeric    *value = (numeric *) pgtypes_alloc(sizeof(numeric));
409 	int			ret;
410 
411 	char	   *realptr;
412 	char	  **ptr = (endptr != NULL) ? endptr : &realptr;
413 
414 	if (!value)
415 		return NULL;
416 
417 	ret = set_var_from_str(str, ptr, value);
418 	if (ret)
419 	{
420 		PGTYPESnumeric_free(value);
421 		return NULL;
422 	}
423 
424 	return value;
425 }
426 
427 char *
PGTYPESnumeric_to_asc(numeric * num,int dscale)428 PGTYPESnumeric_to_asc(numeric *num, int dscale)
429 {
430 	numeric    *numcopy = PGTYPESnumeric_new();
431 	char	   *s;
432 
433 	if (numcopy == NULL)
434 		return NULL;
435 
436 	if (PGTYPESnumeric_copy(num, numcopy) < 0)
437 	{
438 		PGTYPESnumeric_free(numcopy);
439 		return NULL;
440 	}
441 
442 	if (dscale < 0)
443 		dscale = num->dscale;
444 
445 	/* get_str_from_var may change its argument */
446 	s = get_str_from_var(numcopy, dscale);
447 	PGTYPESnumeric_free(numcopy);
448 	return s;
449 }
450 
451 /* ----------
452  * zero_var() -
453  *
454  *	Set a variable to ZERO.
455  *	Note: rscale and dscale are not touched.
456  * ----------
457  */
458 static void
zero_var(numeric * var)459 zero_var(numeric *var)
460 {
461 	digitbuf_free(var->buf);
462 	var->buf = NULL;
463 	var->digits = NULL;
464 	var->ndigits = 0;
465 	var->weight = 0;			/* by convention; doesn't really matter */
466 	var->sign = NUMERIC_POS;	/* anything but NAN... */
467 }
468 
469 void
PGTYPESnumeric_free(numeric * var)470 PGTYPESnumeric_free(numeric *var)
471 {
472 	digitbuf_free(var->buf);
473 	free(var);
474 }
475 
476 void
PGTYPESdecimal_free(decimal * var)477 PGTYPESdecimal_free(decimal *var)
478 {
479 	free(var);
480 }
481 
482 /* ----------
483  * cmp_abs() -
484  *
485  *	Compare the absolute values of var1 and var2
486  *	Returns:	-1 for ABS(var1) < ABS(var2)
487  *				0  for ABS(var1) == ABS(var2)
488  *				1  for ABS(var1) > ABS(var2)
489  * ----------
490  */
491 static int
cmp_abs(numeric * var1,numeric * var2)492 cmp_abs(numeric *var1, numeric *var2)
493 {
494 	int			i1 = 0;
495 	int			i2 = 0;
496 	int			w1 = var1->weight;
497 	int			w2 = var2->weight;
498 	int			stat;
499 
500 	while (w1 > w2 && i1 < var1->ndigits)
501 	{
502 		if (var1->digits[i1++] != 0)
503 			return 1;
504 		w1--;
505 	}
506 	while (w2 > w1 && i2 < var2->ndigits)
507 	{
508 		if (var2->digits[i2++] != 0)
509 			return -1;
510 		w2--;
511 	}
512 
513 	if (w1 == w2)
514 	{
515 		while (i1 < var1->ndigits && i2 < var2->ndigits)
516 		{
517 			stat = var1->digits[i1++] - var2->digits[i2++];
518 			if (stat)
519 			{
520 				if (stat > 0)
521 					return 1;
522 				return -1;
523 			}
524 		}
525 	}
526 
527 	while (i1 < var1->ndigits)
528 	{
529 		if (var1->digits[i1++] != 0)
530 			return 1;
531 	}
532 	while (i2 < var2->ndigits)
533 	{
534 		if (var2->digits[i2++] != 0)
535 			return -1;
536 	}
537 
538 	return 0;
539 }
540 
541 
542 /* ----------
543  * add_abs() -
544  *
545  *	Add the absolute values of two variables into result.
546  *	result might point to one of the operands without danger.
547  * ----------
548  */
549 static int
add_abs(numeric * var1,numeric * var2,numeric * result)550 add_abs(numeric *var1, numeric *var2, numeric *result)
551 {
552 	NumericDigit *res_buf;
553 	NumericDigit *res_digits;
554 	int			res_ndigits;
555 	int			res_weight;
556 	int			res_rscale;
557 	int			res_dscale;
558 	int			i,
559 				i1,
560 				i2;
561 	int			carry = 0;
562 
563 	/* copy these values into local vars for speed in inner loop */
564 	int			var1ndigits = var1->ndigits;
565 	int			var2ndigits = var2->ndigits;
566 	NumericDigit *var1digits = var1->digits;
567 	NumericDigit *var2digits = var2->digits;
568 
569 	res_weight = Max(var1->weight, var2->weight) + 1;
570 	res_rscale = Max(var1->rscale, var2->rscale);
571 	res_dscale = Max(var1->dscale, var2->dscale);
572 	res_ndigits = res_rscale + res_weight + 1;
573 	if (res_ndigits <= 0)
574 		res_ndigits = 1;
575 
576 	if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
577 		return -1;
578 	res_digits = res_buf;
579 
580 	i1 = res_rscale + var1->weight + 1;
581 	i2 = res_rscale + var2->weight + 1;
582 	for (i = res_ndigits - 1; i >= 0; i--)
583 	{
584 		i1--;
585 		i2--;
586 		if (i1 >= 0 && i1 < var1ndigits)
587 			carry += var1digits[i1];
588 		if (i2 >= 0 && i2 < var2ndigits)
589 			carry += var2digits[i2];
590 
591 		if (carry >= 10)
592 		{
593 			res_digits[i] = carry - 10;
594 			carry = 1;
595 		}
596 		else
597 		{
598 			res_digits[i] = carry;
599 			carry = 0;
600 		}
601 	}
602 
603 	while (res_ndigits > 0 && *res_digits == 0)
604 	{
605 		res_digits++;
606 		res_weight--;
607 		res_ndigits--;
608 	}
609 	while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
610 		res_ndigits--;
611 
612 	if (res_ndigits == 0)
613 		res_weight = 0;
614 
615 	digitbuf_free(result->buf);
616 	result->ndigits = res_ndigits;
617 	result->buf = res_buf;
618 	result->digits = res_digits;
619 	result->weight = res_weight;
620 	result->rscale = res_rscale;
621 	result->dscale = res_dscale;
622 
623 	return 0;
624 }
625 
626 
627 /* ----------
628  * sub_abs() -
629  *
630  *	Subtract the absolute value of var2 from the absolute value of var1
631  *	and store in result. result might point to one of the operands
632  *	without danger.
633  *
634  *	ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
635  * ----------
636  */
637 static int
sub_abs(numeric * var1,numeric * var2,numeric * result)638 sub_abs(numeric *var1, numeric *var2, numeric *result)
639 {
640 	NumericDigit *res_buf;
641 	NumericDigit *res_digits;
642 	int			res_ndigits;
643 	int			res_weight;
644 	int			res_rscale;
645 	int			res_dscale;
646 	int			i,
647 				i1,
648 				i2;
649 	int			borrow = 0;
650 
651 	/* copy these values into local vars for speed in inner loop */
652 	int			var1ndigits = var1->ndigits;
653 	int			var2ndigits = var2->ndigits;
654 	NumericDigit *var1digits = var1->digits;
655 	NumericDigit *var2digits = var2->digits;
656 
657 	res_weight = var1->weight;
658 	res_rscale = Max(var1->rscale, var2->rscale);
659 	res_dscale = Max(var1->dscale, var2->dscale);
660 	res_ndigits = res_rscale + res_weight + 1;
661 	if (res_ndigits <= 0)
662 		res_ndigits = 1;
663 
664 	if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
665 		return -1;
666 	res_digits = res_buf;
667 
668 	i1 = res_rscale + var1->weight + 1;
669 	i2 = res_rscale + var2->weight + 1;
670 	for (i = res_ndigits - 1; i >= 0; i--)
671 	{
672 		i1--;
673 		i2--;
674 		if (i1 >= 0 && i1 < var1ndigits)
675 			borrow += var1digits[i1];
676 		if (i2 >= 0 && i2 < var2ndigits)
677 			borrow -= var2digits[i2];
678 
679 		if (borrow < 0)
680 		{
681 			res_digits[i] = borrow + 10;
682 			borrow = -1;
683 		}
684 		else
685 		{
686 			res_digits[i] = borrow;
687 			borrow = 0;
688 		}
689 	}
690 
691 	while (res_ndigits > 0 && *res_digits == 0)
692 	{
693 		res_digits++;
694 		res_weight--;
695 		res_ndigits--;
696 	}
697 	while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
698 		res_ndigits--;
699 
700 	if (res_ndigits == 0)
701 		res_weight = 0;
702 
703 	digitbuf_free(result->buf);
704 	result->ndigits = res_ndigits;
705 	result->buf = res_buf;
706 	result->digits = res_digits;
707 	result->weight = res_weight;
708 	result->rscale = res_rscale;
709 	result->dscale = res_dscale;
710 
711 	return 0;
712 }
713 
714 /* ----------
715  * add_var() -
716  *
717  *	Full version of add functionality on variable level (handling signs).
718  *	result might point to one of the operands too without danger.
719  * ----------
720  */
721 int
PGTYPESnumeric_add(numeric * var1,numeric * var2,numeric * result)722 PGTYPESnumeric_add(numeric *var1, numeric *var2, numeric *result)
723 {
724 	/*
725 	 * Decide on the signs of the two variables what to do
726 	 */
727 	if (var1->sign == NUMERIC_POS)
728 	{
729 		if (var2->sign == NUMERIC_POS)
730 		{
731 			/*
732 			 * Both are positive result = +(ABS(var1) + ABS(var2))
733 			 */
734 			if (add_abs(var1, var2, result) != 0)
735 				return -1;
736 			result->sign = NUMERIC_POS;
737 		}
738 		else
739 		{
740 			/*
741 			 * var1 is positive, var2 is negative Must compare absolute values
742 			 */
743 			switch (cmp_abs(var1, var2))
744 			{
745 				case 0:
746 					/* ----------
747 					 * ABS(var1) == ABS(var2)
748 					 * result = ZERO
749 					 * ----------
750 					 */
751 					zero_var(result);
752 					result->rscale = Max(var1->rscale, var2->rscale);
753 					result->dscale = Max(var1->dscale, var2->dscale);
754 					break;
755 
756 				case 1:
757 					/* ----------
758 					 * ABS(var1) > ABS(var2)
759 					 * result = +(ABS(var1) - ABS(var2))
760 					 * ----------
761 					 */
762 					if (sub_abs(var1, var2, result) != 0)
763 						return -1;
764 					result->sign = NUMERIC_POS;
765 					break;
766 
767 				case -1:
768 					/* ----------
769 					 * ABS(var1) < ABS(var2)
770 					 * result = -(ABS(var2) - ABS(var1))
771 					 * ----------
772 					 */
773 					if (sub_abs(var2, var1, result) != 0)
774 						return -1;
775 					result->sign = NUMERIC_NEG;
776 					break;
777 			}
778 		}
779 	}
780 	else
781 	{
782 		if (var2->sign == NUMERIC_POS)
783 		{
784 			/* ----------
785 			 * var1 is negative, var2 is positive
786 			 * Must compare absolute values
787 			 * ----------
788 			 */
789 			switch (cmp_abs(var1, var2))
790 			{
791 				case 0:
792 					/* ----------
793 					 * ABS(var1) == ABS(var2)
794 					 * result = ZERO
795 					 * ----------
796 					 */
797 					zero_var(result);
798 					result->rscale = Max(var1->rscale, var2->rscale);
799 					result->dscale = Max(var1->dscale, var2->dscale);
800 					break;
801 
802 				case 1:
803 					/* ----------
804 					 * ABS(var1) > ABS(var2)
805 					 * result = -(ABS(var1) - ABS(var2))
806 					 * ----------
807 					 */
808 					if (sub_abs(var1, var2, result) != 0)
809 						return -1;
810 					result->sign = NUMERIC_NEG;
811 					break;
812 
813 				case -1:
814 					/* ----------
815 					 * ABS(var1) < ABS(var2)
816 					 * result = +(ABS(var2) - ABS(var1))
817 					 * ----------
818 					 */
819 					if (sub_abs(var2, var1, result) != 0)
820 						return -1;
821 					result->sign = NUMERIC_POS;
822 					break;
823 			}
824 		}
825 		else
826 		{
827 			/* ----------
828 			 * Both are negative
829 			 * result = -(ABS(var1) + ABS(var2))
830 			 * ----------
831 			 */
832 			if (add_abs(var1, var2, result) != 0)
833 				return -1;
834 			result->sign = NUMERIC_NEG;
835 		}
836 	}
837 
838 	return 0;
839 }
840 
841 
842 /* ----------
843  * sub_var() -
844  *
845  *	Full version of sub functionality on variable level (handling signs).
846  *	result might point to one of the operands too without danger.
847  * ----------
848  */
849 int
PGTYPESnumeric_sub(numeric * var1,numeric * var2,numeric * result)850 PGTYPESnumeric_sub(numeric *var1, numeric *var2, numeric *result)
851 {
852 	/*
853 	 * Decide on the signs of the two variables what to do
854 	 */
855 	if (var1->sign == NUMERIC_POS)
856 	{
857 		if (var2->sign == NUMERIC_NEG)
858 		{
859 			/* ----------
860 			 * var1 is positive, var2 is negative
861 			 * result = +(ABS(var1) + ABS(var2))
862 			 * ----------
863 			 */
864 			if (add_abs(var1, var2, result) != 0)
865 				return -1;
866 			result->sign = NUMERIC_POS;
867 		}
868 		else
869 		{
870 			/* ----------
871 			 * Both are positive
872 			 * Must compare absolute values
873 			 * ----------
874 			 */
875 			switch (cmp_abs(var1, var2))
876 			{
877 				case 0:
878 					/* ----------
879 					 * ABS(var1) == ABS(var2)
880 					 * result = ZERO
881 					 * ----------
882 					 */
883 					zero_var(result);
884 					result->rscale = Max(var1->rscale, var2->rscale);
885 					result->dscale = Max(var1->dscale, var2->dscale);
886 					break;
887 
888 				case 1:
889 					/* ----------
890 					 * ABS(var1) > ABS(var2)
891 					 * result = +(ABS(var1) - ABS(var2))
892 					 * ----------
893 					 */
894 					if (sub_abs(var1, var2, result) != 0)
895 						return -1;
896 					result->sign = NUMERIC_POS;
897 					break;
898 
899 				case -1:
900 					/* ----------
901 					 * ABS(var1) < ABS(var2)
902 					 * result = -(ABS(var2) - ABS(var1))
903 					 * ----------
904 					 */
905 					if (sub_abs(var2, var1, result) != 0)
906 						return -1;
907 					result->sign = NUMERIC_NEG;
908 					break;
909 			}
910 		}
911 	}
912 	else
913 	{
914 		if (var2->sign == NUMERIC_NEG)
915 		{
916 			/* ----------
917 			 * Both are negative
918 			 * Must compare absolute values
919 			 * ----------
920 			 */
921 			switch (cmp_abs(var1, var2))
922 			{
923 				case 0:
924 					/* ----------
925 					 * ABS(var1) == ABS(var2)
926 					 * result = ZERO
927 					 * ----------
928 					 */
929 					zero_var(result);
930 					result->rscale = Max(var1->rscale, var2->rscale);
931 					result->dscale = Max(var1->dscale, var2->dscale);
932 					break;
933 
934 				case 1:
935 					/* ----------
936 					 * ABS(var1) > ABS(var2)
937 					 * result = -(ABS(var1) - ABS(var2))
938 					 * ----------
939 					 */
940 					if (sub_abs(var1, var2, result) != 0)
941 						return -1;
942 					result->sign = NUMERIC_NEG;
943 					break;
944 
945 				case -1:
946 					/* ----------
947 					 * ABS(var1) < ABS(var2)
948 					 * result = +(ABS(var2) - ABS(var1))
949 					 * ----------
950 					 */
951 					if (sub_abs(var2, var1, result) != 0)
952 						return -1;
953 					result->sign = NUMERIC_POS;
954 					break;
955 			}
956 		}
957 		else
958 		{
959 			/* ----------
960 			 * var1 is negative, var2 is positive
961 			 * result = -(ABS(var1) + ABS(var2))
962 			 * ----------
963 			 */
964 			if (add_abs(var1, var2, result) != 0)
965 				return -1;
966 			result->sign = NUMERIC_NEG;
967 		}
968 	}
969 
970 	return 0;
971 }
972 
973 /* ----------
974  * mul_var() -
975  *
976  *	Multiplication on variable level. Product of var1 * var2 is stored
977  *	in result.  Accuracy of result is determined by global_rscale.
978  * ----------
979  */
980 int
PGTYPESnumeric_mul(numeric * var1,numeric * var2,numeric * result)981 PGTYPESnumeric_mul(numeric *var1, numeric *var2, numeric *result)
982 {
983 	NumericDigit *res_buf;
984 	NumericDigit *res_digits;
985 	int			res_ndigits;
986 	int			res_weight;
987 	int			res_sign;
988 	int			i,
989 				ri,
990 				i1,
991 				i2;
992 	long		sum = 0;
993 	int			global_rscale = var1->rscale + var2->rscale;
994 
995 	res_weight = var1->weight + var2->weight + 2;
996 	res_ndigits = var1->ndigits + var2->ndigits + 1;
997 	if (var1->sign == var2->sign)
998 		res_sign = NUMERIC_POS;
999 	else
1000 		res_sign = NUMERIC_NEG;
1001 
1002 	if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
1003 		return -1;
1004 	res_digits = res_buf;
1005 	memset(res_digits, 0, res_ndigits);
1006 
1007 	ri = res_ndigits;
1008 	for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
1009 	{
1010 		sum = 0;
1011 		i = --ri;
1012 
1013 		for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
1014 		{
1015 			sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
1016 			res_digits[i--] = sum % 10;
1017 			sum /= 10;
1018 		}
1019 		res_digits[i] = sum;
1020 	}
1021 
1022 	i = res_weight + global_rscale + 2;
1023 	if (i >= 0 && i < res_ndigits)
1024 	{
1025 		sum = (res_digits[i] > 4) ? 1 : 0;
1026 		res_ndigits = i;
1027 		i--;
1028 		while (sum)
1029 		{
1030 			sum += res_digits[i];
1031 			res_digits[i--] = sum % 10;
1032 			sum /= 10;
1033 		}
1034 	}
1035 
1036 	while (res_ndigits > 0 && *res_digits == 0)
1037 	{
1038 		res_digits++;
1039 		res_weight--;
1040 		res_ndigits--;
1041 	}
1042 	while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
1043 		res_ndigits--;
1044 
1045 	if (res_ndigits == 0)
1046 	{
1047 		res_sign = NUMERIC_POS;
1048 		res_weight = 0;
1049 	}
1050 
1051 	digitbuf_free(result->buf);
1052 	result->buf = res_buf;
1053 	result->digits = res_digits;
1054 	result->ndigits = res_ndigits;
1055 	result->weight = res_weight;
1056 	result->rscale = global_rscale;
1057 	result->sign = res_sign;
1058 	result->dscale = var1->dscale + var2->dscale;
1059 
1060 	return 0;
1061 }
1062 
1063 /*
1064  * Default scale selection for division
1065  *
1066  * Returns the appropriate display scale for the division result,
1067  * and sets global_rscale to the result scale to use during div_var.
1068  *
1069  * Note that this must be called before div_var.
1070  */
1071 static int
select_div_scale(numeric * var1,numeric * var2,int * rscale)1072 select_div_scale(numeric *var1, numeric *var2, int *rscale)
1073 {
1074 	int			weight1,
1075 				weight2,
1076 				qweight,
1077 				i;
1078 	NumericDigit firstdigit1,
1079 				firstdigit2;
1080 	int			res_dscale;
1081 
1082 	/*
1083 	 * The result scale of a division isn't specified in any SQL standard. For
1084 	 * PostgreSQL we select a display scale that will give at least
1085 	 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
1086 	 * result no less accurate than float8; but use a scale not less than
1087 	 * either input's display scale.
1088 	 */
1089 
1090 	/* Get the actual (normalized) weight and first digit of each input */
1091 
1092 	weight1 = 0;				/* values to use if var1 is zero */
1093 	firstdigit1 = 0;
1094 	for (i = 0; i < var1->ndigits; i++)
1095 	{
1096 		firstdigit1 = var1->digits[i];
1097 		if (firstdigit1 != 0)
1098 		{
1099 			weight1 = var1->weight - i;
1100 			break;
1101 		}
1102 	}
1103 
1104 	weight2 = 0;				/* values to use if var2 is zero */
1105 	firstdigit2 = 0;
1106 	for (i = 0; i < var2->ndigits; i++)
1107 	{
1108 		firstdigit2 = var2->digits[i];
1109 		if (firstdigit2 != 0)
1110 		{
1111 			weight2 = var2->weight - i;
1112 			break;
1113 		}
1114 	}
1115 
1116 	/*
1117 	 * Estimate weight of quotient.  If the two first digits are equal, we
1118 	 * can't be sure, but assume that var1 is less than var2.
1119 	 */
1120 	qweight = weight1 - weight2;
1121 	if (firstdigit1 <= firstdigit2)
1122 		qweight--;
1123 
1124 	/* Select display scale */
1125 	res_dscale = NUMERIC_MIN_SIG_DIGITS - qweight;
1126 	res_dscale = Max(res_dscale, var1->dscale);
1127 	res_dscale = Max(res_dscale, var2->dscale);
1128 	res_dscale = Max(res_dscale, NUMERIC_MIN_DISPLAY_SCALE);
1129 	res_dscale = Min(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1130 
1131 	/* Select result scale */
1132 	*rscale = res_dscale + 4;
1133 
1134 	return res_dscale;
1135 }
1136 
1137 int
PGTYPESnumeric_div(numeric * var1,numeric * var2,numeric * result)1138 PGTYPESnumeric_div(numeric *var1, numeric *var2, numeric *result)
1139 {
1140 	NumericDigit *res_digits;
1141 	int			res_ndigits;
1142 	int			res_sign;
1143 	int			res_weight;
1144 	numeric		dividend;
1145 	numeric		divisor[10];
1146 	int			ndigits_tmp;
1147 	int			weight_tmp;
1148 	int			rscale_tmp;
1149 	int			ri;
1150 	int			i;
1151 	long		guess;
1152 	long		first_have;
1153 	long		first_div;
1154 	int			first_nextdigit;
1155 	int			stat = 0;
1156 	int			rscale;
1157 	int			res_dscale = select_div_scale(var1, var2, &rscale);
1158 	int			err = -1;
1159 	NumericDigit *tmp_buf;
1160 
1161 	/*
1162 	 * First of all division by zero check
1163 	 */
1164 	ndigits_tmp = var2->ndigits + 1;
1165 	if (ndigits_tmp == 1)
1166 	{
1167 		errno = PGTYPES_NUM_DIVIDE_ZERO;
1168 		return -1;
1169 	}
1170 
1171 	/*
1172 	 * Determine the result sign, weight and number of digits to calculate
1173 	 */
1174 	if (var1->sign == var2->sign)
1175 		res_sign = NUMERIC_POS;
1176 	else
1177 		res_sign = NUMERIC_NEG;
1178 	res_weight = var1->weight - var2->weight + 1;
1179 	res_ndigits = rscale + res_weight;
1180 	if (res_ndigits <= 0)
1181 		res_ndigits = 1;
1182 
1183 	/*
1184 	 * Now result zero check
1185 	 */
1186 	if (var1->ndigits == 0)
1187 	{
1188 		zero_var(result);
1189 		result->rscale = rscale;
1190 		return 0;
1191 	}
1192 
1193 	/*
1194 	 * Initialize local variables
1195 	 */
1196 	init_var(&dividend);
1197 	for (i = 1; i < 10; i++)
1198 		init_var(&divisor[i]);
1199 
1200 	/*
1201 	 * Make a copy of the divisor which has one leading zero digit
1202 	 */
1203 	divisor[1].ndigits = ndigits_tmp;
1204 	divisor[1].rscale = var2->ndigits;
1205 	divisor[1].sign = NUMERIC_POS;
1206 	divisor[1].buf = digitbuf_alloc(ndigits_tmp);
1207 	if (divisor[1].buf == NULL)
1208 		goto done;
1209 	divisor[1].digits = divisor[1].buf;
1210 	divisor[1].digits[0] = 0;
1211 	memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
1212 
1213 	/*
1214 	 * Make a copy of the dividend
1215 	 */
1216 	dividend.ndigits = var1->ndigits;
1217 	dividend.weight = 0;
1218 	dividend.rscale = var1->ndigits;
1219 	dividend.sign = NUMERIC_POS;
1220 	dividend.buf = digitbuf_alloc(var1->ndigits);
1221 	if (dividend.buf == NULL)
1222 		goto done;
1223 	dividend.digits = dividend.buf;
1224 	memcpy(dividend.digits, var1->digits, var1->ndigits);
1225 
1226 	/*
1227 	 * Setup the result. Do the allocation in a temporary buffer first, so we
1228 	 * don't free result->buf unless we have successfully allocated a buffer
1229 	 * to replace it with.
1230 	 */
1231 	tmp_buf = digitbuf_alloc(res_ndigits + 2);
1232 	if (tmp_buf == NULL)
1233 		goto done;
1234 	digitbuf_free(result->buf);
1235 	result->buf = tmp_buf;
1236 	res_digits = result->buf;
1237 	result->digits = res_digits;
1238 	result->ndigits = res_ndigits;
1239 	result->weight = res_weight;
1240 	result->rscale = rscale;
1241 	result->sign = res_sign;
1242 	res_digits[0] = 0;
1243 
1244 	first_div = divisor[1].digits[1] * 10;
1245 	if (ndigits_tmp > 2)
1246 		first_div += divisor[1].digits[2];
1247 
1248 	first_have = 0;
1249 	first_nextdigit = 0;
1250 
1251 	weight_tmp = 1;
1252 	rscale_tmp = divisor[1].rscale;
1253 
1254 	for (ri = 0; ri <= res_ndigits; ri++)
1255 	{
1256 		first_have = first_have * 10;
1257 		if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1258 			first_have += dividend.digits[first_nextdigit];
1259 		first_nextdigit++;
1260 
1261 		guess = (first_have * 10) / first_div + 1;
1262 		if (guess > 9)
1263 			guess = 9;
1264 
1265 		while (guess > 0)
1266 		{
1267 			if (divisor[guess].buf == NULL)
1268 			{
1269 				int			i;
1270 				long		sum = 0;
1271 
1272 				memcpy(&divisor[guess], &divisor[1], sizeof(numeric));
1273 				divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
1274 				if (divisor[guess].buf == NULL)
1275 					goto done;
1276 				divisor[guess].digits = divisor[guess].buf;
1277 				for (i = divisor[1].ndigits - 1; i >= 0; i--)
1278 				{
1279 					sum += divisor[1].digits[i] * guess;
1280 					divisor[guess].digits[i] = sum % 10;
1281 					sum /= 10;
1282 				}
1283 			}
1284 
1285 			divisor[guess].weight = weight_tmp;
1286 			divisor[guess].rscale = rscale_tmp;
1287 
1288 			stat = cmp_abs(&dividend, &divisor[guess]);
1289 			if (stat >= 0)
1290 				break;
1291 
1292 			guess--;
1293 		}
1294 
1295 		res_digits[ri + 1] = guess;
1296 		if (stat == 0)
1297 		{
1298 			ri++;
1299 			break;
1300 		}
1301 
1302 		weight_tmp--;
1303 		rscale_tmp++;
1304 
1305 		if (guess == 0)
1306 			continue;
1307 
1308 		if (sub_abs(&dividend, &divisor[guess], &dividend) != 0)
1309 			goto done;
1310 
1311 		first_nextdigit = dividend.weight - weight_tmp;
1312 		first_have = 0;
1313 		if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1314 			first_have = dividend.digits[first_nextdigit];
1315 		first_nextdigit++;
1316 	}
1317 
1318 	result->ndigits = ri + 1;
1319 	if (ri == res_ndigits + 1)
1320 	{
1321 		int			carry = (res_digits[ri] > 4) ? 1 : 0;
1322 
1323 		result->ndigits = ri;
1324 		res_digits[ri] = 0;
1325 
1326 		while (carry && ri > 0)
1327 		{
1328 			carry += res_digits[--ri];
1329 			res_digits[ri] = carry % 10;
1330 			carry /= 10;
1331 		}
1332 	}
1333 
1334 	while (result->ndigits > 0 && *(result->digits) == 0)
1335 	{
1336 		(result->digits)++;
1337 		(result->weight)--;
1338 		(result->ndigits)--;
1339 	}
1340 	while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
1341 		(result->ndigits)--;
1342 	if (result->ndigits == 0)
1343 		result->sign = NUMERIC_POS;
1344 
1345 	result->dscale = res_dscale;
1346 	err = 0;					/* if we've made it this far, return success */
1347 
1348 done:
1349 
1350 	/*
1351 	 * Tidy up
1352 	 */
1353 	if (dividend.buf != NULL)
1354 		digitbuf_free(dividend.buf);
1355 
1356 	for (i = 1; i < 10; i++)
1357 	{
1358 		if (divisor[i].buf != NULL)
1359 			digitbuf_free(divisor[i].buf);
1360 	}
1361 
1362 	return err;
1363 }
1364 
1365 
1366 int
PGTYPESnumeric_cmp(numeric * var1,numeric * var2)1367 PGTYPESnumeric_cmp(numeric *var1, numeric *var2)
1368 {
1369 	/* use cmp_abs function to calculate the result */
1370 
1371 	/* both are positive: normal comparison with cmp_abs */
1372 	if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_POS)
1373 		return cmp_abs(var1, var2);
1374 
1375 	/* both are negative: return the inverse of the normal comparison */
1376 	if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_NEG)
1377 	{
1378 		/*
1379 		 * instead of inverting the result, we invert the parameter ordering
1380 		 */
1381 		return cmp_abs(var2, var1);
1382 	}
1383 
1384 	/* one is positive, one is negative: trivial */
1385 	if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_NEG)
1386 		return 1;
1387 	if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_POS)
1388 		return -1;
1389 
1390 	errno = PGTYPES_NUM_BAD_NUMERIC;
1391 	return INT_MAX;
1392 
1393 }
1394 
1395 int
PGTYPESnumeric_from_int(signed int int_val,numeric * var)1396 PGTYPESnumeric_from_int(signed int int_val, numeric *var)
1397 {
1398 	/* implicit conversion */
1399 	signed long int long_int = int_val;
1400 
1401 	return PGTYPESnumeric_from_long(long_int, var);
1402 }
1403 
1404 int
PGTYPESnumeric_from_long(signed long int long_val,numeric * var)1405 PGTYPESnumeric_from_long(signed long int long_val, numeric *var)
1406 {
1407 	/* calculate the size of the long int number */
1408 	/* a number n needs log_10 n digits */
1409 
1410 	/*
1411 	 * however we multiply by 10 each time and compare instead of calculating
1412 	 * the logarithm
1413 	 */
1414 
1415 	int			size = 0;
1416 	int			i;
1417 	signed long int abs_long_val = long_val;
1418 	signed long int extract;
1419 	signed long int reach_limit;
1420 
1421 	if (abs_long_val < 0)
1422 	{
1423 		abs_long_val *= -1;
1424 		var->sign = NUMERIC_NEG;
1425 	}
1426 	else
1427 		var->sign = NUMERIC_POS;
1428 
1429 	reach_limit = 1;
1430 	do
1431 	{
1432 		size++;
1433 		reach_limit *= 10;
1434 	} while (reach_limit - 1 < abs_long_val && reach_limit <= LONG_MAX / 10);
1435 
1436 	if (reach_limit > LONG_MAX / 10)
1437 	{
1438 		/* add the first digit and a .0 */
1439 		size += 2;
1440 	}
1441 	else
1442 	{
1443 		/* always add a .0 */
1444 		size++;
1445 		reach_limit /= 10;
1446 	}
1447 
1448 	if (alloc_var(var, size) < 0)
1449 		return -1;
1450 
1451 	var->rscale = 1;
1452 	var->dscale = 1;
1453 	var->weight = size - 2;
1454 
1455 	i = 0;
1456 	do
1457 	{
1458 		extract = abs_long_val - (abs_long_val % reach_limit);
1459 		var->digits[i] = extract / reach_limit;
1460 		abs_long_val -= extract;
1461 		i++;
1462 		reach_limit /= 10;
1463 
1464 		/*
1465 		 * we can abandon if abs_long_val reaches 0, because the memory is
1466 		 * initialized properly and filled with '0', so converting 10000 in
1467 		 * only one step is no problem
1468 		 */
1469 	} while (abs_long_val > 0);
1470 
1471 	return 0;
1472 }
1473 
1474 int
PGTYPESnumeric_copy(numeric * src,numeric * dst)1475 PGTYPESnumeric_copy(numeric *src, numeric *dst)
1476 {
1477 	int			i;
1478 
1479 	if (dst == NULL)
1480 		return -1;
1481 	zero_var(dst);
1482 
1483 	dst->weight = src->weight;
1484 	dst->rscale = src->rscale;
1485 	dst->dscale = src->dscale;
1486 	dst->sign = src->sign;
1487 
1488 	if (alloc_var(dst, src->ndigits) != 0)
1489 		return -1;
1490 
1491 	for (i = 0; i < src->ndigits; i++)
1492 		dst->digits[i] = src->digits[i];
1493 
1494 	return 0;
1495 }
1496 
1497 int
PGTYPESnumeric_from_double(double d,numeric * dst)1498 PGTYPESnumeric_from_double(double d, numeric *dst)
1499 {
1500 	char		buffer[DBL_DIG + 100];
1501 	numeric    *tmp;
1502 	int			i;
1503 
1504 	if (sprintf(buffer, "%.*g", DBL_DIG, d) <= 0)
1505 		return -1;
1506 
1507 	if ((tmp = PGTYPESnumeric_from_asc(buffer, NULL)) == NULL)
1508 		return -1;
1509 	i = PGTYPESnumeric_copy(tmp, dst);
1510 	PGTYPESnumeric_free(tmp);
1511 	if (i != 0)
1512 		return -1;
1513 
1514 	errno = 0;
1515 	return 0;
1516 }
1517 
1518 static int
numericvar_to_double(numeric * var,double * dp)1519 numericvar_to_double(numeric *var, double *dp)
1520 {
1521 	char	   *tmp;
1522 	double		val;
1523 	char	   *endptr;
1524 	numeric    *varcopy = PGTYPESnumeric_new();
1525 
1526 	if (varcopy == NULL)
1527 		return -1;
1528 
1529 	if (PGTYPESnumeric_copy(var, varcopy) < 0)
1530 	{
1531 		PGTYPESnumeric_free(varcopy);
1532 		return -1;
1533 	}
1534 
1535 	tmp = get_str_from_var(varcopy, varcopy->dscale);
1536 	PGTYPESnumeric_free(varcopy);
1537 
1538 	if (tmp == NULL)
1539 		return -1;
1540 
1541 	/*
1542 	 * strtod does not reset errno to 0 in case of success.
1543 	 */
1544 	errno = 0;
1545 	val = strtod(tmp, &endptr);
1546 	if (errno == ERANGE)
1547 	{
1548 		free(tmp);
1549 		if (val == 0)
1550 			errno = PGTYPES_NUM_UNDERFLOW;
1551 		else
1552 			errno = PGTYPES_NUM_OVERFLOW;
1553 		return -1;
1554 	}
1555 
1556 	/* can't free tmp yet, endptr points still into it */
1557 	if (*endptr != '\0')
1558 	{
1559 		/* shouldn't happen ... */
1560 		free(tmp);
1561 		errno = PGTYPES_NUM_BAD_NUMERIC;
1562 		return -1;
1563 	}
1564 	free(tmp);
1565 	*dp = val;
1566 	return 0;
1567 }
1568 
1569 int
PGTYPESnumeric_to_double(numeric * nv,double * dp)1570 PGTYPESnumeric_to_double(numeric *nv, double *dp)
1571 {
1572 	double		tmp;
1573 
1574 	if (numericvar_to_double(nv, &tmp) != 0)
1575 		return -1;
1576 	*dp = tmp;
1577 	return 0;
1578 }
1579 
1580 int
PGTYPESnumeric_to_int(numeric * nv,int * ip)1581 PGTYPESnumeric_to_int(numeric *nv, int *ip)
1582 {
1583 	long		l;
1584 	int			i;
1585 
1586 	if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0)
1587 		return i;
1588 
1589 /* silence compilers that might complain about useless tests */
1590 #if SIZEOF_LONG > SIZEOF_INT
1591 
1592 	if (l < INT_MIN || l > INT_MAX)
1593 	{
1594 		errno = PGTYPES_NUM_OVERFLOW;
1595 		return -1;
1596 	}
1597 
1598 #endif
1599 
1600 	*ip = (int) l;
1601 	return 0;
1602 }
1603 
1604 int
PGTYPESnumeric_to_long(numeric * nv,long * lp)1605 PGTYPESnumeric_to_long(numeric *nv, long *lp)
1606 {
1607 	char	   *s = PGTYPESnumeric_to_asc(nv, 0);
1608 	char	   *endptr;
1609 
1610 	if (s == NULL)
1611 		return -1;
1612 
1613 	errno = 0;
1614 	*lp = strtol(s, &endptr, 10);
1615 	if (endptr == s)
1616 	{
1617 		/* this should not happen actually */
1618 		free(s);
1619 		return -1;
1620 	}
1621 	free(s);
1622 	if (errno == ERANGE)
1623 	{
1624 		if (*lp == LONG_MIN)
1625 			errno = PGTYPES_NUM_UNDERFLOW;
1626 		else
1627 			errno = PGTYPES_NUM_OVERFLOW;
1628 		return -1;
1629 	}
1630 	return 0;
1631 }
1632 
1633 int
PGTYPESnumeric_to_decimal(numeric * src,decimal * dst)1634 PGTYPESnumeric_to_decimal(numeric *src, decimal *dst)
1635 {
1636 	int			i;
1637 
1638 	if (src->ndigits > DECSIZE)
1639 	{
1640 		errno = PGTYPES_NUM_OVERFLOW;
1641 		return -1;
1642 	}
1643 
1644 	dst->weight = src->weight;
1645 	dst->rscale = src->rscale;
1646 	dst->dscale = src->dscale;
1647 	dst->sign = src->sign;
1648 	dst->ndigits = src->ndigits;
1649 
1650 	for (i = 0; i < src->ndigits; i++)
1651 		dst->digits[i] = src->digits[i];
1652 
1653 	return 0;
1654 }
1655 
1656 int
PGTYPESnumeric_from_decimal(decimal * src,numeric * dst)1657 PGTYPESnumeric_from_decimal(decimal *src, numeric *dst)
1658 {
1659 	int			i;
1660 
1661 	zero_var(dst);
1662 
1663 	dst->weight = src->weight;
1664 	dst->rscale = src->rscale;
1665 	dst->dscale = src->dscale;
1666 	dst->sign = src->sign;
1667 
1668 	if (alloc_var(dst, src->ndigits) != 0)
1669 		return -1;
1670 
1671 	for (i = 0; i < src->ndigits; i++)
1672 		dst->digits[i] = src->digits[i];
1673 
1674 	return 0;
1675 }
1676