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