1 /****************************************************************************/
2 /*                          APQ DATABASE BINDINGS                           */
3 /*                                                                          */
4 /*                            A P Q - POSTGRESQL			    */
5 /*                                                                          */
6 /*				  B o d y                                   */
7 /*                                                                          */
8 /*         Copyright (C) 2002-2007, Warren W. Gay VE3WWG                    */
9 /*         Copyright (C) 2007-2009, Ada Works Project                       */
10 /*                                                                          */
11 /*                                                                          */
12 /* APQ is free software;  you can  redistribute it  and/or modify it under  */
13 /* terms of the  GNU General Public License as published  by the Free Soft- */
14 /* ware  Foundation;  either version 2,  or (at your option) any later ver- */
15 /* sion.  APQ is distributed in the hope that it will be useful, but WITH-  */
16 /* OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY */
17 /* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License */
18 /* for  more details.  You should have  received  a copy of the GNU General */
19 /* Public License  distributed with APQ;  see file COPYING.  If not, write  */
20 /* to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, */
21 /* MA 02111-1307, USA.                                                      */
22 /*                                                                          */
23 /* As a special exception,  if other files  instantiate  generics from this */
24 /* unit, or you link  this unit with other files  to produce an executable, */
25 /* this  unit  does not  by itself cause  the resulting  executable  to  be */
26 /* covered  by the  GNU  General  Public  License.  This exception does not */
27 /* however invalidate  any other reasons why  the executable file  might be */
28 /* covered by the  GNU Public License.                                      */
29 /****************************************************************************/
30 
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34 
35 #include "decimal.h"
36 
37 /* ----------
38  * Uncomment the following to enable compilation of dump_numeric()
39  * and dump_var() and to get a dump of any result produced by make_result().
40  * ----------
41 #define NUMERIC_DEBUG
42  */
43 
44 /* ----------
45  * Local definitions
46  * ----------
47  */
48 #ifndef MIN
49 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
50 #endif
51 #ifndef MAX
52 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
53 #endif
54 
55 #ifndef NAN
56 #define NAN		(0.0/0.0)
57 #endif
58 
59 #define nan_var(v)	free_var(v)
60 
61 /* ----------
62  * Local data types
63  *
64  * Note: the first digit of a NumericVar's value is assumed to be multiplied
65  * by 10 ** weight.  Another way to say it is that there are weight+1 digits
66  * before the decimal point.  It is possible to have weight < 0.
67  *
68  * The value represented by a NumericVar is determined by the sign, weight,
69  * ndigits, and digits[] array.  The rscale and dscale are carried along,
70  * but they are just auxiliary information until rounding is done before
71  * final storage or display.  (Scales are the number of digits wanted
72  * *after* the decimal point.  Scales are always >= 0.)
73  *
74  * buf points at the physical start of the palloc'd digit buffer for the
75  * NumericVar.	digits points at the first digit in actual use (the one
76  * with the specified weight).	We normally leave an unused byte or two
77  * (preset to zeroes) between buf and digits, so that there is room to store
78  * a carry out of the top digit without special pushups.  We just need to
79  * decrement digits (and increment weight) to make room for the carry digit.
80  *
81  * If buf is NULL then the digit buffer isn't actually palloc'd and should
82  * not be freed --- see the constants below for an example.
83  *
84  * NB: All the variable-level functions are written in a style that makes it
85  * possible to give one and the same variable as argument and destination.
86  * This is feasible because the digit buffer is separate from the variable.
87  * ----------
88  */
89 typedef unsigned char NumericDigit;
90 
91 typedef struct NumericVar
92 {
93 	int		ndigits;	/* number of digits in digits[] - can be * 0! */
94 	int		weight;		/* weight of first digit */
95 	int		rscale;		/* result scale */
96 	int		dscale;		/* display scale */
97 	int		sign;		/* NUMERIC_POS, NUMERIC_NEG, or * NUMERIC_NAN */
98 	NumericDigit	*buf;		/* start of palloc'd space for digits[] */
99 	NumericDigit	*digits;	/* decimal digits */
100 } NumericVar;
101 
102 /* ----------
103  * Some preinitialized variables we need often
104  * ----------
105  */
106 static NumericDigit const_zero_data[1] = {0};
107 static NumericVar const_zero = {0, 0, 0, 0, NUMERIC_POS, NULL, const_zero_data};
108 
109 static NumericDigit const_one_data[1] = {1};
110 static NumericVar const_one = {1, 0, 0, 0, NUMERIC_POS, NULL, const_one_data};
111 
112 static NumericDigit const_two_data[1] = {2};
113 static NumericVar const_two = {1, 0, 0, 0, NUMERIC_POS, NULL, const_two_data};
114 
115 static NumericVar const_nan = {0, 0, 0, 0, NUMERIC_NAN, NULL, NULL};
116 
117 /* ----------
118  * Local functions
119  * ----------
120  */
121 
122 #ifdef NUMERIC_DEBUG
123 static void dump_numeric(char *str, Numeric num);
124 static void dump_var(char *str, NumericVar *var);
125 #else
126 #define dump_numeric(s,n)
127 #define dump_var(s,v)
128 #endif
129 
130 #define digitbuf_alloc(size)  ((NumericDigit *) palloc(size))
131 #define digitbuf_free(buf)	\
132 	do { \
133 		 if ((buf) != NULL) \
134 			 pfree(buf); \
135 	} while (0)
136 
137 #define init_var(v)		memset(v,0,sizeof(NumericVar))
138 static void alloc_var(NumericVar *var, int ndigits);
139 static void free_var(NumericVar *var);
140 static void zero_var(NumericVar *var);
141 
142 static void set_var_from_str(const char *str, NumericVar *dest, Decimal_Exception *ex);
143 static void set_var_from_num(Numeric value, NumericVar *dest);
144 static void set_var_from_var(NumericVar *value, NumericVar *dest);
145 static char *get_str_from_var(NumericVar *var, int dscale);
146 
147 static Numeric make_result(NumericVar *var);
148 
149 static void apply_typmod(NumericVar *var, int precision, int scale, Decimal_Exception *ex);
150 
151 static int cmp_numerics(Numeric num1, Numeric num2);
152 static int cmp_var(NumericVar *var1, NumericVar *var2);
153 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
154 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
155 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int *global_rscale);
156 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int *global_rscale, Decimal_Exception *ex);
157 static int select_div_scale(NumericVar *var1, NumericVar *var2, int *global_rscale);
158 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int *global_rscale, Decimal_Exception *ex);
159 static void ceil_var(NumericVar *var, NumericVar *result);
160 static void floor_var(NumericVar *var, NumericVar *result);
161 
162 static void sqrt_var(NumericVar *arg, NumericVar *result, int *global_rscale, Decimal_Exception *ex);
163 static void exp_var(NumericVar *arg, NumericVar *result, int *global_rscale, Decimal_Exception *ex);
164 static void ln_var(NumericVar *arg, NumericVar *result, int *global_rscale, Decimal_Exception *ex);
165 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result, int *global_rscale, Decimal_Exception *ex);
166 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result, int *global_rscale, Decimal_Exception *ex);
167 
168 static int cmp_abs(NumericVar *var1, NumericVar *var2);
169 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
170 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
171 
172 /*
173  * Provide an initialization value for global_rscale :
174  */
175 int
numeric_global_rscale(void)176 numeric_global_rscale(void) {
177 	return NUMERIC_MIN_RESULT_SCALE;
178 }
179 
180 /* ----------------------------------------------------------------------
181  *
182  * Input-, output- and rounding-functions
183  *
184  * ----------------------------------------------------------------------
185  * numeric_in() -
186  *
187  *	Input function for numeric data type :
188  * NOTES:
189  *	When precision is zero, the precision and scale arguments are
190  *	ignored. Otherwise the converted value is made to fit the
191  *	parameters supplied, else Numeric_Overflow exception.
192  * ----------
193  */
194 Numeric
numeric_in(const char * str,int precision,int scale,Decimal_Exception * ex)195 numeric_in(const char *str, int precision, int scale, Decimal_Exception *ex) {
196 	NumericVar	value;
197 	Numeric		res;
198 
199 	*ex = No_Error;
200 
201 	/*
202 	 * Check for NaN
203 	 */
204 	if (strcmp(str, "NaN") == 0)
205 		return make_result(&const_nan);
206 
207 	/*
208 	 * Use set_var_from_str() to parse the input string and return it in
209 	 * the packed DB storage format
210 	 */
211 	init_var(&value);
212 	set_var_from_str(str, &value, ex);
213 	if ( *ex != No_Error ) {
214 		res = make_result(&const_nan);
215 	} else	{
216 		if ( precision != 0 )
217 			apply_typmod(&value, precision, scale, ex);
218 		res = make_result(&value);
219 	}
220 	free_var(&value);
221 
222 	return res;
223 }
224 
225 /* ----------
226  * numeric_out() -
227  *
228  *	Output function for numeric data type
229  * ----------
230  */
231 char *
numeric_out(Numeric num)232 numeric_out(Numeric num) {
233 	NumericVar	x;
234 	char	   	*str;
235 
236 	/*
237 	 * Handle NaN
238 	 */
239 	if (NUMERIC_IS_NAN(num))
240 		return pstrdup("NaN");
241 
242 	/*
243 	 * Get the number in the variable format.
244 	 *
245 	 * Even if we didn't need to change format, we'd still need to copy the
246 	 * value to have a modifiable copy for rounding.  set_var_from_num()
247 	 * also guarantees there is extra digit space in case we produce a
248 	 * carry out from rounding.
249 	 */
250 	init_var(&x);
251 	set_var_from_num(num, &x);
252 
253 	str = get_str_from_var(&x, x.dscale);
254 
255 	free_var(&x);
256 
257 	return str;
258 }
259 
260 /*
261  * Return TRUE if the value is NaN :
262  */
263 int
numeric_isnan(Numeric num)264 numeric_isnan(Numeric num) {
265 	return NUMERIC_IS_NAN(num);
266 }
267 
268 /* ----------
269  * numeric() -
270  *
271  *	This is a special function called by the Postgres database system
272  *	before a value is stored in a tuples attribute. The precision and
273  *	scale of the attribute have to be applied on the value.
274  * ----------
275  */
276 Numeric
numeric(Numeric num,int precision,int scale,Decimal_Exception * ex)277 numeric(Numeric num, int precision, int scale, Decimal_Exception *ex) {
278 	Numeric		new;
279 	int		maxweight;
280 	NumericVar	var;
281 
282 	*ex = No_Error;
283 
284 	/*
285 	 * Handle NaN
286 	 */
287 	if (NUMERIC_IS_NAN(num))
288 		return make_result(&const_nan);
289 
290 	maxweight = precision - scale;
291 
292 	/*
293 	 * If the number is in bounds and due to the present result scale no
294 	 * rounding could be necessary, just make a copy of the input and
295 	 * modify its scale fields.
296 	 */
297 	if (num->n_weight < maxweight && scale >= num->n_rscale)
298 	{
299 		new = (Numeric) palloc(num->varlen);
300 		memcpy(new, num, num->varlen);
301 		new->n_rscale = scale;
302 		new->n_sign_dscale = NUMERIC_SIGN(new) | ((uint16) scale & NUMERIC_DSCALE_MASK);
303 		return new;
304 	}
305 
306 	/*
307 	 * We really need to fiddle with things - unpack the number into a
308 	 * variable and let apply_typmod() do it.
309 	 */
310 	init_var(&var);
311 	set_var_from_num(num, &var);
312 	apply_typmod(&var, precision, scale, ex);
313 	new = make_result(&var);
314 
315 	free_var(&var);
316 
317 	return new;
318 }
319 
320 /*
321  * Release the storage occupied by this Numeric :
322  * (designed to be called by Ada95)
323  */
324 void
numeric_free(Numeric num)325 numeric_free(Numeric num) {
326 	free(num);
327 }
328 
329 /* ----------------------------------------------------------------------
330  *
331  * Sign manipulation, rounding and the like
332  *
333  * ----------------------------------------------------------------------
334  */
335 Numeric
numeric_abs(Numeric num)336 numeric_abs(Numeric num) {
337 	Numeric		res;
338 
339 	/*
340 	 * Handle NaN
341 	 */
342 	if (NUMERIC_IS_NAN(num))
343 		return make_result(&const_nan);
344 
345 	/*
346 	 * Do it the easy way directly on the packed format
347 	 */
348 	res = (Numeric) palloc(num->varlen);
349 	memcpy(res, num, num->varlen);
350 
351 	res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
352 
353 	return res;
354 }
355 
356 Numeric
numeric_uminus(Numeric num)357 numeric_uminus(Numeric num) {
358 	Numeric		res;
359 
360 	/*
361 	 * Handle NaN
362 	 */
363 	if (NUMERIC_IS_NAN(num))
364 		return make_result(&const_nan);
365 
366 	/*
367 	 * Do it the easy way directly on the packed format
368 	 */
369 	res = (Numeric) palloc(num->varlen);
370 	memcpy(res, num, num->varlen);
371 
372 	/*
373 	 * The packed format is known to be totally zero digit trimmed always.
374 	 * So we can identify a ZERO by the fact that there are no digits at
375 	 * all.  Do nothing to a zero.
376 	 */
377 	if (num->varlen != NUMERIC_HDRSZ)
378 	{
379 		/* Else, flip the sign */
380 		if (NUMERIC_SIGN(num) == NUMERIC_POS)
381 			res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
382 		else
383 			res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
384 	}
385 
386 	return res;
387 }
388 
389 /*
390  * This effectively just copies the value :
391  */
392 Numeric
numeric_uplus(Numeric num)393 numeric_uplus(Numeric num) {
394 	Numeric		res;
395 
396 	res = (Numeric) palloc(num->varlen);
397 	memcpy(res, num, num->varlen);
398 	return res;
399 }
400 
401 /*
402  * Return the sign of the value :
403  */
404 Numeric
numeric_sign(Numeric num)405 numeric_sign(Numeric num) {
406 	Numeric		res;
407 	NumericVar	result;
408 
409 	/*
410 	 * Handle NaN
411 	 */
412 	if (NUMERIC_IS_NAN(num))
413 		return make_result(&const_nan);
414 
415 	init_var(&result);
416 
417 	/*
418 	 * The packed format is known to be totally zero digit trimmed always.
419 	 * So we can identify a ZERO by the fact that there are no digits at
420 	 * all.
421 	 */
422 	if (num->varlen == NUMERIC_HDRSZ)
423 		set_var_from_var(&const_zero, &result);
424 	else
425 	{
426 		/*
427 		 * And if there are some, we return a copy of ONE with the sign of
428 		 * our argument
429 		 */
430 		set_var_from_var(&const_one, &result);
431 		result.sign = NUMERIC_SIGN(num);
432 	}
433 
434 	res = make_result(&result);
435 	free_var(&result);
436 
437 	return res;
438 }
439 
440 /* ----------
441  * numeric_round() -
442  *
443  *	Round a value to have 'scale' digits after the decimal point.
444  *	We allow negative 'scale', implying rounding before the decimal
445  *	point --- Oracle interprets rounding that way.
446  * ----------
447  */
448 Numeric
numeric_round(Numeric num,int scale)449 numeric_round(Numeric num,int scale) {
450 	Numeric		res;
451 	NumericVar	arg;
452 	int			i;
453 
454 	/*
455 	 * Handle NaN
456 	 */
457 	if (NUMERIC_IS_NAN(num))
458 		return make_result(&const_nan);
459 
460 	/*
461 	 * Limit the scale value to avoid possible overflow in calculations
462 	 * below.
463 	 */
464 	scale = MIN(NUMERIC_MAX_RESULT_SCALE,
465 				MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
466 
467 	/*
468 	 * Unpack the argument and round it at the proper digit position
469 	 */
470 	init_var(&arg);
471 	set_var_from_num(num, &arg);
472 
473 	i = arg.weight + scale + 1;
474 
475 	if (i < arg.ndigits)
476 	{
477 		/*
478 		 * If i = 0, the value loses all digits, but could round up if its
479 		 * first digit is more than 4.	If i < 0 the result must be 0.
480 		 */
481 		if (i < 0)
482 			arg.ndigits = 0;
483 		else
484 		{
485 			int			carry = (arg.digits[i] > 4) ? 1 : 0;
486 
487 			arg.ndigits = i;
488 
489 			while (carry)
490 			{
491 				carry += arg.digits[--i];
492 				arg.digits[i] = carry % 10;
493 				carry /= 10;
494 			}
495 
496 			if (i < 0)
497 			{
498 				Assert(i == -1);	/* better not have added more than 1 digit */
499 				Assert(arg.digits > arg.buf);
500 				arg.digits--;
501 				arg.ndigits++;
502 				arg.weight++;
503 			}
504 		}
505 	}
506 
507 	/*
508 	 * Set result's scale to something reasonable.
509 	 */
510 	scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
511 	arg.rscale = scale;
512 	arg.dscale = scale;
513 
514 	/*
515 	 * Return the rounded result
516 	 */
517 	res = make_result(&arg);
518 
519 	free_var(&arg);
520 	return res;
521 }
522 
523 /* ----------
524  * numeric_trunc() -
525  *
526  *	Truncate a value to have 'scale' digits after the decimal point.
527  *	We allow negative 'scale', implying a truncation before the decimal
528  *	point --- Oracle interprets truncation that way.
529  * ----------
530  */
531 Numeric
numeric_trunc(Numeric num,int scale)532 numeric_trunc(Numeric num,int scale) {
533 	Numeric		res;
534 	NumericVar	arg;
535 
536 	/*
537 	 * Handle NaN
538 	 */
539 	if (NUMERIC_IS_NAN(num))
540 		return make_result(&const_nan);
541 
542 	/*
543 	 * Limit the scale value to avoid possible overflow in calculations
544 	 * below.
545 	 */
546 	scale = MIN(NUMERIC_MAX_RESULT_SCALE,
547 				MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
548 
549 	/*
550 	 * Unpack the argument and truncate it at the proper digit position
551 	 */
552 	init_var(&arg);
553 	set_var_from_num(num, &arg);
554 
555 	arg.ndigits = MIN(arg.ndigits, MAX(0, arg.weight + scale + 1));
556 
557 	/*
558 	 * Set result's scale to something reasonable.
559 	 */
560 	scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
561 	arg.rscale = scale;
562 	arg.dscale = scale;
563 
564 	/*
565 	 * Return the truncated result
566 	 */
567 	res = make_result(&arg);
568 
569 	free_var(&arg);
570 	return res;
571 }
572 
573 /* ----------
574  * numeric_ceil() -
575  *
576  *	Return the smallest integer greater than or equal to the argument
577  * ----------
578  */
579 Numeric
numeric_ceil(Numeric num)580 numeric_ceil(Numeric num) {
581 	Numeric		res;
582 	NumericVar	result;
583 
584 	if (NUMERIC_IS_NAN(num))
585 		return make_result(&const_nan);
586 
587 	init_var(&result);
588 
589 	set_var_from_num(num, &result);
590 	ceil_var(&result, &result);
591 
592 	result.dscale = 0;
593 
594 	res = make_result(&result);
595 	free_var(&result);
596 
597 	return res;
598 }
599 
600 
601 /* ----------
602  * numeric_floor() -
603  *
604  *	Return the largest integer equal to or less than the argument
605  * ----------
606  */
607 Numeric
numeric_floor(Numeric num)608 numeric_floor(Numeric num) {
609 	Numeric		res;
610 	NumericVar	result;
611 
612 	if (NUMERIC_IS_NAN(num))
613 		return make_result(&const_nan);
614 
615 	init_var(&result);
616 
617 	set_var_from_num(num, &result);
618 	floor_var(&result, &result);
619 
620 	result.dscale = 0;
621 
622 	res = make_result(&result);
623 	free_var(&result);
624 
625 	return res;
626 }
627 
628 
629 /* ----------------------------------------------------------------------
630  *
631  * Comparison functions
632  *
633  * Note: btree indexes need these routines not to leak memory; therefore,
634  * be careful to free working copies of toasted datums.  Most places don't
635  * need to be so careful.
636  * ----------------------------------------------------------------------
637  */
638 
639 int
numeric_cmp(Numeric num1,Numeric num2)640 numeric_cmp(Numeric num1, Numeric num2) {
641 	Numeric	orig1 = num1, orig2 = num2;
642 	int	result;
643 
644 	result = cmp_numerics(num1, num2);
645 
646 	if ( num1 != orig1 )
647 		free(num1);
648 	if ( num2 != orig2 )
649 		free(num2);
650 
651 	return result;
652 }
653 
654 int
numeric_eq(Numeric num1,Numeric num2)655 numeric_eq(Numeric num1, Numeric num2) {
656 	return numeric_cmp(num1,num2) == 0;
657 }
658 
659 int
numeric_ne(Numeric num1,Numeric num2)660 numeric_ne(Numeric num1, Numeric num2) {
661 	return numeric_cmp(num1,num2) != 0;
662 }
663 
664 int
numeric_gt(Numeric num1,Numeric num2)665 numeric_gt(Numeric num1, Numeric num2) {
666 	return numeric_cmp(num1,num2) > 0;
667 }
668 
669 int
numeric_ge(Numeric num1,Numeric num2)670 numeric_ge(Numeric num1, Numeric num2) {
671 	return numeric_cmp(num1,num2) >= 0;
672 }
673 
674 int
numeric_lt(Numeric num1,Numeric num2)675 numeric_lt(Numeric num1, Numeric num2) {
676 	return numeric_cmp(num1,num2) < 0;
677 }
678 
679 int
numeric_le(Numeric num1,Numeric num2)680 numeric_le(Numeric num1, Numeric num2) {
681 	return numeric_cmp(num1,num2) <= 0;
682 }
683 
684 static int
cmp_numerics(Numeric num1,Numeric num2)685 cmp_numerics(Numeric num1, Numeric num2)
686 {
687 	int			result;
688 
689 	/*
690 	 * We consider all NANs to be equal and larger than any non-NAN. This
691 	 * is somewhat arbitrary; the important thing is to have a consistent
692 	 * sort order.
693 	 */
694 	if (NUMERIC_IS_NAN(num1))
695 	{
696 		if (NUMERIC_IS_NAN(num2))
697 			result = 0;			/* NAN = NAN */
698 		else
699 			result = 1;			/* NAN > non-NAN */
700 	}
701 	else if (NUMERIC_IS_NAN(num2))
702 	{
703 		result = -1;			/* non-NAN < NAN */
704 	}
705 	else
706 	{
707 		NumericVar	arg1;
708 		NumericVar	arg2;
709 
710 		init_var(&arg1);
711 		init_var(&arg2);
712 
713 		set_var_from_num(num1, &arg1);
714 		set_var_from_num(num2, &arg2);
715 
716 		result = cmp_var(&arg1, &arg2);
717 
718 		free_var(&arg1);
719 		free_var(&arg2);
720 	}
721 
722 	return result;
723 }
724 
725 
726 /* ----------------------------------------------------------------------
727  *
728  * Arithmetic base functions
729  *
730  * ----------------------------------------------------------------------
731  * numeric_add() -
732  *
733  *	Add two numerics
734  * ----------
735  */
736 Numeric
numeric_add(Numeric num1,Numeric num2)737 numeric_add(Numeric num1, Numeric num2) {
738 	NumericVar	arg1;
739 	NumericVar	arg2;
740 	NumericVar	result;
741 	Numeric		res;
742 
743 	/*
744 	 * Handle NaN
745 	 */
746 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
747 		return make_result(&const_nan);
748 
749 	/*
750 	 * Unpack the values, let add_var() compute the result and return it.
751 	 * The internals of add_var() will automatically set the correct
752 	 * result and display scales in the result.
753 	 */
754 	init_var(&arg1);
755 	init_var(&arg2);
756 	init_var(&result);
757 
758 	set_var_from_num(num1, &arg1);
759 	set_var_from_num(num2, &arg2);
760 
761 	add_var(&arg1, &arg2, &result);
762 	res = make_result(&result);
763 
764 	free_var(&arg1);
765 	free_var(&arg2);
766 	free_var(&result);
767 
768 	return res;
769 }
770 
771 /* ----------
772  * numeric_sub() -
773  *
774  *	Subtract one numeric from another
775  * ----------
776  */
777 Numeric
numeric_sub(Numeric num1,Numeric num2)778 numeric_sub(Numeric num1, Numeric num2) {
779 	NumericVar	arg1;
780 	NumericVar	arg2;
781 	NumericVar	result;
782 	Numeric		res;
783 
784 	/*
785 	 * Handle NaN
786 	 */
787 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
788 		return make_result(&const_nan);
789 
790 	/*
791 	 * Unpack the two arguments, let sub_var() compute the result and
792 	 * return it.
793 	 */
794 	init_var(&arg1);
795 	init_var(&arg2);
796 	init_var(&result);
797 
798 	set_var_from_num(num1, &arg1);
799 	set_var_from_num(num2, &arg2);
800 
801 	sub_var(&arg1, &arg2, &result);
802 	res = make_result(&result);
803 
804 	free_var(&arg1);
805 	free_var(&arg2);
806 	free_var(&result);
807 
808 	return res;
809 }
810 
811 /* ----------
812  * numeric_mul() -
813  *
814  *	Calculate the product of two numerics
815  * ----------
816  */
817 Numeric
numeric_mul(Numeric num1,Numeric num2,int * global_rscale)818 numeric_mul(Numeric num1, Numeric num2, int *global_rscale) {
819 	NumericVar	arg1;
820 	NumericVar	arg2;
821 	NumericVar	result;
822 	Numeric		res;
823 
824 	/*
825 	 * Handle NaN
826 	 */
827 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
828 		return make_result(&const_nan);
829 
830 	/*
831 	 * Unpack the arguments, let mul_var() compute the result and return
832 	 * it. Unlike add_var() and sub_var(), mul_var() will round the result
833 	 * to the scale stored in global_rscale. In the case of numeric_mul(),
834 	 * which is invoked for the * operator on numerics, we set it to the
835 	 * exact representation for the product (rscale = sum(rscale of arg1,
836 	 * rscale of arg2) and the same for the dscale).
837 	 */
838 	init_var(&arg1);
839 	init_var(&arg2);
840 	init_var(&result);
841 
842 	set_var_from_num(num1, &arg1);
843 	set_var_from_num(num2, &arg2);
844 
845 	*global_rscale = arg1.rscale + arg2.rscale;
846 
847 	mul_var(&arg1, &arg2, &result, global_rscale);
848 
849 	result.dscale = arg1.dscale + arg2.dscale;
850 
851 	res = make_result(&result);
852 
853 	free_var(&arg1);
854 	free_var(&arg2);
855 	free_var(&result);
856 
857 	return res;
858 }
859 
860 /* ----------
861  * numeric_div() -
862  *
863  *	Divide one numeric into another
864  * ----------
865  */
866 Numeric
numeric_div(Numeric num1,Numeric num2,int * global_rscale,Decimal_Exception * ex)867 numeric_div(Numeric num1, Numeric num2, int *global_rscale, Decimal_Exception *ex) {
868 	NumericVar	arg1;
869 	NumericVar	arg2;
870 	NumericVar	result;
871 	Numeric		res;
872 	int		res_dscale;
873 
874 	*ex = No_Error;
875 
876 	/*
877 	 * Handle NaN
878 	 */
879 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
880 		return make_result(&const_nan);
881 
882 	/*
883 	 * Unpack the arguments
884 	 */
885 	init_var(&arg1);
886 	init_var(&arg2);
887 	init_var(&result);
888 
889 	set_var_from_num(num1, &arg1);
890 	set_var_from_num(num2, &arg2);
891 
892 	res_dscale = select_div_scale(&arg1, &arg2, global_rscale);
893 
894 	/*
895 	 * Do the divide, set the display scale and return the result
896 	 */
897 	div_var(&arg1, &arg2, &result, global_rscale, ex);
898 	if ( *ex != No_Error ) {
899 		res = make_result(&const_nan);
900 	} else	{
901 		result.dscale = res_dscale;
902 		res = make_result(&result);
903 	}
904 
905 	free_var(&arg1);
906 	free_var(&arg2);
907 	free_var(&result);
908 
909 	return res;
910 }
911 
912 /* ----------
913  * numeric_mod() -
914  *
915  *	Calculate the modulo of two numerics
916  * ----------
917  */
918 Numeric
numeric_mod(Numeric num1,Numeric num2,int * global_rscale,Decimal_Exception * ex)919 numeric_mod(Numeric num1, Numeric num2, int *global_rscale, Decimal_Exception *ex) {
920 	Numeric		res;
921 	NumericVar	arg1;
922 	NumericVar	arg2;
923 	NumericVar	result;
924 
925 	*ex = No_Error;
926 
927 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
928 		return make_result(&const_nan);
929 
930 	init_var(&arg1);
931 	init_var(&arg2);
932 	init_var(&result);
933 
934 	set_var_from_num(num1, &arg1);
935 	set_var_from_num(num2, &arg2);
936 
937 	mod_var(&arg1, &arg2, &result, global_rscale, ex);
938 
939 	res = make_result(&result);
940 
941 	free_var(&result);
942 	free_var(&arg2);
943 	free_var(&arg1);
944 
945 	return res;
946 }
947 
948 /* ----------
949  * numeric_smaller() -
950  *
951  *	Return the smaller of two numbers
952  * ----------
953  */
954 Numeric
numeric_smaller(Numeric num1,Numeric num2)955 numeric_smaller(Numeric num1, Numeric num2) {
956 	NumericVar	arg1;
957 	NumericVar	arg2;
958 	Numeric		res;
959 
960 	/*
961 	 * Handle NaN
962 	 */
963 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
964 		return make_result(&const_nan);
965 
966 	/*
967 	 * Unpack the values, and decide which is the smaller one
968 	 */
969 	init_var(&arg1);
970 	init_var(&arg2);
971 
972 	set_var_from_num(num1, &arg1);
973 	set_var_from_num(num2, &arg2);
974 
975 	if (cmp_var(&arg1, &arg2) <= 0)
976 		res = make_result(&arg1);
977 	else
978 		res = make_result(&arg2);
979 
980 	free_var(&arg1);
981 	free_var(&arg2);
982 
983 	return res;
984 }
985 
986 
987 /* ----------
988  * numeric_larger() -
989  *
990  *	Return the larger of two numbers
991  * ----------
992  */
993 Numeric
numeric_larger(Numeric num1,Numeric num2)994 numeric_larger(Numeric num1, Numeric num2) {
995 	NumericVar	arg1;
996 	NumericVar	arg2;
997 	Numeric		res;
998 
999 	/*
1000 	 * Handle NaN
1001 	 */
1002 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1003 		return make_result(&const_nan);
1004 
1005 	/*
1006 	 * Unpack the values, and decide which is the larger one
1007 	 */
1008 	init_var(&arg1);
1009 	init_var(&arg2);
1010 
1011 	set_var_from_num(num1, &arg1);
1012 	set_var_from_num(num2, &arg2);
1013 
1014 	if (cmp_var(&arg1, &arg2) >= 0)
1015 		res = make_result(&arg1);
1016 	else
1017 		res = make_result(&arg2);
1018 
1019 	free_var(&arg1);
1020 	free_var(&arg2);
1021 
1022 	return res;
1023 }
1024 
1025 /* ----------------------------------------------------------------------
1026  *
1027  * Complex math functions
1028  *
1029  * ----------------------------------------------------------------------
1030  * numeric_sqrt() -
1031  *
1032  *	Compute the square root of a numeric.
1033  * ----------
1034  */
1035 Numeric
numeric_sqrt(Numeric num,int * global_rscale,Decimal_Exception * ex)1036 numeric_sqrt(Numeric num, int *global_rscale, Decimal_Exception *ex) {
1037 	Numeric		res;
1038 	NumericVar	arg;
1039 	NumericVar	result;
1040 	int		res_dscale;
1041 
1042 	*ex = No_Error;
1043 
1044 	/*
1045 	 * Handle NaN
1046 	 */
1047 	if (NUMERIC_IS_NAN(num))
1048 		return make_result(&const_nan);
1049 
1050 	/*
1051 	 * Unpack the argument, determine the scales like for divide, let
1052 	 * sqrt_var() do the calculation and return the result.
1053 	 */
1054 	init_var(&arg);
1055 	init_var(&result);
1056 
1057 	set_var_from_num(num, &arg);
1058 
1059 	res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1060 	res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1061 	*global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1062 	*global_rscale = MAX(*global_rscale, res_dscale + 4);
1063 	*global_rscale = MIN(*global_rscale, NUMERIC_MAX_RESULT_SCALE);
1064 
1065 	sqrt_var(&arg, &result, global_rscale, ex);
1066 
1067 	result.dscale = res_dscale;
1068 
1069 	res = make_result(&result);
1070 
1071 	free_var(&result);
1072 	free_var(&arg);
1073 
1074 	return res;
1075 }
1076 
1077 /* ----------
1078  * numeric_exp() -
1079  *
1080  *	Raise e to the power of x
1081  * ----------
1082  */
1083 Numeric
numeric_exp(Numeric num,int * global_rscale,Decimal_Exception * ex)1084 numeric_exp(Numeric num, int *global_rscale, Decimal_Exception *ex) {
1085 	Numeric		res;
1086 	NumericVar	arg;
1087 	NumericVar	result;
1088 	int		res_dscale;
1089 
1090 	*ex = No_Error;
1091 
1092 	/*
1093 	 * Handle NaN
1094 	 */
1095 	if (NUMERIC_IS_NAN(num))
1096 		return make_result(&const_nan);
1097 
1098 	/*
1099 	 * Same procedure like for sqrt().
1100 	 */
1101 	init_var(&arg);
1102 	init_var(&result);
1103 	set_var_from_num(num, &arg);
1104 
1105 	res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1106 	res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1107 	*global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1108 	*global_rscale = MAX(*global_rscale, res_dscale + 4);
1109 	*global_rscale = MIN(*global_rscale, NUMERIC_MAX_RESULT_SCALE);
1110 
1111 	exp_var(&arg, &result, global_rscale, ex);
1112 
1113 	result.dscale = res_dscale;
1114 
1115 	res = make_result(&result);
1116 
1117 	free_var(&result);
1118 	free_var(&arg);
1119 
1120 	return res;
1121 }
1122 
1123 
1124 /* ----------
1125  * numeric_ln() -
1126  *
1127  *	Compute the natural logarithm of x
1128  * ----------
1129  */
1130 Numeric
numeric_ln(Numeric num,int * global_rscale,Decimal_Exception * ex)1131 numeric_ln(Numeric num, int *global_rscale, Decimal_Exception *ex) {
1132 	Numeric		res;
1133 	NumericVar	arg;
1134 	NumericVar	result;
1135 	int		res_dscale;
1136 
1137 	*ex = No_Error;
1138 
1139 	/*
1140 	 * Handle NaN
1141 	 */
1142 	if (NUMERIC_IS_NAN(num))
1143 		return make_result(&const_nan);
1144 
1145 	/*
1146 	 * Same procedure like for sqrt()
1147 	 */
1148 	init_var(&arg);
1149 	init_var(&result);
1150 	set_var_from_num(num, &arg);
1151 
1152 	res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1153 	res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1154 	*global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1155 	*global_rscale = MAX(*global_rscale, res_dscale + 4);
1156 	*global_rscale = MIN(*global_rscale, NUMERIC_MAX_RESULT_SCALE);
1157 
1158 	ln_var(&arg, &result, global_rscale, ex);
1159 	if ( *ex == No_Error )
1160 		result.dscale = res_dscale;
1161 
1162 	res = make_result(&result);
1163 
1164 	free_var(&result);
1165 	free_var(&arg);
1166 
1167 	return res;
1168 }
1169 
1170 
1171 /* ----------
1172  * numeric_log() -
1173  *
1174  *	Compute the logarithm of x in a given base
1175  * ----------
1176  */
1177 Numeric
numeric_log(Numeric num1,Numeric num2,int * global_rscale,Decimal_Exception * ex)1178 numeric_log(Numeric num1, Numeric num2, int *global_rscale, Decimal_Exception *ex) {
1179 	Numeric		res;
1180 	NumericVar	arg1;
1181 	NumericVar	arg2;
1182 	NumericVar	result;
1183 	int		res_dscale;
1184 
1185 	*ex = No_Error;
1186 
1187 	/*
1188 	 * Handle NaN
1189 	 */
1190 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1191 		return make_result(&const_nan);
1192 
1193 	/*
1194 	 * Initialize things and calculate scales
1195 	 */
1196 	init_var(&arg1);
1197 	init_var(&arg2);
1198 	init_var(&result);
1199 	set_var_from_num(num1, &arg1);
1200 	set_var_from_num(num2, &arg2);
1201 
1202 	res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1203 	res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1204 	*global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1205 	*global_rscale = MAX(*global_rscale, res_dscale + 4);
1206 	*global_rscale = MIN(*global_rscale, NUMERIC_MAX_RESULT_SCALE);
1207 
1208 	/*
1209 	 * Call log_var() to compute and return the result
1210 	 */
1211 	log_var(&arg1, &arg2, &result, global_rscale, ex);
1212 
1213 	if ( *ex == No_Error )
1214 		result.dscale = res_dscale;
1215 
1216 	res = make_result(&result);
1217 
1218 	free_var(&result);
1219 	free_var(&arg2);
1220 	free_var(&arg1);
1221 
1222 	return res;
1223 }
1224 
1225 
1226 /* ----------
1227  * numeric_power() -
1228  *
1229  *	Raise m to the power of x
1230  * ----------
1231  */
1232 Numeric
numeric_power(Numeric num1,Numeric num2,int * global_rscale,Decimal_Exception * ex)1233 numeric_power(Numeric num1, Numeric num2, int *global_rscale, Decimal_Exception *ex) {
1234 	Numeric		res;
1235 	NumericVar	arg1;
1236 	NumericVar	arg2;
1237 	NumericVar	result;
1238 	int		res_dscale;
1239 
1240 	*ex = No_Error;
1241 
1242 	/*
1243 	 * Handle NaN
1244 	 */
1245 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1246 		return make_result(&const_nan);
1247 
1248 	/*
1249 	 * Initialize things and calculate scales
1250 	 */
1251 	init_var(&arg1);
1252 	init_var(&arg2);
1253 	init_var(&result);
1254 	set_var_from_num(num1, &arg1);
1255 	set_var_from_num(num2, &arg2);
1256 
1257 	res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1258 	res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1259 	*global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1260 	*global_rscale = MAX(*global_rscale, res_dscale + 4);
1261 	*global_rscale = MIN(*global_rscale, NUMERIC_MAX_RESULT_SCALE);
1262 
1263 	/*
1264 	 * Call log_var() to compute and return the result
1265 	 */
1266 	power_var(&arg1, &arg2, &result, global_rscale, ex);
1267 
1268 	if ( *ex == No_Error )
1269 		result.dscale = res_dscale;
1270 
1271 	res = make_result(&result);
1272 
1273 	free_var(&result);
1274 	free_var(&arg2);
1275 	free_var(&arg1);
1276 
1277 	return res;
1278 }
1279 
1280 
1281 /* ----------------------------------------------------------------------
1282  *
1283  * Local functions follow
1284  *
1285  * ----------------------------------------------------------------------
1286  */
1287 
1288 #ifdef NUMERIC_DEBUG
1289 
1290 /* ----------
1291  * dump_numeric() - Dump a value in the db storage format for debugging
1292  * ----------
1293  */
1294 static void
dump_numeric(char * str,Numeric num)1295 dump_numeric(char *str, Numeric num)
1296 {
1297 	int			i;
1298 
1299 	printf("%s: NUMERIC w=%d r=%d d=%d ", str, num->n_weight, num->n_rscale,
1300 		   NUMERIC_DSCALE(num));
1301 	switch (NUMERIC_SIGN(num))
1302 	{
1303 		case NUMERIC_POS:
1304 			printf("POS");
1305 			break;
1306 		case NUMERIC_NEG:
1307 			printf("NEG");
1308 			break;
1309 		case NUMERIC_NAN:
1310 			printf("NaN");
1311 			break;
1312 		default:
1313 			printf("SIGN=0x%x", NUMERIC_SIGN(num));
1314 			break;
1315 	}
1316 
1317 	for (i = 0; i < num->varlen - NUMERIC_HDRSZ; i++)
1318 		printf(" %d %d", (num->n_data[i] >> 4) & 0x0f, num->n_data[i] & 0x0f);
1319 	printf("\n");
1320 }
1321 
1322 /* ----------
1323  * dump_var() - Dump a value in the variable format for debugging
1324  * ----------
1325  */
1326 static void
dump_var(char * str,NumericVar * var)1327 dump_var(char *str, NumericVar *var)
1328 {
1329 	int			i;
1330 
1331 	printf("%s: VAR w=%d r=%d d=%d ", str, var->weight, var->rscale,
1332 		   var->dscale);
1333 	switch (var->sign)
1334 	{
1335 		case NUMERIC_POS:
1336 			printf("POS");
1337 			break;
1338 		case NUMERIC_NEG:
1339 			printf("NEG");
1340 			break;
1341 		case NUMERIC_NAN:
1342 			printf("NaN");
1343 			break;
1344 		default:
1345 			printf("SIGN=0x%x", var->sign);
1346 			break;
1347 	}
1348 
1349 	for (i = 0; i < var->ndigits; i++)
1350 		printf(" %d", var->digits[i]);
1351 
1352 	printf("\n");
1353 }
1354 #endif   /* NUMERIC_DEBUG */
1355 
1356 
1357 /* ----------
1358  * alloc_var() -
1359  *
1360  *	Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
1361  * ----------
1362  */
1363 static void
alloc_var(NumericVar * var,int ndigits)1364 alloc_var(NumericVar *var, int ndigits)
1365 {
1366 	digitbuf_free(var->buf);
1367 	var->buf = digitbuf_alloc(ndigits + 1);
1368 	var->buf[0] = 0;
1369 	var->digits = var->buf + 1;
1370 	var->ndigits = ndigits;
1371 }
1372 
1373 /* ----------
1374  * free_var() -
1375  *
1376  *	Return the digit buffer of a variable to the free pool
1377  * ----------
1378  */
1379 static void
free_var(NumericVar * var)1380 free_var(NumericVar *var)
1381 {
1382 	digitbuf_free(var->buf);
1383 	var->buf = NULL;
1384 	var->digits = NULL;
1385 	var->sign = NUMERIC_NAN;
1386 }
1387 
1388 /* ----------
1389  * zero_var() -
1390  *
1391  *	Set a variable to ZERO.
1392  *	Note: rscale and dscale are not touched.
1393  * ----------
1394  */
1395 static void
zero_var(NumericVar * var)1396 zero_var(NumericVar *var)
1397 {
1398 	digitbuf_free(var->buf);
1399 	var->buf = NULL;
1400 	var->digits = NULL;
1401 	var->ndigits = 0;
1402 	var->weight = 0;			/* by convention; doesn't really matter */
1403 	var->sign = NUMERIC_POS;	/* anything but NAN... */
1404 }
1405 
1406 /* ----------
1407  * set_var_from_str()
1408  *
1409  *	Parse a string and put the number into a variable
1410  * ----------
1411  */
1412 static void
set_var_from_str(const char * str,NumericVar * dest,Decimal_Exception * ex)1413 set_var_from_str(const char *str, NumericVar *dest, Decimal_Exception *ex) {
1414 	char	*cp = (char *) str;
1415 	bool	have_dp = FALSE;
1416 	int	i = 0;
1417 	bool	bad_format = FALSE;
1418 
1419 	while (*cp)
1420 	{
1421 		if (!isspace((unsigned char) *cp))
1422 			break;
1423 		cp++;
1424 	}
1425 
1426 	alloc_var(dest, strlen(cp));
1427 	dest->weight = -1;
1428 	dest->dscale = 0;
1429 	dest->sign = NUMERIC_POS;
1430 
1431 	switch (*cp)
1432 	{
1433 		case '+':
1434 			dest->sign = NUMERIC_POS;
1435 			cp++;
1436 			break;
1437 
1438 		case '-':
1439 			dest->sign = NUMERIC_NEG;
1440 			cp++;
1441 			break;
1442 	}
1443 
1444 	if (*cp == '.')
1445 	{
1446 		have_dp = TRUE;
1447 		cp++;
1448 	}
1449 
1450 	if (!isdigit((unsigned char) *cp))
1451 		bad_format = TRUE;			/* Bad format exception */
1452 
1453 	while (*cp)
1454 	{
1455 		if (isdigit((unsigned char) *cp))
1456 		{
1457 			dest->digits[i++] = *cp++ - '0';
1458 			if (!have_dp)
1459 				dest->weight++;
1460 			else
1461 				dest->dscale++;
1462 		}
1463 		else if (*cp == '.')
1464 		{
1465 			if (have_dp)
1466 				bad_format = TRUE;
1467 			have_dp = TRUE;
1468 			cp++;
1469 		}
1470 		else
1471 			break;
1472 	}
1473 	dest->ndigits = i;
1474 
1475 	/* Handle exponent, if any */
1476 	if (*cp == 'e' || *cp == 'E')
1477 	{
1478 		long		exponent;
1479 		char	   *endptr;
1480 
1481 		cp++;
1482 		exponent = strtol(cp, &endptr, 10);
1483 		if (endptr == cp)
1484 			bad_format = TRUE;
1485 		cp = endptr;
1486 		if (exponent > NUMERIC_MAX_PRECISION ||
1487 			exponent < -NUMERIC_MAX_PRECISION)
1488 			bad_format = TRUE;
1489 		dest->weight += (int) exponent;
1490 		dest->dscale -= (int) exponent;
1491 		if (dest->dscale < 0)
1492 			dest->dscale = 0;
1493 	}
1494 
1495 	/* Should be nothing left but spaces */
1496 	while (*cp)
1497 	{
1498 		if (!isspace((unsigned char) *cp))
1499 			bad_format = TRUE;
1500 		cp++;
1501 	}
1502 
1503 	/* Strip any leading zeroes */
1504 	while (dest->ndigits > 0 && *(dest->digits) == 0)
1505 	{
1506 		(dest->digits)++;
1507 		(dest->weight)--;
1508 		(dest->ndigits)--;
1509 	}
1510 	if (dest->ndigits == 0)
1511 		dest->weight = 0;
1512 
1513 	dest->rscale = dest->dscale;
1514 
1515 	if ( bad_format )
1516 		*ex = Numeric_Format;		/* Bad format exception */
1517 }
1518 
1519 /*
1520  * set_var_from_num() -
1521  *
1522  *	Parse back the packed db format into a variable
1523  *
1524  */
1525 static void
set_var_from_num(Numeric num,NumericVar * dest)1526 set_var_from_num(Numeric num, NumericVar *dest)
1527 {
1528 	NumericDigit *digit;
1529 	int			i;
1530 	int			n;
1531 
1532 	n = num->varlen - NUMERIC_HDRSZ;	/* number of digit-pairs in packed
1533 										 * fmt */
1534 
1535 	alloc_var(dest, n * 2);
1536 
1537 	dest->weight = num->n_weight;
1538 	dest->rscale = num->n_rscale;
1539 	dest->dscale = NUMERIC_DSCALE(num);
1540 	dest->sign = NUMERIC_SIGN(num);
1541 
1542 	digit = dest->digits;
1543 
1544 	for (i = 0; i < n; i++)
1545 	{
1546 		unsigned char digitpair = num->n_data[i];
1547 
1548 		*digit++ = (digitpair >> 4) & 0x0f;
1549 		*digit++ = digitpair & 0x0f;
1550 	}
1551 }
1552 
1553 /* ----------
1554  * set_var_from_var() -
1555  *
1556  *	Copy one variable into another
1557  * ----------
1558  */
1559 static void
set_var_from_var(NumericVar * value,NumericVar * dest)1560 set_var_from_var(NumericVar *value, NumericVar *dest)
1561 {
1562 	NumericDigit *newbuf;
1563 
1564 	newbuf = digitbuf_alloc(value->ndigits + 1);
1565 	newbuf[0] = 0;				/* spare digit for rounding */
1566 	memcpy(newbuf + 1, value->digits, value->ndigits);
1567 
1568 	digitbuf_free(dest->buf);
1569 
1570 	memcpy(dest, value, sizeof(NumericVar));
1571 	dest->buf = newbuf;
1572 	dest->digits = newbuf + 1;
1573 }
1574 
1575 /* ----------
1576  * get_str_from_var() -
1577  *
1578  *	Convert a var to text representation (guts of numeric_out).
1579  *	CAUTION: var's contents may be modified by rounding!
1580  *	Caller must have checked for NaN case.
1581  *	Returns a palloc'd string.
1582  * ----------
1583  */
1584 static char *
get_str_from_var(NumericVar * var,int dscale)1585 get_str_from_var(NumericVar *var, int dscale)
1586 {
1587 	char	*str;
1588 	char	*cp;
1589 	int	i;
1590 	int	d;
1591 
1592 	/*
1593 	 * Check if we must round up before printing the value and do so.
1594 	 */
1595 	i = dscale + var->weight + 1;
1596 	if (i >= 0 && var->ndigits > i)	{
1597 		int carry = (var->digits[i] > 4) ? 1 : 0;
1598 
1599 		var->ndigits = i;
1600 
1601 		while (carry)
1602 		{
1603 			carry += var->digits[--i];
1604 			var->digits[i] = carry % 10;
1605 			carry /= 10;
1606 		}
1607 
1608 		if (i < 0)
1609 		{
1610 			Assert(i == -1);	/* better not have added more than 1 digit */
1611 			Assert(var->digits > var->buf);
1612 			var->digits--;
1613 			var->ndigits++;
1614 			var->weight++;
1615 		}
1616 	}
1617 	else
1618 		var->ndigits = MAX(0, MIN(i, var->ndigits));
1619 
1620 	/*
1621 	 * Allocate space for the result
1622 	 */
1623 	str = palloc(MAX(0, dscale) + MAX(0, var->weight) + 4);
1624 	cp = str;
1625 
1626 	/*
1627 	 * Output a dash for negative values
1628 	 */
1629 	if (var->sign == NUMERIC_NEG)
1630 		*cp++ = '-';
1631 
1632 	/*
1633 	 * Output all digits before the decimal point
1634 	 */
1635 	i = MAX(var->weight, 0);
1636 	d = 0;
1637 
1638 	while (i >= 0)
1639 	{
1640 		if (i <= var->weight && d < var->ndigits)
1641 			*cp++ = var->digits[d++] + '0';
1642 		else
1643 			*cp++ = '0';
1644 		i--;
1645 	}
1646 
1647 	/*
1648 	 * If requested, output a decimal point and all the digits that follow
1649 	 * it.
1650 	 */
1651 	if (dscale > 0)
1652 	{
1653 		*cp++ = '.';
1654 		while (i >= -dscale)
1655 		{
1656 			if (i <= var->weight && d < var->ndigits)
1657 				*cp++ = var->digits[d++] + '0';
1658 			else
1659 				*cp++ = '0';
1660 			i--;
1661 		}
1662 	}
1663 
1664 	/*
1665 	 * terminate the string and return it
1666 	 */
1667 	*cp = '\0';
1668 	return str;
1669 }
1670 
1671 Numeric
numeric_nan(void)1672 numeric_nan(void) {
1673 	Numeric num = (Numeric) palloc(NUMERIC_HDRSZ);
1674 
1675 	num->varlen = NUMERIC_HDRSZ;
1676 	num->n_weight = 0;
1677 	num->n_rscale = 0;
1678 	num->n_sign_dscale = NUMERIC_NAN;
1679 
1680 	return num;
1681 }
1682 
1683 /* ----------
1684  * make_result() -
1685  *
1686  *	Create the packed db numeric format in palloc()'d memory from
1687  *	a variable.  The var's rscale determines the number of digits kept.
1688  * ----------
1689  */
1690 static Numeric
make_result(NumericVar * var)1691 make_result(NumericVar *var)
1692 {
1693 	Numeric		result;
1694 	NumericDigit *digit = var->digits;
1695 	int			weight = var->weight;
1696 	int			sign = var->sign;
1697 	int			n;
1698 	int			i,
1699 				j;
1700 
1701 	if (sign == NUMERIC_NAN)
1702 	{
1703 		return numeric_nan();
1704 		return result;
1705 	}
1706 
1707 	n = MAX(0, MIN(var->ndigits, var->weight + var->rscale + 1));
1708 
1709 	/* truncate leading zeroes */
1710 	while (n > 0 && *digit == 0)
1711 	{
1712 		digit++;
1713 		weight--;
1714 		n--;
1715 	}
1716 	/* truncate trailing zeroes */
1717 	while (n > 0 && digit[n - 1] == 0)
1718 		n--;
1719 
1720 	/* If zero result, force to weight=0 and positive sign */
1721 	if (n == 0)
1722 	{
1723 		weight = 0;
1724 		sign = NUMERIC_POS;
1725 	}
1726 
1727 	result = (Numeric) palloc(NUMERIC_HDRSZ + (n + 1) / 2);
1728 	result->varlen = NUMERIC_HDRSZ + (n + 1) / 2;
1729 	result->n_weight = weight;
1730 	result->n_rscale = var->rscale;
1731 	result->n_sign_dscale = sign |
1732 		((uint16) var->dscale & NUMERIC_DSCALE_MASK);
1733 
1734 	i = 0;
1735 	j = 0;
1736 	while (j < n)
1737 	{
1738 		unsigned char digitpair = digit[j++] << 4;
1739 
1740 		if (j < n)
1741 			digitpair |= digit[j++];
1742 		result->n_data[i++] = digitpair;
1743 	}
1744 
1745 	dump_numeric("make_result()", result);
1746 	return result;
1747 }
1748 
1749 /* ----------
1750  * apply_typmod() -
1751  *
1752  *	Do bounds checking and rounding according to the attributes
1753  *	typmod field.
1754  * ----------
1755  */
1756 static void
apply_typmod(NumericVar * var,int precision,int scale,Decimal_Exception * ex)1757 apply_typmod(NumericVar *var, int precision, int scale, Decimal_Exception *ex) {
1758 	int maxweight;
1759 	int i;
1760 
1761 	maxweight = precision - scale;
1762 
1763 	/* Round to target scale */
1764 	i = scale + var->weight + 1;
1765 	if (i >= 0 && var->ndigits > i) {
1766 		int carry = (var->digits[i] > 4) ? 1 : 0;
1767 
1768 		var->ndigits = i;
1769 
1770 		while (carry)
1771 		{
1772 			carry += var->digits[--i];
1773 			var->digits[i] = carry % 10;
1774 			carry /= 10;
1775 		}
1776 
1777 		if (i < 0)
1778 		{
1779 			Assert(i == -1);	/* better not have added more than 1 digit */
1780 			Assert(var->digits > var->buf);
1781 			var->digits--;
1782 			var->ndigits++;
1783 			var->weight++;
1784 		}
1785 	} else
1786 		var->ndigits = MAX(0, MIN(i, var->ndigits));
1787 
1788 	/*
1789 	 * Check for overflow - note we can't do this before rounding, because
1790 	 * rounding could raise the weight.  Also note that the var's weight
1791 	 * could be inflated by leading zeroes, which will be stripped before
1792 	 * storage but perhaps might not have been yet. In any case, we must
1793 	 * recognize a true zero, whose weight doesn't mean anything.
1794 	 */
1795 	if (var->weight >= maxweight) {
1796 		/* Determine true weight; and check for all-zero result */
1797 		int tweight = var->weight;
1798 
1799 		for (i = 0; i < var->ndigits; i++)
1800 		{
1801 			if (var->digits[i])
1802 				break;
1803 			tweight--;
1804 		}
1805 
1806 		if ( tweight >= maxweight && i < var->ndigits )
1807 			*ex = Numeric_Overflow;		/* Overflow exception */
1808 	}
1809 
1810 	if ( *ex == No_Error ) {
1811 		var->rscale = scale;
1812 		var->dscale = scale;
1813 	} else
1814 		nan_var(var);
1815 }
1816 
1817 /* ----------
1818  * cmp_var() -
1819  *
1820  *	Compare two values on variable level
1821  * ----------
1822  */
1823 static int
cmp_var(NumericVar * var1,NumericVar * var2)1824 cmp_var(NumericVar *var1, NumericVar *var2)
1825 {
1826 	if (var1->ndigits == 0)
1827 	{
1828 		if (var2->ndigits == 0)
1829 			return 0;
1830 		if (var2->sign == NUMERIC_NEG)
1831 			return 1;
1832 		return -1;
1833 	}
1834 	if (var2->ndigits == 0)
1835 	{
1836 		if (var1->sign == NUMERIC_POS)
1837 			return 1;
1838 		return -1;
1839 	}
1840 
1841 	if (var1->sign == NUMERIC_POS)
1842 	{
1843 		if (var2->sign == NUMERIC_NEG)
1844 			return 1;
1845 		return cmp_abs(var1, var2);
1846 	}
1847 
1848 	if (var2->sign == NUMERIC_POS)
1849 		return -1;
1850 
1851 	return cmp_abs(var2, var1);
1852 }
1853 
1854 /* ----------
1855  * add_var() -
1856  *
1857  *	Full version of add functionality on variable level (handling signs).
1858  *	result might point to one of the operands too without danger.
1859  * ----------
1860  */
1861 static void
add_var(NumericVar * var1,NumericVar * var2,NumericVar * result)1862 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
1863 {
1864 	/*
1865 	 * Decide on the signs of the two variables what to do
1866 	 */
1867 	if (var1->sign == NUMERIC_POS)
1868 	{
1869 		if (var2->sign == NUMERIC_POS)
1870 		{
1871 			/*
1872 			 * Both are positive result = +(ABS(var1) + ABS(var2))
1873 			 */
1874 			add_abs(var1, var2, result);
1875 			result->sign = NUMERIC_POS;
1876 		}
1877 		else
1878 		{
1879 			/*
1880 			 * var1 is positive, var2 is negative Must compare absolute
1881 			 * values
1882 			 */
1883 			switch (cmp_abs(var1, var2))
1884 			{
1885 				case 0:
1886 					/* ----------
1887 					 * ABS(var1) == ABS(var2)
1888 					 * result = ZERO
1889 					 * ----------
1890 					 */
1891 					zero_var(result);
1892 					result->rscale = MAX(var1->rscale, var2->rscale);
1893 					result->dscale = MAX(var1->dscale, var2->dscale);
1894 					break;
1895 
1896 				case 1:
1897 					/* ----------
1898 					 * ABS(var1) > ABS(var2)
1899 					 * result = +(ABS(var1) - ABS(var2))
1900 					 * ----------
1901 					 */
1902 					sub_abs(var1, var2, result);
1903 					result->sign = NUMERIC_POS;
1904 					break;
1905 
1906 				case -1:
1907 					/* ----------
1908 					 * ABS(var1) < ABS(var2)
1909 					 * result = -(ABS(var2) - ABS(var1))
1910 					 * ----------
1911 					 */
1912 					sub_abs(var2, var1, result);
1913 					result->sign = NUMERIC_NEG;
1914 					break;
1915 			}
1916 		}
1917 	}
1918 	else
1919 	{
1920 		if (var2->sign == NUMERIC_POS)
1921 		{
1922 			/* ----------
1923 			 * var1 is negative, var2 is positive
1924 			 * Must compare absolute values
1925 			 * ----------
1926 			 */
1927 			switch (cmp_abs(var1, var2))
1928 			{
1929 				case 0:
1930 					/* ----------
1931 					 * ABS(var1) == ABS(var2)
1932 					 * result = ZERO
1933 					 * ----------
1934 					 */
1935 					zero_var(result);
1936 					result->rscale = MAX(var1->rscale, var2->rscale);
1937 					result->dscale = MAX(var1->dscale, var2->dscale);
1938 					break;
1939 
1940 				case 1:
1941 					/* ----------
1942 					 * ABS(var1) > ABS(var2)
1943 					 * result = -(ABS(var1) - ABS(var2))
1944 					 * ----------
1945 					 */
1946 					sub_abs(var1, var2, result);
1947 					result->sign = NUMERIC_NEG;
1948 					break;
1949 
1950 				case -1:
1951 					/* ----------
1952 					 * ABS(var1) < ABS(var2)
1953 					 * result = +(ABS(var2) - ABS(var1))
1954 					 * ----------
1955 					 */
1956 					sub_abs(var2, var1, result);
1957 					result->sign = NUMERIC_POS;
1958 					break;
1959 			}
1960 		}
1961 		else
1962 		{
1963 			/* ----------
1964 			 * Both are negative
1965 			 * result = -(ABS(var1) + ABS(var2))
1966 			 * ----------
1967 			 */
1968 			add_abs(var1, var2, result);
1969 			result->sign = NUMERIC_NEG;
1970 		}
1971 	}
1972 }
1973 
1974 /* ----------
1975  * sub_var() -
1976  *
1977  *	Full version of sub functionality on variable level (handling signs).
1978  *	result might point to one of the operands too without danger.
1979  * ----------
1980  */
1981 static void
sub_var(NumericVar * var1,NumericVar * var2,NumericVar * result)1982 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
1983 {
1984 	/*
1985 	 * Decide on the signs of the two variables what to do
1986 	 */
1987 	if (var1->sign == NUMERIC_POS)
1988 	{
1989 		if (var2->sign == NUMERIC_NEG)
1990 		{
1991 			/* ----------
1992 			 * var1 is positive, var2 is negative
1993 			 * result = +(ABS(var1) + ABS(var2))
1994 			 * ----------
1995 			 */
1996 			add_abs(var1, var2, result);
1997 			result->sign = NUMERIC_POS;
1998 		}
1999 		else
2000 		{
2001 			/* ----------
2002 			 * Both are positive
2003 			 * Must compare absolute values
2004 			 * ----------
2005 			 */
2006 			switch (cmp_abs(var1, var2))
2007 			{
2008 				case 0:
2009 					/* ----------
2010 					 * ABS(var1) == ABS(var2)
2011 					 * result = ZERO
2012 					 * ----------
2013 					 */
2014 					zero_var(result);
2015 					result->rscale = MAX(var1->rscale, var2->rscale);
2016 					result->dscale = MAX(var1->dscale, var2->dscale);
2017 					break;
2018 
2019 				case 1:
2020 					/* ----------
2021 					 * ABS(var1) > ABS(var2)
2022 					 * result = +(ABS(var1) - ABS(var2))
2023 					 * ----------
2024 					 */
2025 					sub_abs(var1, var2, result);
2026 					result->sign = NUMERIC_POS;
2027 					break;
2028 
2029 				case -1:
2030 					/* ----------
2031 					 * ABS(var1) < ABS(var2)
2032 					 * result = -(ABS(var2) - ABS(var1))
2033 					 * ----------
2034 					 */
2035 					sub_abs(var2, var1, result);
2036 					result->sign = NUMERIC_NEG;
2037 					break;
2038 			}
2039 		}
2040 	}
2041 	else
2042 	{
2043 		if (var2->sign == NUMERIC_NEG)
2044 		{
2045 			/* ----------
2046 			 * Both are negative
2047 			 * Must compare absolute values
2048 			 * ----------
2049 			 */
2050 			switch (cmp_abs(var1, var2))
2051 			{
2052 				case 0:
2053 					/* ----------
2054 					 * ABS(var1) == ABS(var2)
2055 					 * result = ZERO
2056 					 * ----------
2057 					 */
2058 					zero_var(result);
2059 					result->rscale = MAX(var1->rscale, var2->rscale);
2060 					result->dscale = MAX(var1->dscale, var2->dscale);
2061 					break;
2062 
2063 				case 1:
2064 					/* ----------
2065 					 * ABS(var1) > ABS(var2)
2066 					 * result = -(ABS(var1) - ABS(var2))
2067 					 * ----------
2068 					 */
2069 					sub_abs(var1, var2, result);
2070 					result->sign = NUMERIC_NEG;
2071 					break;
2072 
2073 				case -1:
2074 					/* ----------
2075 					 * ABS(var1) < ABS(var2)
2076 					 * result = +(ABS(var2) - ABS(var1))
2077 					 * ----------
2078 					 */
2079 					sub_abs(var2, var1, result);
2080 					result->sign = NUMERIC_POS;
2081 					break;
2082 			}
2083 		}
2084 		else
2085 		{
2086 			/* ----------
2087 			 * var1 is negative, var2 is positive
2088 			 * result = -(ABS(var1) + ABS(var2))
2089 			 * ----------
2090 			 */
2091 			add_abs(var1, var2, result);
2092 			result->sign = NUMERIC_NEG;
2093 		}
2094 	}
2095 }
2096 
2097 /* ----------
2098  * mul_var() -
2099  *
2100  *	Multiplication on variable level. Product of var1 * var2 is stored
2101  *	in result.
2102  * ----------
2103  */
2104 static void
mul_var(NumericVar * var1,NumericVar * var2,NumericVar * result,int * global_rscale)2105 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int *global_rscale)
2106 {
2107 	NumericDigit *res_buf;
2108 	NumericDigit *res_digits;
2109 	int			res_ndigits;
2110 	int			res_weight;
2111 	int			res_sign;
2112 	int			i,
2113 				ri,
2114 				i1,
2115 				i2;
2116 	long		sum = 0;
2117 
2118 	res_weight = var1->weight + var2->weight + 2;
2119 	res_ndigits = var1->ndigits + var2->ndigits + 1;
2120 	if (var1->sign == var2->sign)
2121 		res_sign = NUMERIC_POS;
2122 	else
2123 		res_sign = NUMERIC_NEG;
2124 
2125 	res_buf = digitbuf_alloc(res_ndigits);
2126 	res_digits = res_buf;
2127 	memset(res_digits, 0, res_ndigits);
2128 
2129 	ri = res_ndigits;
2130 	for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
2131 	{
2132 		sum = 0;
2133 		i = --ri;
2134 
2135 		for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
2136 		{
2137 			sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
2138 			res_digits[i--] = sum % 10;
2139 			sum /= 10;
2140 		}
2141 		res_digits[i] = sum;
2142 	}
2143 
2144 	i = res_weight + *global_rscale + 2;
2145 	if (i >= 0 && i < res_ndigits)
2146 	{
2147 		sum = (res_digits[i] > 4) ? 1 : 0;
2148 		res_ndigits = i;
2149 		i--;
2150 		while (sum)
2151 		{
2152 			sum += res_digits[i];
2153 			res_digits[i--] = sum % 10;
2154 			sum /= 10;
2155 		}
2156 	}
2157 
2158 	while (res_ndigits > 0 && *res_digits == 0)
2159 	{
2160 		res_digits++;
2161 		res_weight--;
2162 		res_ndigits--;
2163 	}
2164 	while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
2165 		res_ndigits--;
2166 
2167 	if (res_ndigits == 0)
2168 	{
2169 		res_sign = NUMERIC_POS;
2170 		res_weight = 0;
2171 	}
2172 
2173 	digitbuf_free(result->buf);
2174 	result->buf = res_buf;
2175 	result->digits = res_digits;
2176 	result->ndigits = res_ndigits;
2177 	result->weight = res_weight;
2178 	result->rscale = *global_rscale;
2179 	result->sign = res_sign;
2180 }
2181 
2182 /* ----------
2183  * div_var() -
2184  *
2185  *	Division on variable level.
2186  * ----------
2187  */
2188 static void
div_var(NumericVar * var1,NumericVar * var2,NumericVar * result,int * global_rscale,Decimal_Exception * ex)2189 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int *global_rscale, Decimal_Exception *ex)
2190 {
2191 	NumericDigit 	*res_digits;
2192 	int		res_ndigits;
2193 	int		res_sign;
2194 	int		res_weight;
2195 	NumericVar	dividend;
2196 	NumericVar	divisor[10];
2197 	int		ndigits_tmp;
2198 	int		weight_tmp;
2199 	int		rscale_tmp;
2200 	int		ri;
2201 	int		i;
2202 	long		guess;
2203 	long		first_have;
2204 	long		first_div;
2205 	int		first_nextdigit;
2206 	int		stat = 0;
2207 
2208 	/*
2209 	 * First of all division by zero check
2210 	 */
2211 	ndigits_tmp = var2->ndigits + 1;
2212 	if (ndigits_tmp == 1) {
2213 		*ex = Divide_By_Zero;
2214 		nan_var(result);
2215 		return;
2216 	}
2217 
2218 	/*
2219 	 * Determine the result sign, weight and number of digits to calculate
2220 	 */
2221 	if (var1->sign == var2->sign)
2222 		res_sign = NUMERIC_POS;
2223 	else
2224 		res_sign = NUMERIC_NEG;
2225 	res_weight = var1->weight - var2->weight + 1;
2226 	res_ndigits = *global_rscale + res_weight;
2227 	if (res_ndigits <= 0)
2228 		res_ndigits = 1;
2229 
2230 	/*
2231 	 * Now result zero check
2232 	 */
2233 	if (var1->ndigits == 0)
2234 	{
2235 		zero_var(result);
2236 		result->rscale = *global_rscale;
2237 		return;
2238 	}
2239 
2240 	/*
2241 	 * Initialize local variables
2242 	 */
2243 	init_var(&dividend);
2244 	for (i = 1; i < 10; i++)
2245 		init_var(&divisor[i]);
2246 
2247 	/*
2248 	 * Make a copy of the divisor which has one leading zero digit
2249 	 */
2250 	divisor[1].ndigits = ndigits_tmp;
2251 	divisor[1].rscale = var2->ndigits;
2252 	divisor[1].sign = NUMERIC_POS;
2253 	divisor[1].buf = digitbuf_alloc(ndigits_tmp);
2254 	divisor[1].digits = divisor[1].buf;
2255 	divisor[1].digits[0] = 0;
2256 	memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
2257 
2258 	/*
2259 	 * Make a copy of the dividend
2260 	 */
2261 	dividend.ndigits = var1->ndigits;
2262 	dividend.weight = 0;
2263 	dividend.rscale = var1->ndigits;
2264 	dividend.sign = NUMERIC_POS;
2265 	dividend.buf = digitbuf_alloc(var1->ndigits);
2266 	dividend.digits = dividend.buf;
2267 	memcpy(dividend.digits, var1->digits, var1->ndigits);
2268 
2269 	/*
2270 	 * Setup the result
2271 	 */
2272 	digitbuf_free(result->buf);
2273 	result->buf = digitbuf_alloc(res_ndigits + 2);
2274 	res_digits = result->buf;
2275 	result->digits = res_digits;
2276 	result->ndigits = res_ndigits;
2277 	result->weight = res_weight;
2278 	result->rscale = *global_rscale;
2279 	result->sign = res_sign;
2280 	res_digits[0] = 0;
2281 
2282 	first_div = divisor[1].digits[1] * 10;
2283 	if (ndigits_tmp > 2)
2284 		first_div += divisor[1].digits[2];
2285 
2286 	first_have = 0;
2287 	first_nextdigit = 0;
2288 
2289 	weight_tmp = 1;
2290 	rscale_tmp = divisor[1].rscale;
2291 
2292 	for (ri = 0; ri <= res_ndigits; ri++)
2293 	{
2294 		first_have = first_have * 10;
2295 		if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
2296 			first_have += dividend.digits[first_nextdigit];
2297 		first_nextdigit++;
2298 
2299 		guess = (first_have * 10) / first_div + 1;
2300 		if (guess > 9)
2301 			guess = 9;
2302 
2303 		while (guess > 0)
2304 		{
2305 			if (divisor[guess].buf == NULL)
2306 			{
2307 				int			i;
2308 				long		sum = 0;
2309 
2310 				memcpy(&divisor[guess], &divisor[1], sizeof(NumericVar));
2311 				divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
2312 				divisor[guess].digits = divisor[guess].buf;
2313 				for (i = divisor[1].ndigits - 1; i >= 0; i--)
2314 				{
2315 					sum += divisor[1].digits[i] * guess;
2316 					divisor[guess].digits[i] = sum % 10;
2317 					sum /= 10;
2318 				}
2319 			}
2320 
2321 			divisor[guess].weight = weight_tmp;
2322 			divisor[guess].rscale = rscale_tmp;
2323 
2324 			stat = cmp_abs(&dividend, &divisor[guess]);
2325 			if (stat >= 0)
2326 				break;
2327 
2328 			guess--;
2329 		}
2330 
2331 		res_digits[ri + 1] = guess;
2332 		if (stat == 0)
2333 		{
2334 			ri++;
2335 			break;
2336 		}
2337 
2338 		weight_tmp--;
2339 		rscale_tmp++;
2340 
2341 		if (guess == 0)
2342 			continue;
2343 
2344 		sub_abs(&dividend, &divisor[guess], &dividend);
2345 
2346 		first_nextdigit = dividend.weight - weight_tmp;
2347 		first_have = 0;
2348 		if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
2349 			first_have = dividend.digits[first_nextdigit];
2350 		first_nextdigit++;
2351 	}
2352 
2353 	result->ndigits = ri + 1;
2354 	if (ri == res_ndigits + 1)
2355 	{
2356 		int			carry = (res_digits[ri] > 4) ? 1 : 0;
2357 
2358 		result->ndigits = ri;
2359 		res_digits[ri] = 0;
2360 
2361 		while (carry && ri > 0)
2362 		{
2363 			carry += res_digits[--ri];
2364 			res_digits[ri] = carry % 10;
2365 			carry /= 10;
2366 		}
2367 	}
2368 
2369 	while (result->ndigits > 0 && *(result->digits) == 0)
2370 	{
2371 		(result->digits)++;
2372 		(result->weight)--;
2373 		(result->ndigits)--;
2374 	}
2375 	while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
2376 		(result->ndigits)--;
2377 	if (result->ndigits == 0)
2378 		result->sign = NUMERIC_POS;
2379 
2380 	/*
2381 	 * Tidy up
2382 	 */
2383 	digitbuf_free(dividend.buf);
2384 	for (i = 1; i < 10; i++)
2385 		digitbuf_free(divisor[i].buf);
2386 }
2387 
2388 
2389 /*
2390  * Default scale selection for division
2391  *
2392  * Returns the appropriate display scale for the division result,
2393  * and sets global_rscale to the result scale to use during div_var.
2394  *
2395  * Note that this must be called before div_var.
2396  */
2397 static int
select_div_scale(NumericVar * var1,NumericVar * var2,int * global_rscale)2398 select_div_scale(NumericVar *var1, NumericVar *var2, int *global_rscale)
2399 {
2400 	int			res_dscale;
2401 	int			res_rscale;
2402 
2403 	/* ----------
2404 	 * The result scale of a division isn't specified in any
2405 	 * SQL standard. For Postgres it is the following (where
2406 	 * SR, DR are the result- and display-scales of the returned
2407 	 * value, S1, D1, S2 and D2 are the scales of the two arguments,
2408 	 * The minimum and maximum scales are compile time options from
2409 	 * numeric.h):
2410 	 *
2411 	 *	DR = MIN(MAX(D1 + D2, MIN_DISPLAY_SCALE), MAX_DISPLAY_SCALE)
2412 	 *	SR = MIN(MAX(MAX(S1 + S2, DR + 4), MIN_RESULT_SCALE), MAX_RESULT_SCALE)
2413 	 *
2414 	 * By default, any result is computed with a minimum of 34 digits
2415 	 * after the decimal point or at least with 4 digits more than
2416 	 * displayed.
2417 	 * ----------
2418 	 */
2419 	res_dscale = var1->dscale + var2->dscale;
2420 	res_dscale = MAX(res_dscale, NUMERIC_MIN_DISPLAY_SCALE);
2421 	res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
2422 
2423 	res_rscale = var1->rscale + var2->rscale;
2424 	res_rscale = MAX(res_rscale, res_dscale + 4);
2425 	res_rscale = MAX(res_rscale, NUMERIC_MIN_RESULT_SCALE);
2426 	res_rscale = MIN(res_rscale, NUMERIC_MAX_RESULT_SCALE);
2427 	*global_rscale = res_rscale;
2428 
2429 	return res_dscale;
2430 }
2431 
2432 /* ----------
2433  * mod_var() -
2434  *
2435  *	Calculate the modulo of two numerics at variable level
2436  * ----------
2437  */
2438 static void
mod_var(NumericVar * var1,NumericVar * var2,NumericVar * result,int * global_rscale,Decimal_Exception * ex)2439 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int *global_rscale, Decimal_Exception *ex)
2440 {
2441 	NumericVar	tmp;
2442 	int			save_global_rscale;
2443 	int			div_dscale;
2444 
2445 	*ex = No_Error;
2446 
2447 	init_var(&tmp);
2448 
2449 	/* ---------
2450 	 * We do this using the equation
2451 	 *		mod(x,y) = x - trunc(x/y)*y
2452 	 * We set global_rscale the same way numeric_div and numeric_mul do
2453 	 * to get the right answer from the equation.  The final result,
2454 	 * however, need not be displayed to more precision than the inputs.
2455 	 * ----------
2456 	 */
2457 	save_global_rscale = *global_rscale;
2458 
2459 	div_dscale = select_div_scale(var1, var2, global_rscale);
2460 
2461 	div_var(var1, var2, &tmp, global_rscale, ex);
2462 	if ( *ex == No_Error ) {
2463 		tmp.dscale = div_dscale;
2464 
2465 		/* do trunc() by forgetting digits to the right of the decimal point */
2466 		tmp.ndigits = MAX(0, MIN(tmp.ndigits, tmp.weight + 1));
2467 
2468 		*global_rscale = var2->rscale + tmp.rscale;
2469 
2470 		mul_var(var2, &tmp, &tmp, global_rscale);
2471 
2472 		sub_var(var1, &tmp, result);
2473 
2474 		result->dscale = MAX(var1->dscale, var2->dscale);
2475 
2476 		*global_rscale = save_global_rscale;
2477 	}
2478 	free_var(&tmp);
2479 }
2480 
2481 /* ----------
2482  * ceil_var() -
2483  *
2484  *	Return the smallest integer greater than or equal to the argument
2485  *	on variable level
2486  * ----------
2487  */
2488 static void
ceil_var(NumericVar * var,NumericVar * result)2489 ceil_var(NumericVar *var, NumericVar *result)
2490 {
2491 	NumericVar	tmp;
2492 
2493 	init_var(&tmp);
2494 	set_var_from_var(var, &tmp);
2495 
2496 	tmp.rscale = 0;
2497 	tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
2498 	if (tmp.sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
2499 		add_var(&tmp, &const_one, &tmp);
2500 
2501 	set_var_from_var(&tmp, result);
2502 	free_var(&tmp);
2503 }
2504 
2505 /* ----------
2506  * floor_var() -
2507  *
2508  *	Return the largest integer equal to or less than the argument
2509  *	on variable level
2510  * ----------
2511  */
2512 static void
floor_var(NumericVar * var,NumericVar * result)2513 floor_var(NumericVar *var, NumericVar *result)
2514 {
2515 	NumericVar	tmp;
2516 
2517 	init_var(&tmp);
2518 	set_var_from_var(var, &tmp);
2519 
2520 	tmp.rscale = 0;
2521 	tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
2522 	if (tmp.sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
2523 		sub_var(&tmp, &const_one, &tmp);
2524 
2525 	set_var_from_var(&tmp, result);
2526 	free_var(&tmp);
2527 }
2528 
2529 /* ----------
2530  * sqrt_var() -
2531  *
2532  *	Compute the square root of x using Newtons algorithm
2533  * ----------
2534  */
2535 static void
sqrt_var(NumericVar * arg,NumericVar * result,int * global_rscale,Decimal_Exception * ex)2536 sqrt_var(NumericVar *arg, NumericVar *result, int *global_rscale, Decimal_Exception *ex)
2537 {
2538 	NumericVar	tmp_arg;
2539 	NumericVar	tmp_val;
2540 	NumericVar	last_val;
2541 	int			res_rscale;
2542 	int			save_global_rscale;
2543 	int			stat;
2544 
2545 	save_global_rscale = *global_rscale;
2546 	*global_rscale += 8;
2547 	res_rscale = *global_rscale;
2548 
2549 	stat = cmp_var(arg, &const_zero);
2550 	if (stat == 0)
2551 	{
2552 		set_var_from_var(&const_zero, result);
2553 		result->rscale = res_rscale;
2554 		result->sign = NUMERIC_POS;
2555 		return;
2556 	}
2557 
2558 	if (stat < 0) {
2559 		*ex = Undefined_Result;
2560 		nan_var(result);
2561 		return;
2562 	}
2563 
2564 	init_var(&tmp_arg);
2565 	init_var(&tmp_val);
2566 	init_var(&last_val);
2567 
2568 	set_var_from_var(arg, &tmp_arg);
2569 	set_var_from_var(result, &last_val);
2570 
2571 	/*
2572 	 * Initialize the result to the first guess
2573 	 */
2574 	digitbuf_free(result->buf);
2575 	result->buf = digitbuf_alloc(1);
2576 	result->digits = result->buf;
2577 	result->digits[0] = tmp_arg.digits[0] / 2;
2578 	if (result->digits[0] == 0)
2579 		result->digits[0] = 1;
2580 	result->ndigits = 1;
2581 	result->weight = tmp_arg.weight / 2;
2582 	result->rscale = res_rscale;
2583 	result->sign = NUMERIC_POS;
2584 
2585 	for (;;)
2586 	{
2587 		div_var(&tmp_arg, result, &tmp_val, global_rscale, ex);
2588 		if ( *ex != No_Error )
2589 			break;
2590 
2591 		add_var(result, &tmp_val, result);
2592 		div_var(result, &const_two, result, global_rscale, ex);
2593 		if ( *ex != No_Error )
2594 			break;
2595 
2596 		if (cmp_var(&last_val, result) == 0)
2597 			break;
2598 		set_var_from_var(result, &last_val);
2599 	}
2600 
2601 	free_var(&last_val);
2602 	free_var(&tmp_val);
2603 	free_var(&tmp_arg);
2604 
2605 	if ( *ex == No_Error ) {
2606 		*global_rscale = save_global_rscale;
2607 		div_var(result, &const_one, result, global_rscale, ex);
2608 	}
2609 
2610 	if ( *ex != No_Error )
2611 		nan_var(result);		/* Set NAN if any exception occurred */
2612 }
2613 
2614 /* ----------
2615  * exp_var() -
2616  *
2617  *	Raise e to the power of x
2618  * ----------
2619  */
2620 static void
exp_var(NumericVar * arg,NumericVar * result,int * global_rscale,Decimal_Exception * ex)2621 exp_var(NumericVar *arg, NumericVar *result,int *global_rscale, Decimal_Exception *ex)
2622 {
2623 	NumericVar	x;
2624 	NumericVar	xpow;
2625 	NumericVar	ifac;
2626 	NumericVar	elem;
2627 	NumericVar	ni;
2628 	int		d;
2629 	int		i;
2630 	int		ndiv2 = 0;
2631 	bool		xneg = FALSE;
2632 	int		save_global_rscale;
2633 
2634 	init_var(&x);
2635 	init_var(&xpow);
2636 	init_var(&ifac);
2637 	init_var(&elem);
2638 	init_var(&ni);
2639 
2640 	set_var_from_var(arg, &x);
2641 
2642 	if (x.sign == NUMERIC_NEG)
2643 	{
2644 		xneg = TRUE;
2645 		x.sign = NUMERIC_POS;
2646 	}
2647 
2648 	save_global_rscale = *global_rscale;
2649 	*global_rscale = 0;
2650 	for (i = x.weight, d = 0; i >= 0; i--, d++)
2651 	{
2652 		*global_rscale *= 10;
2653 		if (d < x.ndigits)
2654 			*global_rscale += x.digits[d];
2655 		if (*global_rscale >= 1000) {
2656 			*ex = Numeric_Overflow;		/* argument for EXP() too big */
2657 			nan_var(result);
2658 			return;
2659 		}
2660 	}
2661 
2662 	*global_rscale = *global_rscale / 2 + save_global_rscale + 8;
2663 
2664 	while (cmp_var(&x, &const_one) > 0)
2665 	{
2666 		ndiv2++;
2667 		(*global_rscale)++;
2668 		div_var(&x, &const_two, &x, global_rscale, ex);
2669 		if ( *ex != No_Error )
2670 			break;
2671 	}
2672 
2673 	if ( *ex == No_Error ) {
2674 		add_var(&const_one, &x, result);
2675 		set_var_from_var(&x, &xpow);
2676 		set_var_from_var(&const_one, &ifac);
2677 		set_var_from_var(&const_one, &ni);
2678 
2679 		for (i = 2;; i++)
2680 		{
2681 			add_var(&ni, &const_one, &ni);
2682 			mul_var(&xpow, &x, &xpow, global_rscale);
2683 			mul_var(&ifac, &ni, &ifac, global_rscale);
2684 			div_var(&xpow, &ifac, &elem, global_rscale, ex);
2685 			if ( *ex != No_Error )
2686 				break;
2687 
2688 			if (elem.ndigits == 0)
2689 				break;
2690 
2691 			add_var(result, &elem, result);
2692 		}
2693 	}
2694 
2695 	if ( *ex == No_Error ) {
2696 
2697 		while (ndiv2-- > 0)
2698 			mul_var(result, result, result, global_rscale);
2699 
2700 		*global_rscale = save_global_rscale;
2701 		if (xneg)
2702 			div_var(&const_one, result, result, global_rscale, ex);
2703 		else
2704 			div_var(result, &const_one, result, global_rscale, ex);
2705 
2706 		if ( *ex == No_Error )
2707 			result->sign = NUMERIC_POS;
2708 	}
2709 
2710 	free_var(&x);
2711 	free_var(&xpow);
2712 	free_var(&ifac);
2713 	free_var(&elem);
2714 	free_var(&ni);
2715 
2716 	if ( *ex != No_Error )
2717 		nan_var(result);
2718 }
2719 
2720 /* ----------
2721  * ln_var() -
2722  *
2723  *	Compute the natural log of x
2724  * ----------
2725  */
2726 static void
ln_var(NumericVar * arg,NumericVar * result,int * global_rscale,Decimal_Exception * ex)2727 ln_var(NumericVar *arg, NumericVar *result, int *global_rscale, Decimal_Exception *ex)
2728 {
2729 	NumericVar	x;
2730 	NumericVar	xx;
2731 	NumericVar	ni;
2732 	NumericVar	elem;
2733 	NumericVar	fact;
2734 	int			i;
2735 	int			save_global_rscale;
2736 
2737 	if (cmp_var(arg, &const_zero) <= 0) {
2738 		/* math error on numeric - cannot compute LN of value <= zero */
2739 		*ex = Numeric_Overflow;
2740 		nan_var(result);
2741 		return;
2742 	}
2743 
2744 	save_global_rscale = *global_rscale;
2745 	*global_rscale += 8;
2746 
2747 	init_var(&x);
2748 	init_var(&xx);
2749 	init_var(&ni);
2750 	init_var(&elem);
2751 	init_var(&fact);
2752 
2753 	set_var_from_var(&const_two, &fact);
2754 	set_var_from_var(arg, &x);
2755 
2756 	while (cmp_var(&x, &const_two) >= 0)
2757 	{
2758 		sqrt_var(&x, &x, global_rscale, ex);
2759 		if ( *ex != No_Error )
2760 			break;
2761 		mul_var(&fact, &const_two, &fact, global_rscale);
2762 	}
2763 
2764 	if ( *ex == No_Error ) {
2765 		set_var_from_str("0.5", &elem, ex);	/* This won't raise exception */
2766 		while (cmp_var(&x, &elem) <= 0)
2767 		{
2768 			sqrt_var(&x, &x, global_rscale, ex);
2769 			if ( *ex != No_Error )
2770 				break;
2771 			mul_var(&fact, &const_two, &fact, global_rscale);
2772 		}
2773 	}
2774 
2775 	if ( *ex == No_Error ) {
2776 		sub_var(&x, &const_one, result);
2777 		add_var(&x, &const_one, &elem);
2778 		div_var(result, &elem, result, global_rscale, ex);
2779 	}
2780 
2781 	if ( *ex == No_Error ) {
2782 		set_var_from_var(result, &xx);
2783 		mul_var(result, result, &x, global_rscale);
2784 
2785 		set_var_from_var(&const_one, &ni);
2786 
2787 		for (i = 2;; i++)
2788 		{
2789 			add_var(&ni, &const_two, &ni);
2790 			mul_var(&xx, &x, &xx, global_rscale);
2791 			div_var(&xx, &ni, &elem, global_rscale, ex);
2792 			if ( *ex != No_Error )
2793 				break;
2794 			if (cmp_var(&elem, &const_zero) == 0)
2795 				break;
2796 
2797 			add_var(result, &elem, result);
2798 		}
2799 	}
2800 
2801 	if ( *ex == No_Error ) {
2802 		*global_rscale = save_global_rscale;
2803 		mul_var(result, &fact, result, global_rscale);
2804 	}
2805 
2806 	free_var(&x);
2807 	free_var(&xx);
2808 	free_var(&ni);
2809 	free_var(&elem);
2810 	free_var(&fact);
2811 
2812 	if ( *ex != No_Error )
2813 		nan_var(result);
2814 }
2815 
2816 /* ----------
2817  * log_var() -
2818  *
2819  *	Compute the logarithm of x in a given base
2820  * ----------
2821  */
2822 static void
log_var(NumericVar * base,NumericVar * num,NumericVar * result,int * global_rscale,Decimal_Exception * ex)2823 log_var(NumericVar *base, NumericVar *num, NumericVar *result, int *global_rscale, Decimal_Exception *ex)
2824 {
2825 	NumericVar	ln_base;
2826 	NumericVar	ln_num;
2827 
2828 	*global_rscale += 8;
2829 
2830 	init_var(&ln_base);
2831 	init_var(&ln_num);
2832 
2833 	ln_var(base, &ln_base, global_rscale, ex);
2834 	if ( *ex == No_Error )
2835 		ln_var(num, &ln_num, global_rscale, ex);
2836 
2837 	if ( *ex == No_Error ) {
2838 		*global_rscale -= 8;
2839 
2840 		div_var(&ln_num, &ln_base, result, global_rscale, ex);
2841 	}
2842 
2843 	free_var(&ln_num);
2844 	free_var(&ln_base);
2845 
2846 	if ( *ex != No_Error )
2847 		nan_var(result);
2848 }
2849 
2850 /* ----------
2851  * power_var() -
2852  *
2853  *	Raise base to the power of exp
2854  * ----------
2855  */
2856 static void
power_var(NumericVar * base,NumericVar * exp,NumericVar * result,int * global_rscale,Decimal_Exception * ex)2857 power_var(NumericVar *base, NumericVar *exp, NumericVar *result, int *global_rscale, Decimal_Exception *ex)
2858 {
2859 	NumericVar	ln_base;
2860 	NumericVar	ln_num;
2861 	int			save_global_rscale;
2862 
2863 	save_global_rscale = *global_rscale;
2864 	*global_rscale += *global_rscale / 3 + 8;
2865 
2866 	init_var(&ln_base);
2867 	init_var(&ln_num);
2868 
2869 	ln_var(base, &ln_base, global_rscale, ex);
2870 
2871 	if ( *ex == No_Error ) {
2872 		mul_var(&ln_base, exp, &ln_num, global_rscale);
2873 		*global_rscale = save_global_rscale;
2874 
2875 		exp_var(&ln_num, result, global_rscale, ex);
2876 	}
2877 
2878 	free_var(&ln_num);
2879 	free_var(&ln_base);
2880 
2881 	if ( *ex != No_Error )
2882 		nan_var(result);
2883 }
2884 
2885 /* ----------------------------------------------------------------------
2886  *
2887  * Following are the lowest level functions that operate unsigned
2888  * on the variable level
2889  *
2890  * ----------------------------------------------------------------------
2891  */
2892 
2893 /* ----------
2894  * cmp_abs() -
2895  *
2896  *	Compare the absolute values of var1 and var2
2897  *	Returns:	-1 for ABS(var1) < ABS(var2)
2898  *				0  for ABS(var1) == ABS(var2)
2899  *				1  for ABS(var1) > ABS(var2)
2900  * ----------
2901  */
2902 static int
cmp_abs(NumericVar * var1,NumericVar * var2)2903 cmp_abs(NumericVar *var1, NumericVar *var2)
2904 {
2905 	int			i1 = 0;
2906 	int			i2 = 0;
2907 	int			w1 = var1->weight;
2908 	int			w2 = var2->weight;
2909 	int			stat;
2910 
2911 	while (w1 > w2 && i1 < var1->ndigits)
2912 	{
2913 		if (var1->digits[i1++] != 0)
2914 			return 1;
2915 		w1--;
2916 	}
2917 	while (w2 > w1 && i2 < var2->ndigits)
2918 	{
2919 		if (var2->digits[i2++] != 0)
2920 			return -1;
2921 		w2--;
2922 	}
2923 
2924 	if (w1 == w2)
2925 	{
2926 		while (i1 < var1->ndigits && i2 < var2->ndigits)
2927 		{
2928 			stat = var1->digits[i1++] - var2->digits[i2++];
2929 			if (stat)
2930 			{
2931 				if (stat > 0)
2932 					return 1;
2933 				return -1;
2934 			}
2935 		}
2936 	}
2937 
2938 	while (i1 < var1->ndigits)
2939 	{
2940 		if (var1->digits[i1++] != 0)
2941 			return 1;
2942 	}
2943 	while (i2 < var2->ndigits)
2944 	{
2945 		if (var2->digits[i2++] != 0)
2946 			return -1;
2947 	}
2948 
2949 	return 0;
2950 }
2951 
2952 /* ----------
2953  * add_abs() -
2954  *
2955  *	Add the absolute values of two variables into result.
2956  *	result might point to one of the operands without danger.
2957  * ----------
2958  */
2959 static void
add_abs(NumericVar * var1,NumericVar * var2,NumericVar * result)2960 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
2961 {
2962 	NumericDigit *res_buf;
2963 	NumericDigit *res_digits;
2964 	int			res_ndigits;
2965 	int			res_weight;
2966 	int			res_rscale;
2967 	int			res_dscale;
2968 	int			i,
2969 				i1,
2970 				i2;
2971 	int			carry = 0;
2972 
2973 	/* copy these values into local vars for speed in inner loop */
2974 	int			var1ndigits = var1->ndigits;
2975 	int			var2ndigits = var2->ndigits;
2976 	NumericDigit *var1digits = var1->digits;
2977 	NumericDigit *var2digits = var2->digits;
2978 
2979 	res_weight = MAX(var1->weight, var2->weight) + 1;
2980 	res_rscale = MAX(var1->rscale, var2->rscale);
2981 	res_dscale = MAX(var1->dscale, var2->dscale);
2982 	res_ndigits = res_rscale + res_weight + 1;
2983 	if (res_ndigits <= 0)
2984 		res_ndigits = 1;
2985 
2986 	res_buf = digitbuf_alloc(res_ndigits);
2987 	res_digits = res_buf;
2988 
2989 	i1 = res_rscale + var1->weight + 1;
2990 	i2 = res_rscale + var2->weight + 1;
2991 	for (i = res_ndigits - 1; i >= 0; i--)
2992 	{
2993 		i1--;
2994 		i2--;
2995 		if (i1 >= 0 && i1 < var1ndigits)
2996 			carry += var1digits[i1];
2997 		if (i2 >= 0 && i2 < var2ndigits)
2998 			carry += var2digits[i2];
2999 
3000 		if (carry >= 10)
3001 		{
3002 			res_digits[i] = carry - 10;
3003 			carry = 1;
3004 		}
3005 		else
3006 		{
3007 			res_digits[i] = carry;
3008 			carry = 0;
3009 		}
3010 	}
3011 
3012 	Assert(carry == 0);			/* else we failed to allow for carry out */
3013 
3014 	while (res_ndigits > 0 && *res_digits == 0)
3015 	{
3016 		res_digits++;
3017 		res_weight--;
3018 		res_ndigits--;
3019 	}
3020 	while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3021 		res_ndigits--;
3022 
3023 	if (res_ndigits == 0)
3024 		res_weight = 0;
3025 
3026 	digitbuf_free(result->buf);
3027 	result->ndigits = res_ndigits;
3028 	result->buf = res_buf;
3029 	result->digits = res_digits;
3030 	result->weight = res_weight;
3031 	result->rscale = res_rscale;
3032 	result->dscale = res_dscale;
3033 }
3034 
3035 /* ----------
3036  * sub_abs() -
3037  *
3038  *	Subtract the absolute value of var2 from the absolute value of var1
3039  *	and store in result. result might point to one of the operands
3040  *	without danger.
3041  *
3042  *	ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
3043  * ----------
3044  */
3045 static void
sub_abs(NumericVar * var1,NumericVar * var2,NumericVar * result)3046 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3047 {
3048 	NumericDigit *res_buf;
3049 	NumericDigit *res_digits;
3050 	int			res_ndigits;
3051 	int			res_weight;
3052 	int			res_rscale;
3053 	int			res_dscale;
3054 	int			i,
3055 				i1,
3056 				i2;
3057 	int			borrow = 0;
3058 
3059 	/* copy these values into local vars for speed in inner loop */
3060 	int			var1ndigits = var1->ndigits;
3061 	int			var2ndigits = var2->ndigits;
3062 	NumericDigit *var1digits = var1->digits;
3063 	NumericDigit *var2digits = var2->digits;
3064 
3065 	res_weight = var1->weight;
3066 	res_rscale = MAX(var1->rscale, var2->rscale);
3067 	res_dscale = MAX(var1->dscale, var2->dscale);
3068 	res_ndigits = res_rscale + res_weight + 1;
3069 	if (res_ndigits <= 0)
3070 		res_ndigits = 1;
3071 
3072 	res_buf = digitbuf_alloc(res_ndigits);
3073 	res_digits = res_buf;
3074 
3075 	i1 = res_rscale + var1->weight + 1;
3076 	i2 = res_rscale + var2->weight + 1;
3077 	for (i = res_ndigits - 1; i >= 0; i--)
3078 	{
3079 		i1--;
3080 		i2--;
3081 		if (i1 >= 0 && i1 < var1ndigits)
3082 			borrow += var1digits[i1];
3083 		if (i2 >= 0 && i2 < var2ndigits)
3084 			borrow -= var2digits[i2];
3085 
3086 		if (borrow < 0)
3087 		{
3088 			res_digits[i] = borrow + 10;
3089 			borrow = -1;
3090 		}
3091 		else
3092 		{
3093 			res_digits[i] = borrow;
3094 			borrow = 0;
3095 		}
3096 	}
3097 
3098 	Assert(borrow == 0);		/* else caller gave us var1 < var2 */
3099 
3100 	while (res_ndigits > 0 && *res_digits == 0)
3101 	{
3102 		res_digits++;
3103 		res_weight--;
3104 		res_ndigits--;
3105 	}
3106 	while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3107 		res_ndigits--;
3108 
3109 	if (res_ndigits == 0)
3110 		res_weight = 0;
3111 
3112 	digitbuf_free(result->buf);
3113 	result->ndigits = res_ndigits;
3114 	result->buf = res_buf;
3115 	result->digits = res_digits;
3116 	result->weight = res_weight;
3117 	result->rscale = res_rscale;
3118 	result->dscale = res_dscale;
3119 }
3120 
3121 
3122