OSDN Git Service

pgindent run. Make it all clean.
[pg-rex/syncrep.git] / src / backend / utils / adt / numeric.c
1 /* ----------
2  * numeric.c
3  *
4  *      An exact numeric data type for the Postgres database system
5  *
6  *      1998 Jan Wieck
7  *
8  * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.38 2001/03/22 03:59:52 momjian Exp $
9  *
10  * ----------
11  */
12
13 #include "postgres.h"
14
15 #include <ctype.h>
16 #include <float.h>
17 #include <math.h>
18 #include <errno.h>
19 #include <sys/types.h>
20
21 #include "utils/array.h"
22 #include "utils/builtins.h"
23 #include "utils/int8.h"
24 #include "utils/numeric.h"
25
26 /* ----------
27  * Uncomment the following to enable compilation of dump_numeric()
28  * and dump_var() and to get a dump of any result produced by make_result().
29  * ----------
30 #define NUMERIC_DEBUG
31  */
32
33
34 /* ----------
35  * Local definitions
36  * ----------
37  */
38 #ifndef MIN
39 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
40 #endif
41 #ifndef MAX
42 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
43 #endif
44
45 #ifndef NAN
46 #define NAN             (0.0/0.0)
47 #endif
48
49
50 /* ----------
51  * Local data types
52  *
53  * Note: the first digit of a NumericVar's value is assumed to be multiplied
54  * by 10 ** weight.  Another way to say it is that there are weight+1 digits
55  * before the decimal point.  It is possible to have weight < 0.
56  *
57  * The value represented by a NumericVar is determined by the sign, weight,
58  * ndigits, and digits[] array.  The rscale and dscale are carried along,
59  * but they are just auxiliary information until rounding is done before
60  * final storage or display.  (Scales are the number of digits wanted
61  * *after* the decimal point.  Scales are always >= 0.)
62  *
63  * buf points at the physical start of the palloc'd digit buffer for the
64  * NumericVar.  digits points at the first digit in actual use (the one
65  * with the specified weight).  We normally leave an unused byte or two
66  * (preset to zeroes) between buf and digits, so that there is room to store
67  * a carry out of the top digit without special pushups.  We just need to
68  * decrement digits (and increment weight) to make room for the carry digit.
69  *
70  * If buf is NULL then the digit buffer isn't actually palloc'd and should
71  * not be freed --- see the constants below for an example.
72  *
73  * NB: All the variable-level functions are written in a style that makes it
74  * possible to give one and the same variable as argument and destination.
75  * This is feasible because the digit buffer is separate from the variable.
76  * ----------
77  */
78 typedef unsigned char NumericDigit;
79
80 typedef struct NumericVar
81 {
82         int                     ndigits;                /* number of digits in digits[] - can be
83                                                                  * 0! */
84         int                     weight;                 /* weight of first digit */
85         int                     rscale;                 /* result scale */
86         int                     dscale;                 /* display scale */
87         int                     sign;                   /* NUMERIC_POS, NUMERIC_NEG, or
88                                                                  * NUMERIC_NAN */
89         NumericDigit *buf;                      /* start of palloc'd space for digits[] */
90         NumericDigit *digits;           /* decimal digits */
91 } NumericVar;
92
93
94 /* ----------
95  * Local data
96  * ----------
97  */
98 static int      global_rscale = NUMERIC_MIN_RESULT_SCALE;
99
100 /* ----------
101  * Some preinitialized variables we need often
102  * ----------
103  */
104 static NumericDigit const_zero_data[1] = {0};
105 static NumericVar const_zero =
106 {0, 0, 0, 0, NUMERIC_POS, NULL, const_zero_data};
107
108 static NumericDigit const_one_data[1] = {1};
109 static NumericVar const_one =
110 {1, 0, 0, 0, NUMERIC_POS, NULL, const_one_data};
111
112 static NumericDigit const_two_data[1] = {2};
113 static NumericVar const_two =
114 {1, 0, 0, 0, NUMERIC_POS, NULL, const_two_data};
115
116 static NumericVar const_nan =
117 {0, 0, 0, 0, NUMERIC_NAN, NULL, NULL};
118
119
120
121 /* ----------
122  * Local functions
123  * ----------
124  */
125
126 #ifdef NUMERIC_DEBUG
127 static void dump_numeric(char *str, Numeric num);
128 static void dump_var(char *str, NumericVar *var);
129
130 #else
131 #define dump_numeric(s,n)
132 #define dump_var(s,v)
133 #endif
134
135 #define digitbuf_alloc(size)  ((NumericDigit *) palloc(size))
136 #define digitbuf_free(buf)      \
137         do { \
138                  if ((buf) != NULL) \
139                          pfree(buf); \
140         } while (0)
141
142 #define init_var(v)             memset(v,0,sizeof(NumericVar))
143 static void alloc_var(NumericVar *var, int ndigits);
144 static void free_var(NumericVar *var);
145 static void zero_var(NumericVar *var);
146
147 static void set_var_from_str(char *str, NumericVar *dest);
148 static void set_var_from_num(Numeric value, NumericVar *dest);
149 static void set_var_from_var(NumericVar *value, NumericVar *dest);
150 static char *get_str_from_var(NumericVar *var, int dscale);
151
152 static Numeric make_result(NumericVar *var);
153
154 static void apply_typmod(NumericVar *var, int32 typmod);
155
156 static int      cmp_var(NumericVar *var1, NumericVar *var2);
157 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
158 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
159 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
160 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
161 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
162 static void ceil_var(NumericVar *var, NumericVar *result);
163 static void floor_var(NumericVar *var, NumericVar *result);
164
165 static void sqrt_var(NumericVar *arg, NumericVar *result);
166 static void exp_var(NumericVar *arg, NumericVar *result);
167 static void ln_var(NumericVar *arg, NumericVar *result);
168 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
169 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
170
171 static int      cmp_abs(NumericVar *var1, NumericVar *var2);
172 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
173 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
174
175
176
177 /* ----------------------------------------------------------------------
178  *
179  * Input-, output- and rounding-functions
180  *
181  * ----------------------------------------------------------------------
182  */
183
184
185 /* ----------
186  * numeric_in() -
187  *
188  *      Input function for numeric data type
189  * ----------
190  */
191 Datum
192 numeric_in(PG_FUNCTION_ARGS)
193 {
194         char       *str = PG_GETARG_CSTRING(0);
195
196 #ifdef NOT_USED
197         Oid                     typelem = PG_GETARG_OID(1);
198
199 #endif
200         int32           typmod = PG_GETARG_INT32(2);
201         NumericVar      value;
202         Numeric         res;
203
204         /* ----------
205          * Check for NaN
206          * ----------
207          */
208         if (strcmp(str, "NaN") == 0)
209                 PG_RETURN_NUMERIC(make_result(&const_nan));
210
211         /* ----------
212          * Use set_var_from_str() to parse the input string
213          * and return it in the packed DB storage format
214          * ----------
215          */
216         init_var(&value);
217         set_var_from_str(str, &value);
218
219         apply_typmod(&value, typmod);
220
221         res = make_result(&value);
222         free_var(&value);
223
224         PG_RETURN_NUMERIC(res);
225 }
226
227
228 /* ----------
229  * numeric_out() -
230  *
231  *      Output function for numeric data type
232  * ----------
233  */
234 Datum
235 numeric_out(PG_FUNCTION_ARGS)
236 {
237         Numeric         num = PG_GETARG_NUMERIC(0);
238         NumericVar      x;
239         char       *str;
240
241         /* ----------
242          * Handle NaN
243          * ----------
244          */
245         if (NUMERIC_IS_NAN(num))
246                 PG_RETURN_CSTRING(pstrdup("NaN"));
247
248         /* ----------
249          * Get the number in the variable format.
250          *
251          * Even if we didn't need to change format, we'd still need to copy
252          * the value to have a modifiable copy for rounding.  set_var_from_num()
253          * also guarantees there is extra digit space in case we produce a
254          * carry out from rounding.
255          * ----------
256          */
257         init_var(&x);
258         set_var_from_num(num, &x);
259
260         str = get_str_from_var(&x, x.dscale);
261
262         free_var(&x);
263
264         PG_RETURN_CSTRING(str);
265 }
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 Datum
277 numeric(PG_FUNCTION_ARGS)
278 {
279         Numeric         num = PG_GETARG_NUMERIC(0);
280         int32           typmod = PG_GETARG_INT32(1);
281         Numeric         new;
282         int32           tmp_typmod;
283         int                     precision;
284         int                     scale;
285         int                     maxweight;
286         NumericVar      var;
287
288         /* ----------
289          * Handle NaN
290          * ----------
291          */
292         if (NUMERIC_IS_NAN(num))
293                 PG_RETURN_NUMERIC(make_result(&const_nan));
294
295         /* ----------
296          * If the value isn't a valid type modifier, simply return a
297          * copy of the input value
298          * ----------
299          */
300         if (typmod < (int32) (VARHDRSZ))
301         {
302                 new = (Numeric) palloc(num->varlen);
303                 memcpy(new, num, num->varlen);
304                 PG_RETURN_NUMERIC(new);
305         }
306
307         /* ----------
308          * Get the precision and scale out of the typmod value
309          * ----------
310          */
311         tmp_typmod = typmod - VARHDRSZ;
312         precision = (tmp_typmod >> 16) & 0xffff;
313         scale = tmp_typmod & 0xffff;
314         maxweight = precision - scale;
315
316         /* ----------
317          * If the number is in bounds and due to the present result scale
318          * no rounding could be necessary, just make a copy of the input
319          * and modify its scale fields.
320          * ----------
321          */
322         if (num->n_weight < maxweight && scale >= num->n_rscale)
323         {
324                 new = (Numeric) palloc(num->varlen);
325                 memcpy(new, num, num->varlen);
326                 new->n_rscale = scale;
327                 new->n_sign_dscale = NUMERIC_SIGN(new) |
328                         ((uint16) scale & NUMERIC_DSCALE_MASK);
329                 PG_RETURN_NUMERIC(new);
330         }
331
332         /* ----------
333          * We really need to fiddle with things - unpack the number into
334          * a variable and let apply_typmod() do it.
335          * ----------
336          */
337         init_var(&var);
338
339         set_var_from_num(num, &var);
340         apply_typmod(&var, typmod);
341         new = make_result(&var);
342
343         free_var(&var);
344
345         PG_RETURN_NUMERIC(new);
346 }
347
348
349 /* ----------------------------------------------------------------------
350  *
351  * Sign manipulation, rounding and the like
352  *
353  * ----------------------------------------------------------------------
354  */
355
356 Datum
357 numeric_abs(PG_FUNCTION_ARGS)
358 {
359         Numeric         num = PG_GETARG_NUMERIC(0);
360         Numeric         res;
361
362         /* ----------
363          * Handle NaN
364          * ----------
365          */
366         if (NUMERIC_IS_NAN(num))
367                 PG_RETURN_NUMERIC(make_result(&const_nan));
368
369         /* ----------
370          * Do it the easy way directly on the packed format
371          * ----------
372          */
373         res = (Numeric) palloc(num->varlen);
374         memcpy(res, num, num->varlen);
375
376         res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
377
378         PG_RETURN_NUMERIC(res);
379 }
380
381
382 Datum
383 numeric_uminus(PG_FUNCTION_ARGS)
384 {
385         Numeric         num = PG_GETARG_NUMERIC(0);
386         Numeric         res;
387
388         /* ----------
389          * Handle NaN
390          * ----------
391          */
392         if (NUMERIC_IS_NAN(num))
393                 PG_RETURN_NUMERIC(make_result(&const_nan));
394
395         /* ----------
396          * Do it the easy way directly on the packed format
397          * ----------
398          */
399         res = (Numeric) palloc(num->varlen);
400         memcpy(res, num, num->varlen);
401
402         /* ----------
403          * The packed format is known to be totally zero digit trimmed
404          * always. So we can identify a ZERO by the fact that there
405          * are no digits at all.  Do nothing to a zero.
406          * ----------
407          */
408         if (num->varlen != NUMERIC_HDRSZ)
409         {
410                 /* Else, flip the sign */
411                 if (NUMERIC_SIGN(num) == NUMERIC_POS)
412                         res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
413                 else
414                         res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
415         }
416
417         PG_RETURN_NUMERIC(res);
418 }
419
420
421 Datum
422 numeric_sign(PG_FUNCTION_ARGS)
423 {
424         Numeric         num = PG_GETARG_NUMERIC(0);
425         Numeric         res;
426         NumericVar      result;
427
428         /* ----------
429          * Handle NaN
430          * ----------
431          */
432         if (NUMERIC_IS_NAN(num))
433                 PG_RETURN_NUMERIC(make_result(&const_nan));
434
435         init_var(&result);
436
437         /* ----------
438          * The packed format is known to be totally zero digit trimmed
439          * always. So we can identify a ZERO by the fact that there
440          * are no digits at all.
441          * ----------
442          */
443         if (num->varlen == NUMERIC_HDRSZ)
444                 set_var_from_var(&const_zero, &result);
445         else
446         {
447                 /* ----------
448                  * And if there are some, we return a copy of ONE
449                  * with the sign of our argument
450                  * ----------
451                  */
452                 set_var_from_var(&const_one, &result);
453                 result.sign = NUMERIC_SIGN(num);
454         }
455
456         res = make_result(&result);
457         free_var(&result);
458
459         PG_RETURN_NUMERIC(res);
460 }
461
462
463 /* ----------
464  * numeric_round() -
465  *
466  *      Round a value to have 'scale' digits after the decimal point.
467  *      We allow negative 'scale', implying rounding before the decimal
468  *      point --- Oracle interprets rounding that way.
469  * ----------
470  */
471 Datum
472 numeric_round(PG_FUNCTION_ARGS)
473 {
474         Numeric         num = PG_GETARG_NUMERIC(0);
475         int32           scale = PG_GETARG_INT32(1);
476         Numeric         res;
477         NumericVar      arg;
478         int                     i;
479
480         /* ----------
481          * Handle NaN
482          * ----------
483          */
484         if (NUMERIC_IS_NAN(num))
485                 PG_RETURN_NUMERIC(make_result(&const_nan));
486
487         /* ----------
488          * Limit the scale value to avoid possible overflow in calculations below.
489          * ----------
490          */
491         scale = MIN(NUMERIC_MAX_RESULT_SCALE,
492                                 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
493
494         /* ----------
495          * Unpack the argument and round it at the proper digit position
496          * ----------
497          */
498         init_var(&arg);
499         set_var_from_num(num, &arg);
500
501         i = arg.weight + scale + 1;
502
503         if (i < arg.ndigits)
504         {
505
506                 /*
507                  * If i = 0, the value loses all digits, but could round up if its
508                  * first digit is more than 4.  If i < 0 the result must be 0.
509                  */
510                 if (i < 0)
511                         arg.ndigits = 0;
512                 else
513                 {
514                         int                     carry = (arg.digits[i] > 4) ? 1 : 0;
515
516                         arg.ndigits = i;
517
518                         while (carry)
519                         {
520                                 carry += arg.digits[--i];
521                                 arg.digits[i] = carry % 10;
522                                 carry /= 10;
523                         }
524
525                         if (i < 0)
526                         {
527                                 Assert(i == -1);/* better not have added more than 1 digit */
528                                 Assert(arg.digits > arg.buf);
529                                 arg.digits--;
530                                 arg.ndigits++;
531                                 arg.weight++;
532                         }
533                 }
534         }
535
536         /* ----------
537          * Set result's scale to something reasonable.
538          * ----------
539          */
540         scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
541         arg.rscale = scale;
542         arg.dscale = scale;
543
544         /* ----------
545          * Return the rounded result
546          * ----------
547          */
548         res = make_result(&arg);
549
550         free_var(&arg);
551         PG_RETURN_NUMERIC(res);
552 }
553
554
555 /* ----------
556  * numeric_trunc() -
557  *
558  *      Truncate a value to have 'scale' digits after the decimal point.
559  *      We allow negative 'scale', implying a truncation before the decimal
560  *      point --- Oracle interprets truncation that way.
561  * ----------
562  */
563 Datum
564 numeric_trunc(PG_FUNCTION_ARGS)
565 {
566         Numeric         num = PG_GETARG_NUMERIC(0);
567         int32           scale = PG_GETARG_INT32(1);
568         Numeric         res;
569         NumericVar      arg;
570
571         /* ----------
572          * Handle NaN
573          * ----------
574          */
575         if (NUMERIC_IS_NAN(num))
576                 PG_RETURN_NUMERIC(make_result(&const_nan));
577
578         /* ----------
579          * Limit the scale value to avoid possible overflow in calculations below.
580          * ----------
581          */
582         scale = MIN(NUMERIC_MAX_RESULT_SCALE,
583                                 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
584
585         /* ----------
586          * Unpack the argument and truncate it at the proper digit position
587          * ----------
588          */
589         init_var(&arg);
590         set_var_from_num(num, &arg);
591
592         arg.ndigits = MIN(arg.ndigits, MAX(0, arg.weight + scale + 1));
593
594         /* ----------
595          * Set result's scale to something reasonable.
596          * ----------
597          */
598         scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
599         arg.rscale = scale;
600         arg.dscale = scale;
601
602         /* ----------
603          * Return the truncated result
604          * ----------
605          */
606         res = make_result(&arg);
607
608         free_var(&arg);
609         PG_RETURN_NUMERIC(res);
610 }
611
612
613 /* ----------
614  * numeric_ceil() -
615  *
616  *      Return the smallest integer greater than or equal to the argument
617  * ----------
618  */
619 Datum
620 numeric_ceil(PG_FUNCTION_ARGS)
621 {
622         Numeric         num = PG_GETARG_NUMERIC(0);
623         Numeric         res;
624         NumericVar      result;
625
626         if (NUMERIC_IS_NAN(num))
627                 PG_RETURN_NUMERIC(make_result(&const_nan));
628
629         init_var(&result);
630
631         set_var_from_num(num, &result);
632         ceil_var(&result, &result);
633
634         result.dscale = 0;
635
636         res = make_result(&result);
637         free_var(&result);
638
639         PG_RETURN_NUMERIC(res);
640 }
641
642
643 /* ----------
644  * numeric_floor() -
645  *
646  *      Return the largest integer equal to or less than the argument
647  * ----------
648  */
649 Datum
650 numeric_floor(PG_FUNCTION_ARGS)
651 {
652         Numeric         num = PG_GETARG_NUMERIC(0);
653         Numeric         res;
654         NumericVar      result;
655
656         if (NUMERIC_IS_NAN(num))
657                 PG_RETURN_NUMERIC(make_result(&const_nan));
658
659         init_var(&result);
660
661         set_var_from_num(num, &result);
662         floor_var(&result, &result);
663
664         result.dscale = 0;
665
666         res = make_result(&result);
667         free_var(&result);
668
669         PG_RETURN_NUMERIC(res);
670 }
671
672
673 /* ----------------------------------------------------------------------
674  *
675  * Comparison functions
676  *
677  * Note: btree indexes need these routines not to leak memory; therefore,
678  * be careful to free working copies of toasted datums.  Most places don't
679  * need to be so careful.
680  * ----------------------------------------------------------------------
681  */
682
683
684 Datum
685 numeric_cmp(PG_FUNCTION_ARGS)
686 {
687         Numeric         num1 = PG_GETARG_NUMERIC(0);
688         Numeric         num2 = PG_GETARG_NUMERIC(1);
689         int                     result;
690
691         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
692                 result = 0;
693         else
694         {
695                 NumericVar      arg1;
696                 NumericVar      arg2;
697
698                 init_var(&arg1);
699                 init_var(&arg2);
700
701                 set_var_from_num(num1, &arg1);
702                 set_var_from_num(num2, &arg2);
703
704                 result = cmp_var(&arg1, &arg2);
705
706                 free_var(&arg1);
707                 free_var(&arg2);
708         }
709
710         PG_FREE_IF_COPY(num1, 0);
711         PG_FREE_IF_COPY(num2, 1);
712
713         PG_RETURN_INT32(result);
714 }
715
716
717 Datum
718 numeric_eq(PG_FUNCTION_ARGS)
719 {
720         Numeric         num1 = PG_GETARG_NUMERIC(0);
721         Numeric         num2 = PG_GETARG_NUMERIC(1);
722         bool            result;
723
724         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
725                 result = false;
726         else
727         {
728                 NumericVar      arg1;
729                 NumericVar      arg2;
730
731                 init_var(&arg1);
732                 init_var(&arg2);
733
734                 set_var_from_num(num1, &arg1);
735                 set_var_from_num(num2, &arg2);
736
737                 result = cmp_var(&arg1, &arg2) == 0;
738
739                 free_var(&arg1);
740                 free_var(&arg2);
741         }
742
743         PG_FREE_IF_COPY(num1, 0);
744         PG_FREE_IF_COPY(num2, 1);
745
746         PG_RETURN_BOOL(result);
747 }
748
749 Datum
750 numeric_ne(PG_FUNCTION_ARGS)
751 {
752         Numeric         num1 = PG_GETARG_NUMERIC(0);
753         Numeric         num2 = PG_GETARG_NUMERIC(1);
754         bool            result;
755
756         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
757                 result = false;
758         else
759         {
760                 NumericVar      arg1;
761                 NumericVar      arg2;
762
763                 init_var(&arg1);
764                 init_var(&arg2);
765
766                 set_var_from_num(num1, &arg1);
767                 set_var_from_num(num2, &arg2);
768
769                 result = cmp_var(&arg1, &arg2) != 0;
770
771                 free_var(&arg1);
772                 free_var(&arg2);
773         }
774
775         PG_FREE_IF_COPY(num1, 0);
776         PG_FREE_IF_COPY(num2, 1);
777
778         PG_RETURN_BOOL(result);
779 }
780
781 Datum
782 numeric_gt(PG_FUNCTION_ARGS)
783 {
784         Numeric         num1 = PG_GETARG_NUMERIC(0);
785         Numeric         num2 = PG_GETARG_NUMERIC(1);
786         bool            result;
787
788         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
789                 result = false;
790         else
791         {
792                 NumericVar      arg1;
793                 NumericVar      arg2;
794
795                 init_var(&arg1);
796                 init_var(&arg2);
797
798                 set_var_from_num(num1, &arg1);
799                 set_var_from_num(num2, &arg2);
800
801                 result = cmp_var(&arg1, &arg2) > 0;
802
803                 free_var(&arg1);
804                 free_var(&arg2);
805         }
806
807         PG_FREE_IF_COPY(num1, 0);
808         PG_FREE_IF_COPY(num2, 1);
809
810         PG_RETURN_BOOL(result);
811 }
812
813 Datum
814 numeric_ge(PG_FUNCTION_ARGS)
815 {
816         Numeric         num1 = PG_GETARG_NUMERIC(0);
817         Numeric         num2 = PG_GETARG_NUMERIC(1);
818         bool            result;
819
820         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
821                 result = false;
822         else
823         {
824                 NumericVar      arg1;
825                 NumericVar      arg2;
826
827                 init_var(&arg1);
828                 init_var(&arg2);
829
830                 set_var_from_num(num1, &arg1);
831                 set_var_from_num(num2, &arg2);
832
833                 result = cmp_var(&arg1, &arg2) >= 0;
834
835                 free_var(&arg1);
836                 free_var(&arg2);
837         }
838
839         PG_FREE_IF_COPY(num1, 0);
840         PG_FREE_IF_COPY(num2, 1);
841
842         PG_RETURN_BOOL(result);
843 }
844
845 Datum
846 numeric_lt(PG_FUNCTION_ARGS)
847 {
848         Numeric         num1 = PG_GETARG_NUMERIC(0);
849         Numeric         num2 = PG_GETARG_NUMERIC(1);
850         bool            result;
851
852         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
853                 result = false;
854         else
855         {
856                 NumericVar      arg1;
857                 NumericVar      arg2;
858
859                 init_var(&arg1);
860                 init_var(&arg2);
861
862                 set_var_from_num(num1, &arg1);
863                 set_var_from_num(num2, &arg2);
864
865                 result = cmp_var(&arg1, &arg2) < 0;
866
867                 free_var(&arg1);
868                 free_var(&arg2);
869         }
870
871         PG_FREE_IF_COPY(num1, 0);
872         PG_FREE_IF_COPY(num2, 1);
873
874         PG_RETURN_BOOL(result);
875 }
876
877 Datum
878 numeric_le(PG_FUNCTION_ARGS)
879 {
880         Numeric         num1 = PG_GETARG_NUMERIC(0);
881         Numeric         num2 = PG_GETARG_NUMERIC(1);
882         bool            result;
883
884         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
885                 result = false;
886         else
887         {
888                 NumericVar      arg1;
889                 NumericVar      arg2;
890
891                 init_var(&arg1);
892                 init_var(&arg2);
893
894                 set_var_from_num(num1, &arg1);
895                 set_var_from_num(num2, &arg2);
896
897                 result = cmp_var(&arg1, &arg2) <= 0;
898
899                 free_var(&arg1);
900                 free_var(&arg2);
901         }
902
903         PG_FREE_IF_COPY(num1, 0);
904         PG_FREE_IF_COPY(num2, 1);
905
906         PG_RETURN_BOOL(result);
907 }
908
909
910 /* ----------------------------------------------------------------------
911  *
912  * Arithmetic base functions
913  *
914  * ----------------------------------------------------------------------
915  */
916
917
918 /* ----------
919  * numeric_add() -
920  *
921  *      Add two numerics
922  * ----------
923  */
924 Datum
925 numeric_add(PG_FUNCTION_ARGS)
926 {
927         Numeric         num1 = PG_GETARG_NUMERIC(0);
928         Numeric         num2 = PG_GETARG_NUMERIC(1);
929         NumericVar      arg1;
930         NumericVar      arg2;
931         NumericVar      result;
932         Numeric         res;
933
934         /* ----------
935          * Handle NaN
936          * ----------
937          */
938         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
939                 PG_RETURN_NUMERIC(make_result(&const_nan));
940
941         /* ----------
942          * Unpack the values, let add_var() compute the result
943          * and return it. The internals of add_var() will automatically
944          * set the correct result and display scales in the result.
945          * ----------
946          */
947         init_var(&arg1);
948         init_var(&arg2);
949         init_var(&result);
950
951         set_var_from_num(num1, &arg1);
952         set_var_from_num(num2, &arg2);
953
954         add_var(&arg1, &arg2, &result);
955         res = make_result(&result);
956
957         free_var(&arg1);
958         free_var(&arg2);
959         free_var(&result);
960
961         PG_RETURN_NUMERIC(res);
962 }
963
964
965 /* ----------
966  * numeric_sub() -
967  *
968  *      Subtract one numeric from another
969  * ----------
970  */
971 Datum
972 numeric_sub(PG_FUNCTION_ARGS)
973 {
974         Numeric         num1 = PG_GETARG_NUMERIC(0);
975         Numeric         num2 = PG_GETARG_NUMERIC(1);
976         NumericVar      arg1;
977         NumericVar      arg2;
978         NumericVar      result;
979         Numeric         res;
980
981         /* ----------
982          * Handle NaN
983          * ----------
984          */
985         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
986                 PG_RETURN_NUMERIC(make_result(&const_nan));
987
988         /* ----------
989          * Unpack the two arguments, let sub_var() compute the
990          * result and return it.
991          * ----------
992          */
993         init_var(&arg1);
994         init_var(&arg2);
995         init_var(&result);
996
997         set_var_from_num(num1, &arg1);
998         set_var_from_num(num2, &arg2);
999
1000         sub_var(&arg1, &arg2, &result);
1001         res = make_result(&result);
1002
1003         free_var(&arg1);
1004         free_var(&arg2);
1005         free_var(&result);
1006
1007         PG_RETURN_NUMERIC(res);
1008 }
1009
1010
1011 /* ----------
1012  * numeric_mul() -
1013  *
1014  *      Calculate the product of two numerics
1015  * ----------
1016  */
1017 Datum
1018 numeric_mul(PG_FUNCTION_ARGS)
1019 {
1020         Numeric         num1 = PG_GETARG_NUMERIC(0);
1021         Numeric         num2 = PG_GETARG_NUMERIC(1);
1022         NumericVar      arg1;
1023         NumericVar      arg2;
1024         NumericVar      result;
1025         Numeric         res;
1026
1027         /* ----------
1028          * Handle NaN
1029          * ----------
1030          */
1031         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1032                 PG_RETURN_NUMERIC(make_result(&const_nan));
1033
1034         /* ----------
1035          * Unpack the arguments, let mul_var() compute the result
1036          * and return it. Unlike add_var() and sub_var(), mul_var()
1037          * will round the result to the scale stored in global_rscale.
1038          * In the case of numeric_mul(), which is invoked for the *
1039          * operator on numerics, we set it to the exact representation
1040          * for the product (rscale = sum(rscale of arg1, rscale of arg2)
1041          * and the same for the dscale).
1042          * ----------
1043          */
1044         init_var(&arg1);
1045         init_var(&arg2);
1046         init_var(&result);
1047
1048         set_var_from_num(num1, &arg1);
1049         set_var_from_num(num2, &arg2);
1050
1051         global_rscale = arg1.rscale + arg2.rscale;
1052
1053         mul_var(&arg1, &arg2, &result);
1054
1055         result.dscale = arg1.dscale + arg2.dscale;
1056
1057         res = make_result(&result);
1058
1059         free_var(&arg1);
1060         free_var(&arg2);
1061         free_var(&result);
1062
1063         PG_RETURN_NUMERIC(res);
1064 }
1065
1066
1067 /* ----------
1068  * numeric_div() -
1069  *
1070  *      Divide one numeric into another
1071  * ----------
1072  */
1073 Datum
1074 numeric_div(PG_FUNCTION_ARGS)
1075 {
1076         Numeric         num1 = PG_GETARG_NUMERIC(0);
1077         Numeric         num2 = PG_GETARG_NUMERIC(1);
1078         NumericVar      arg1;
1079         NumericVar      arg2;
1080         NumericVar      result;
1081         Numeric         res;
1082         int                     res_dscale;
1083
1084         /* ----------
1085          * Handle NaN
1086          * ----------
1087          */
1088         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1089                 PG_RETURN_NUMERIC(make_result(&const_nan));
1090
1091         /* ----------
1092          * Unpack the arguments
1093          * ----------
1094          */
1095         init_var(&arg1);
1096         init_var(&arg2);
1097         init_var(&result);
1098
1099         set_var_from_num(num1, &arg1);
1100         set_var_from_num(num2, &arg2);
1101
1102         /* ----------
1103          * The result scale of a division isn't specified in any
1104          * SQL standard. For Postgres it is the following (where
1105          * SR, DR are the result- and display-scales of the returned
1106          * value, S1, D1, S2 and D2 are the scales of the two arguments,
1107          * The minimum and maximum scales are compile time options from
1108          * numeric.h):
1109          *
1110          *      DR = MIN(MAX(D1 + D2, MIN_DISPLAY_SCALE), MAX_DISPLAY_SCALE)
1111          *      SR = MIN(MAX(MAX(S1 + S2, MIN_RESULT_SCALE), DR + 4), MAX_RESULT_SCALE)
1112          *
1113          * By default, any result is computed with a minimum of 34 digits
1114          * after the decimal point or at least with 4 digits more than
1115          * displayed.
1116          * ----------
1117          */
1118         res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1119         res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1120         global_rscale = MAX(arg1.rscale + arg2.rscale,
1121                                                 NUMERIC_MIN_RESULT_SCALE);
1122         global_rscale = MAX(global_rscale, res_dscale + 4);
1123         global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1124
1125         /* ----------
1126          * Do the divide, set the display scale and return the result
1127          * ----------
1128          */
1129         div_var(&arg1, &arg2, &result);
1130
1131         result.dscale = res_dscale;
1132
1133         res = make_result(&result);
1134
1135         free_var(&arg1);
1136         free_var(&arg2);
1137         free_var(&result);
1138
1139         PG_RETURN_NUMERIC(res);
1140 }
1141
1142
1143 /* ----------
1144  * numeric_mod() -
1145  *
1146  *      Calculate the modulo of two numerics
1147  * ----------
1148  */
1149 Datum
1150 numeric_mod(PG_FUNCTION_ARGS)
1151 {
1152         Numeric         num1 = PG_GETARG_NUMERIC(0);
1153         Numeric         num2 = PG_GETARG_NUMERIC(1);
1154         Numeric         res;
1155         NumericVar      arg1;
1156         NumericVar      arg2;
1157         NumericVar      result;
1158
1159         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1160                 PG_RETURN_NUMERIC(make_result(&const_nan));
1161
1162         init_var(&arg1);
1163         init_var(&arg2);
1164         init_var(&result);
1165
1166         set_var_from_num(num1, &arg1);
1167         set_var_from_num(num2, &arg2);
1168
1169         mod_var(&arg1, &arg2, &result);
1170
1171         result.dscale = result.rscale;
1172         res = make_result(&result);
1173
1174         free_var(&result);
1175         free_var(&arg2);
1176         free_var(&arg1);
1177
1178         PG_RETURN_NUMERIC(res);
1179 }
1180
1181
1182 /* ----------
1183  * numeric_inc() -
1184  *
1185  *      Increment a number by one
1186  * ----------
1187  */
1188 Datum
1189 numeric_inc(PG_FUNCTION_ARGS)
1190 {
1191         Numeric         num = PG_GETARG_NUMERIC(0);
1192         NumericVar      arg;
1193         Numeric         res;
1194
1195         /* ----------
1196          * Handle NaN
1197          * ----------
1198          */
1199         if (NUMERIC_IS_NAN(num))
1200                 PG_RETURN_NUMERIC(make_result(&const_nan));
1201
1202         /* ----------
1203          * Compute the result and return it
1204          * ----------
1205          */
1206         init_var(&arg);
1207
1208         set_var_from_num(num, &arg);
1209
1210         add_var(&arg, &const_one, &arg);
1211         res = make_result(&arg);
1212
1213         free_var(&arg);
1214
1215         PG_RETURN_NUMERIC(res);
1216 }
1217
1218
1219 /* ----------
1220  * numeric_smaller() -
1221  *
1222  *      Return the smaller of two numbers
1223  * ----------
1224  */
1225 Datum
1226 numeric_smaller(PG_FUNCTION_ARGS)
1227 {
1228         Numeric         num1 = PG_GETARG_NUMERIC(0);
1229         Numeric         num2 = PG_GETARG_NUMERIC(1);
1230         NumericVar      arg1;
1231         NumericVar      arg2;
1232         Numeric         res;
1233
1234         /* ----------
1235          * Handle NaN
1236          * ----------
1237          */
1238         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1239                 PG_RETURN_NUMERIC(make_result(&const_nan));
1240
1241         /* ----------
1242          * Unpack the values, and decide which is the smaller one
1243          * ----------
1244          */
1245         init_var(&arg1);
1246         init_var(&arg2);
1247
1248         set_var_from_num(num1, &arg1);
1249         set_var_from_num(num2, &arg2);
1250
1251         if (cmp_var(&arg1, &arg2) <= 0)
1252                 res = make_result(&arg1);
1253         else
1254                 res = make_result(&arg2);
1255
1256         free_var(&arg1);
1257         free_var(&arg2);
1258
1259         PG_RETURN_NUMERIC(res);
1260 }
1261
1262
1263 /* ----------
1264  * numeric_larger() -
1265  *
1266  *      Return the larger of two numbers
1267  * ----------
1268  */
1269 Datum
1270 numeric_larger(PG_FUNCTION_ARGS)
1271 {
1272         Numeric         num1 = PG_GETARG_NUMERIC(0);
1273         Numeric         num2 = PG_GETARG_NUMERIC(1);
1274         NumericVar      arg1;
1275         NumericVar      arg2;
1276         Numeric         res;
1277
1278         /* ----------
1279          * Handle NaN
1280          * ----------
1281          */
1282         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1283                 PG_RETURN_NUMERIC(make_result(&const_nan));
1284
1285         /* ----------
1286          * Unpack the values, and decide which is the larger one
1287          * ----------
1288          */
1289         init_var(&arg1);
1290         init_var(&arg2);
1291
1292         set_var_from_num(num1, &arg1);
1293         set_var_from_num(num2, &arg2);
1294
1295         if (cmp_var(&arg1, &arg2) >= 0)
1296                 res = make_result(&arg1);
1297         else
1298                 res = make_result(&arg2);
1299
1300         free_var(&arg1);
1301         free_var(&arg2);
1302
1303         PG_RETURN_NUMERIC(res);
1304 }
1305
1306
1307 /* ----------------------------------------------------------------------
1308  *
1309  * Complex math functions
1310  *
1311  * ----------------------------------------------------------------------
1312  */
1313
1314
1315 /* ----------
1316  * numeric_sqrt() -
1317  *
1318  *      Compute the square root of a numeric.
1319  * ----------
1320  */
1321 Datum
1322 numeric_sqrt(PG_FUNCTION_ARGS)
1323 {
1324         Numeric         num = PG_GETARG_NUMERIC(0);
1325         Numeric         res;
1326         NumericVar      arg;
1327         NumericVar      result;
1328         int                     res_dscale;
1329
1330         /* ----------
1331          * Handle NaN
1332          * ----------
1333          */
1334         if (NUMERIC_IS_NAN(num))
1335                 PG_RETURN_NUMERIC(make_result(&const_nan));
1336
1337         /* ----------
1338          * Unpack the argument, determine the scales like for divide,
1339          * let sqrt_var() do the calculation and return the result.
1340          * ----------
1341          */
1342         init_var(&arg);
1343         init_var(&result);
1344
1345         set_var_from_num(num, &arg);
1346
1347         res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1348         res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1349         global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1350         global_rscale = MAX(global_rscale, res_dscale + 4);
1351         global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1352
1353         sqrt_var(&arg, &result);
1354
1355         result.dscale = res_dscale;
1356
1357         res = make_result(&result);
1358
1359         free_var(&result);
1360         free_var(&arg);
1361
1362         PG_RETURN_NUMERIC(res);
1363 }
1364
1365
1366 /* ----------
1367  * numeric_exp() -
1368  *
1369  *      Raise e to the power of x
1370  * ----------
1371  */
1372 Datum
1373 numeric_exp(PG_FUNCTION_ARGS)
1374 {
1375         Numeric         num = PG_GETARG_NUMERIC(0);
1376         Numeric         res;
1377         NumericVar      arg;
1378         NumericVar      result;
1379         int                     res_dscale;
1380
1381         /* ----------
1382          * Handle NaN
1383          * ----------
1384          */
1385         if (NUMERIC_IS_NAN(num))
1386                 PG_RETURN_NUMERIC(make_result(&const_nan));
1387
1388         /* ----------
1389          * Same procedure like for sqrt().
1390          * ----------
1391          */
1392         init_var(&arg);
1393         init_var(&result);
1394         set_var_from_num(num, &arg);
1395
1396         res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1397         res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1398         global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1399         global_rscale = MAX(global_rscale, res_dscale + 4);
1400         global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1401
1402         exp_var(&arg, &result);
1403
1404         result.dscale = res_dscale;
1405
1406         res = make_result(&result);
1407
1408         free_var(&result);
1409         free_var(&arg);
1410
1411         PG_RETURN_NUMERIC(res);
1412 }
1413
1414
1415 /* ----------
1416  * numeric_ln() -
1417  *
1418  *      Compute the natural logarithm of x
1419  * ----------
1420  */
1421 Datum
1422 numeric_ln(PG_FUNCTION_ARGS)
1423 {
1424         Numeric         num = PG_GETARG_NUMERIC(0);
1425         Numeric         res;
1426         NumericVar      arg;
1427         NumericVar      result;
1428         int                     res_dscale;
1429
1430         /* ----------
1431          * Handle NaN
1432          * ----------
1433          */
1434         if (NUMERIC_IS_NAN(num))
1435                 PG_RETURN_NUMERIC(make_result(&const_nan));
1436
1437         /* ----------
1438          * Same procedure like for sqrt()
1439          * ----------
1440          */
1441         init_var(&arg);
1442         init_var(&result);
1443         set_var_from_num(num, &arg);
1444
1445         res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1446         res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1447         global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1448         global_rscale = MAX(global_rscale, res_dscale + 4);
1449         global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1450
1451         ln_var(&arg, &result);
1452
1453         result.dscale = res_dscale;
1454
1455         res = make_result(&result);
1456
1457         free_var(&result);
1458         free_var(&arg);
1459
1460         PG_RETURN_NUMERIC(res);
1461 }
1462
1463
1464 /* ----------
1465  * numeric_log() -
1466  *
1467  *      Compute the logarithm of x in a given base
1468  * ----------
1469  */
1470 Datum
1471 numeric_log(PG_FUNCTION_ARGS)
1472 {
1473         Numeric         num1 = PG_GETARG_NUMERIC(0);
1474         Numeric         num2 = PG_GETARG_NUMERIC(1);
1475         Numeric         res;
1476         NumericVar      arg1;
1477         NumericVar      arg2;
1478         NumericVar      result;
1479         int                     res_dscale;
1480
1481         /* ----------
1482          * Handle NaN
1483          * ----------
1484          */
1485         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1486                 PG_RETURN_NUMERIC(make_result(&const_nan));
1487
1488         /* ----------
1489          * Initialize things and calculate scales
1490          * ----------
1491          */
1492         init_var(&arg1);
1493         init_var(&arg2);
1494         init_var(&result);
1495         set_var_from_num(num1, &arg1);
1496         set_var_from_num(num2, &arg2);
1497
1498         res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1499         res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1500         global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1501         global_rscale = MAX(global_rscale, res_dscale + 4);
1502         global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1503
1504         /* ----------
1505          * Call log_var() to compute and return the result
1506          * ----------
1507          */
1508         log_var(&arg1, &arg2, &result);
1509
1510         result.dscale = res_dscale;
1511
1512         res = make_result(&result);
1513
1514         free_var(&result);
1515         free_var(&arg2);
1516         free_var(&arg1);
1517
1518         PG_RETURN_NUMERIC(res);
1519 }
1520
1521
1522 /* ----------
1523  * numeric_power() -
1524  *
1525  *      Raise m to the power of x
1526  * ----------
1527  */
1528 Datum
1529 numeric_power(PG_FUNCTION_ARGS)
1530 {
1531         Numeric         num1 = PG_GETARG_NUMERIC(0);
1532         Numeric         num2 = PG_GETARG_NUMERIC(1);
1533         Numeric         res;
1534         NumericVar      arg1;
1535         NumericVar      arg2;
1536         NumericVar      result;
1537         int                     res_dscale;
1538
1539         /* ----------
1540          * Handle NaN
1541          * ----------
1542          */
1543         if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1544                 PG_RETURN_NUMERIC(make_result(&const_nan));
1545
1546         /* ----------
1547          * Initialize things and calculate scales
1548          * ----------
1549          */
1550         init_var(&arg1);
1551         init_var(&arg2);
1552         init_var(&result);
1553         set_var_from_num(num1, &arg1);
1554         set_var_from_num(num2, &arg2);
1555
1556         res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1557         res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1558         global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1559         global_rscale = MAX(global_rscale, res_dscale + 4);
1560         global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1561
1562         /* ----------
1563          * Call log_var() to compute and return the result
1564          * ----------
1565          */
1566         power_var(&arg1, &arg2, &result);
1567
1568         result.dscale = res_dscale;
1569
1570         res = make_result(&result);
1571
1572         free_var(&result);
1573         free_var(&arg2);
1574         free_var(&arg1);
1575
1576         PG_RETURN_NUMERIC(res);
1577 }
1578
1579
1580 /* ----------------------------------------------------------------------
1581  *
1582  * Type conversion functions
1583  *
1584  * ----------------------------------------------------------------------
1585  */
1586
1587
1588 Datum
1589 int4_numeric(PG_FUNCTION_ARGS)
1590 {
1591         int32           val = PG_GETARG_INT32(0);
1592         Numeric         res;
1593         NumericVar      result;
1594         char       *tmp;
1595
1596         init_var(&result);
1597
1598         tmp = DatumGetCString(DirectFunctionCall1(int4out,
1599                                                                                           Int32GetDatum(val)));
1600         set_var_from_str(tmp, &result);
1601         res = make_result(&result);
1602
1603         free_var(&result);
1604         pfree(tmp);
1605
1606         PG_RETURN_NUMERIC(res);
1607 }
1608
1609
1610 Datum
1611 numeric_int4(PG_FUNCTION_ARGS)
1612 {
1613         Numeric         num = PG_GETARG_NUMERIC(0);
1614         NumericVar      x;
1615         char       *str;
1616         Datum           result;
1617
1618         /* XXX would it be better to return NULL? */
1619         if (NUMERIC_IS_NAN(num))
1620                 elog(ERROR, "Cannot convert NaN to int4");
1621
1622         /* ----------
1623          * Get the number in the variable format so we can round to integer.
1624          * ----------
1625          */
1626         init_var(&x);
1627         set_var_from_num(num, &x);
1628
1629         str = get_str_from_var(&x, 0);          /* dscale = 0 produces rounding */
1630
1631         free_var(&x);
1632
1633         result = DirectFunctionCall1(int4in, CStringGetDatum(str));
1634         pfree(str);
1635
1636         PG_RETURN_DATUM(result);
1637 }
1638
1639
1640 Datum
1641 int8_numeric(PG_FUNCTION_ARGS)
1642 {
1643         Datum           val = PG_GETARG_DATUM(0);
1644         Numeric         res;
1645         NumericVar      result;
1646         char       *tmp;
1647
1648         init_var(&result);
1649
1650         tmp = DatumGetCString(DirectFunctionCall1(int8out, val));
1651         set_var_from_str(tmp, &result);
1652         res = make_result(&result);
1653
1654         free_var(&result);
1655         pfree(tmp);
1656
1657         PG_RETURN_NUMERIC(res);
1658 }
1659
1660
1661 Datum
1662 numeric_int8(PG_FUNCTION_ARGS)
1663 {
1664         Numeric         num = PG_GETARG_NUMERIC(0);
1665         NumericVar      x;
1666         char       *str;
1667         Datum           result;
1668
1669         /* XXX would it be better to return NULL? */
1670         if (NUMERIC_IS_NAN(num))
1671                 elog(ERROR, "Cannot convert NaN to int8");
1672
1673         /* ----------
1674          * Get the number in the variable format so we can round to integer.
1675          * ----------
1676          */
1677         init_var(&x);
1678         set_var_from_num(num, &x);
1679
1680         str = get_str_from_var(&x, 0);          /* dscale = 0 produces rounding */
1681
1682         free_var(&x);
1683
1684         result = DirectFunctionCall1(int8in, CStringGetDatum(str));
1685         pfree(str);
1686
1687         PG_RETURN_DATUM(result);
1688 }
1689
1690
1691 Datum
1692 int2_numeric(PG_FUNCTION_ARGS)
1693 {
1694         int16           val = PG_GETARG_INT16(0);
1695         Numeric         res;
1696         NumericVar      result;
1697         char       *tmp;
1698
1699         init_var(&result);
1700
1701         tmp = DatumGetCString(DirectFunctionCall1(int2out,
1702                                                                                           Int16GetDatum(val)));
1703         set_var_from_str(tmp, &result);
1704         res = make_result(&result);
1705
1706         free_var(&result);
1707         pfree(tmp);
1708
1709         PG_RETURN_NUMERIC(res);
1710 }
1711
1712
1713 Datum
1714 numeric_int2(PG_FUNCTION_ARGS)
1715 {
1716         Numeric         num = PG_GETARG_NUMERIC(0);
1717         NumericVar      x;
1718         char       *str;
1719         Datum           result;
1720
1721         if (NUMERIC_IS_NAN(num))
1722                 elog(ERROR, "Cannot convert NaN to int2");
1723
1724         /* ----------
1725          * Get the number in the variable format so we can round to integer.
1726          * ----------
1727          */
1728         init_var(&x);
1729         set_var_from_num(num, &x);
1730
1731         str = get_str_from_var(&x, 0);          /* dscale = 0 produces rounding */
1732
1733         free_var(&x);
1734
1735         result = DirectFunctionCall1(int2in, CStringGetDatum(str));
1736         pfree(str);
1737
1738         return result;
1739 }
1740
1741
1742 Datum
1743 float8_numeric(PG_FUNCTION_ARGS)
1744 {
1745         float8          val = PG_GETARG_FLOAT8(0);
1746         Numeric         res;
1747         NumericVar      result;
1748         char            buf[DBL_DIG + 100];
1749
1750         if (isnan(val))
1751                 PG_RETURN_NUMERIC(make_result(&const_nan));
1752
1753         sprintf(buf, "%.*g", DBL_DIG, val);
1754
1755         init_var(&result);
1756
1757         set_var_from_str(buf, &result);
1758         res = make_result(&result);
1759
1760         free_var(&result);
1761
1762         PG_RETURN_NUMERIC(res);
1763 }
1764
1765
1766 Datum
1767 numeric_float8(PG_FUNCTION_ARGS)
1768 {
1769         Numeric         num = PG_GETARG_NUMERIC(0);
1770         char       *tmp;
1771         Datum           result;
1772
1773         if (NUMERIC_IS_NAN(num))
1774                 PG_RETURN_FLOAT8(NAN);
1775
1776         tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1777                                                                                           NumericGetDatum(num)));
1778
1779         result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
1780
1781         pfree(tmp);
1782
1783         PG_RETURN_DATUM(result);
1784 }
1785
1786
1787 Datum
1788 float4_numeric(PG_FUNCTION_ARGS)
1789 {
1790         float4          val = PG_GETARG_FLOAT4(0);
1791         Numeric         res;
1792         NumericVar      result;
1793         char            buf[FLT_DIG + 100];
1794
1795         if (isnan(val))
1796                 PG_RETURN_NUMERIC(make_result(&const_nan));
1797
1798         sprintf(buf, "%.*g", FLT_DIG, val);
1799
1800         init_var(&result);
1801
1802         set_var_from_str(buf, &result);
1803         res = make_result(&result);
1804
1805         free_var(&result);
1806
1807         PG_RETURN_NUMERIC(res);
1808 }
1809
1810
1811 Datum
1812 numeric_float4(PG_FUNCTION_ARGS)
1813 {
1814         Numeric         num = PG_GETARG_NUMERIC(0);
1815         char       *tmp;
1816         Datum           result;
1817
1818         if (NUMERIC_IS_NAN(num))
1819                 PG_RETURN_FLOAT4((float4) NAN);
1820
1821         tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1822                                                                                           NumericGetDatum(num)));
1823
1824         result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
1825
1826         pfree(tmp);
1827
1828         PG_RETURN_DATUM(result);
1829 }
1830
1831
1832 /* ----------------------------------------------------------------------
1833  *
1834  * Aggregate functions
1835  *
1836  * The transition datatype for all these aggregates is a 3-element array
1837  * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
1838  *
1839  * We represent N as a numeric mainly to avoid having to build a special
1840  * datatype; it's unlikely it'd overflow an int4, but ...
1841  *
1842  * ----------------------------------------------------------------------
1843  */
1844
1845 static ArrayType *
1846 do_numeric_accum(ArrayType *transarray, Numeric newval)
1847 {
1848         Datum      *transdatums;
1849         int                     ndatums;
1850         Datum           N,
1851                                 sumX,
1852                                 sumX2;
1853         ArrayType  *result;
1854
1855         /* We assume the input is array of numeric */
1856         deconstruct_array(transarray,
1857                                           false, -1, 'i',
1858                                           &transdatums, &ndatums);
1859         if (ndatums != 3)
1860                 elog(ERROR, "do_numeric_accum: expected 3-element numeric array");
1861         N = transdatums[0];
1862         sumX = transdatums[1];
1863         sumX2 = transdatums[2];
1864
1865         N = DirectFunctionCall1(numeric_inc, N);
1866         sumX = DirectFunctionCall2(numeric_add, sumX,
1867                                                            NumericGetDatum(newval));
1868         sumX2 = DirectFunctionCall2(numeric_add, sumX2,
1869                                                                 DirectFunctionCall2(numeric_mul,
1870                                                                                                  NumericGetDatum(newval),
1871                                                                                            NumericGetDatum(newval)));
1872
1873         transdatums[0] = N;
1874         transdatums[1] = sumX;
1875         transdatums[2] = sumX2;
1876
1877         result = construct_array(transdatums, 3,
1878                                                          false, -1, 'i');
1879
1880         return result;
1881 }
1882
1883 Datum
1884 numeric_accum(PG_FUNCTION_ARGS)
1885 {
1886         ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
1887         Numeric         newval = PG_GETARG_NUMERIC(1);
1888
1889         PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1890 }
1891
1892 /*
1893  * Integer data types all use Numeric accumulators to share code and
1894  * avoid risk of overflow.
1895  */
1896
1897 Datum
1898 int2_accum(PG_FUNCTION_ARGS)
1899 {
1900         ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
1901         Datum           newval2 = PG_GETARG_DATUM(1);
1902         Numeric         newval;
1903
1904         newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
1905
1906         PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1907 }
1908
1909 Datum
1910 int4_accum(PG_FUNCTION_ARGS)
1911 {
1912         ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
1913         Datum           newval4 = PG_GETARG_DATUM(1);
1914         Numeric         newval;
1915
1916         newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
1917
1918         PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1919 }
1920
1921 Datum
1922 int8_accum(PG_FUNCTION_ARGS)
1923 {
1924         ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
1925         Datum           newval8 = PG_GETARG_DATUM(1);
1926         Numeric         newval;
1927
1928         newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
1929
1930         PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1931 }
1932
1933 Datum
1934 numeric_avg(PG_FUNCTION_ARGS)
1935 {
1936         ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
1937         Datum      *transdatums;
1938         int                     ndatums;
1939         Numeric         N,
1940                                 sumX;
1941
1942         /* We assume the input is array of numeric */
1943         deconstruct_array(transarray,
1944                                           false, -1, 'i',
1945                                           &transdatums, &ndatums);
1946         if (ndatums != 3)
1947                 elog(ERROR, "numeric_avg: expected 3-element numeric array");
1948         N = DatumGetNumeric(transdatums[0]);
1949         sumX = DatumGetNumeric(transdatums[1]);
1950         /* ignore sumX2 */
1951
1952         /* SQL92 defines AVG of no values to be NULL */
1953         /* N is zero iff no digits (cf. numeric_uminus) */
1954         if (N->varlen == NUMERIC_HDRSZ)
1955                 PG_RETURN_NULL();
1956
1957         PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
1958                                                                                 NumericGetDatum(sumX),
1959                                                                                 NumericGetDatum(N)));
1960 }
1961
1962 Datum
1963 numeric_variance(PG_FUNCTION_ARGS)
1964 {
1965         ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
1966         Datum      *transdatums;
1967         int                     ndatums;
1968         Numeric         N,
1969                                 sumX,
1970                                 sumX2,
1971                                 res;
1972         NumericVar      vN,
1973                                 vsumX,
1974                                 vsumX2,
1975                                 vNminus1;
1976
1977         /* We assume the input is array of numeric */
1978         deconstruct_array(transarray,
1979                                           false, -1, 'i',
1980                                           &transdatums, &ndatums);
1981         if (ndatums != 3)
1982                 elog(ERROR, "numeric_variance: expected 3-element numeric array");
1983         N = DatumGetNumeric(transdatums[0]);
1984         sumX = DatumGetNumeric(transdatums[1]);
1985         sumX2 = DatumGetNumeric(transdatums[2]);
1986
1987         if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
1988                 PG_RETURN_NUMERIC(make_result(&const_nan));
1989
1990         /* We define VARIANCE of no values to be NULL, of 1 value to be 0 */
1991         /* N is zero iff no digits (cf. numeric_uminus) */
1992         if (N->varlen == NUMERIC_HDRSZ)
1993                 PG_RETURN_NULL();
1994
1995         init_var(&vN);
1996         set_var_from_num(N, &vN);
1997
1998         init_var(&vNminus1);
1999         sub_var(&vN, &const_one, &vNminus1);
2000
2001         if (cmp_var(&vNminus1, &const_zero) <= 0)
2002         {
2003                 free_var(&vN);
2004                 free_var(&vNminus1);
2005                 PG_RETURN_NUMERIC(make_result(&const_zero));
2006         }
2007
2008         init_var(&vsumX);
2009         set_var_from_num(sumX, &vsumX);
2010         init_var(&vsumX2);
2011         set_var_from_num(sumX2, &vsumX2);
2012
2013         mul_var(&vsumX, &vsumX, &vsumX);        /* now vsumX contains sumX * sumX */
2014         mul_var(&vN, &vsumX2, &vsumX2);         /* now vsumX2 contains N * sumX2 */
2015         sub_var(&vsumX2, &vsumX, &vsumX2);      /* N * sumX2 - sumX * sumX */
2016         mul_var(&vN, &vNminus1, &vNminus1); /* N * (N - 1) */
2017         div_var(&vsumX2, &vNminus1, &vsumX);            /* variance */
2018
2019         res = make_result(&vsumX);
2020
2021         free_var(&vN);
2022         free_var(&vNminus1);
2023         free_var(&vsumX);
2024         free_var(&vsumX2);
2025
2026         PG_RETURN_NUMERIC(res);
2027 }
2028
2029 Datum
2030 numeric_stddev(PG_FUNCTION_ARGS)
2031 {
2032         ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
2033         Datum      *transdatums;
2034         int                     ndatums;
2035         Numeric         N,
2036                                 sumX,
2037                                 sumX2,
2038                                 res;
2039         NumericVar      vN,
2040                                 vsumX,
2041                                 vsumX2,
2042                                 vNminus1;
2043
2044         /* We assume the input is array of numeric */
2045         deconstruct_array(transarray,
2046                                           false, -1, 'i',
2047                                           &transdatums, &ndatums);
2048         if (ndatums != 3)
2049                 elog(ERROR, "numeric_stddev: expected 3-element numeric array");
2050         N = DatumGetNumeric(transdatums[0]);
2051         sumX = DatumGetNumeric(transdatums[1]);
2052         sumX2 = DatumGetNumeric(transdatums[2]);
2053
2054         if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2055                 PG_RETURN_NUMERIC(make_result(&const_nan));
2056
2057         /* We define STDDEV of no values to be NULL, of 1 value to be 0 */
2058         /* N is zero iff no digits (cf. numeric_uminus) */
2059         if (N->varlen == NUMERIC_HDRSZ)
2060                 PG_RETURN_NULL();
2061
2062         init_var(&vN);
2063         set_var_from_num(N, &vN);
2064
2065         init_var(&vNminus1);
2066         sub_var(&vN, &const_one, &vNminus1);
2067
2068         if (cmp_var(&vNminus1, &const_zero) <= 0)
2069         {
2070                 free_var(&vN);
2071                 free_var(&vNminus1);
2072                 PG_RETURN_NUMERIC(make_result(&const_zero));
2073         }
2074
2075         init_var(&vsumX);
2076         set_var_from_num(sumX, &vsumX);
2077         init_var(&vsumX2);
2078         set_var_from_num(sumX2, &vsumX2);
2079
2080         mul_var(&vsumX, &vsumX, &vsumX);        /* now vsumX contains sumX * sumX */
2081         mul_var(&vN, &vsumX2, &vsumX2);         /* now vsumX2 contains N * sumX2 */
2082         sub_var(&vsumX2, &vsumX, &vsumX2);      /* N * sumX2 - sumX * sumX */
2083         mul_var(&vN, &vNminus1, &vNminus1); /* N * (N - 1) */
2084         div_var(&vsumX2, &vNminus1, &vsumX);            /* variance */
2085         sqrt_var(&vsumX, &vsumX);       /* stddev */
2086
2087         res = make_result(&vsumX);
2088
2089         free_var(&vN);
2090         free_var(&vNminus1);
2091         free_var(&vsumX);
2092         free_var(&vsumX2);
2093
2094         PG_RETURN_NUMERIC(res);
2095 }
2096
2097
2098 /*
2099  * SUM transition functions for integer datatypes.
2100  *
2101  * We use a Numeric accumulator to avoid overflow.      Because SQL92 defines
2102  * the SUM() of no values to be NULL, not zero, the initial condition of
2103  * the transition data value needs to be NULL.  This means we can't rely
2104  * on ExecAgg to automatically insert the first non-null data value into
2105  * the transition data: it doesn't know how to do the type conversion.
2106  * The upshot is that these routines have to be marked non-strict and
2107  * handle substitution of the first non-null input themselves.
2108  */
2109
2110 Datum
2111 int2_sum(PG_FUNCTION_ARGS)
2112 {
2113         Numeric         oldsum;
2114         Datum           newval;
2115
2116         if (PG_ARGISNULL(0))
2117         {
2118                 /* No non-null input seen so far... */
2119                 if (PG_ARGISNULL(1))
2120                         PG_RETURN_NULL();       /* still no non-null */
2121                 /* This is the first non-null input. */
2122                 newval = DirectFunctionCall1(int2_numeric, PG_GETARG_DATUM(1));
2123                 PG_RETURN_DATUM(newval);
2124         }
2125
2126         oldsum = PG_GETARG_NUMERIC(0);
2127
2128         /* Leave sum unchanged if new input is null. */
2129         if (PG_ARGISNULL(1))
2130                 PG_RETURN_NUMERIC(oldsum);
2131
2132         /* OK to do the addition. */
2133         newval = DirectFunctionCall1(int2_numeric, PG_GETARG_DATUM(1));
2134
2135         PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2136                                                                                 NumericGetDatum(oldsum), newval));
2137 }
2138
2139 Datum
2140 int4_sum(PG_FUNCTION_ARGS)
2141 {
2142         Numeric         oldsum;
2143         Datum           newval;
2144
2145         if (PG_ARGISNULL(0))
2146         {
2147                 /* No non-null input seen so far... */
2148                 if (PG_ARGISNULL(1))
2149                         PG_RETURN_NULL();       /* still no non-null */
2150                 /* This is the first non-null input. */
2151                 newval = DirectFunctionCall1(int4_numeric, PG_GETARG_DATUM(1));
2152                 PG_RETURN_DATUM(newval);
2153         }
2154
2155         oldsum = PG_GETARG_NUMERIC(0);
2156
2157         /* Leave sum unchanged if new input is null. */
2158         if (PG_ARGISNULL(1))
2159                 PG_RETURN_NUMERIC(oldsum);
2160
2161         /* OK to do the addition. */
2162         newval = DirectFunctionCall1(int4_numeric, PG_GETARG_DATUM(1));
2163
2164         PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2165                                                                                 NumericGetDatum(oldsum), newval));
2166 }
2167
2168 Datum
2169 int8_sum(PG_FUNCTION_ARGS)
2170 {
2171         Numeric         oldsum;
2172         Datum           newval;
2173
2174         if (PG_ARGISNULL(0))
2175         {
2176                 /* No non-null input seen so far... */
2177                 if (PG_ARGISNULL(1))
2178                         PG_RETURN_NULL();       /* still no non-null */
2179                 /* This is the first non-null input. */
2180                 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2181                 PG_RETURN_DATUM(newval);
2182         }
2183
2184         oldsum = PG_GETARG_NUMERIC(0);
2185
2186         /* Leave sum unchanged if new input is null. */
2187         if (PG_ARGISNULL(1))
2188                 PG_RETURN_NUMERIC(oldsum);
2189
2190         /* OK to do the addition. */
2191         newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2192
2193         PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2194                                                                                 NumericGetDatum(oldsum), newval));
2195 }
2196
2197
2198 /* ----------------------------------------------------------------------
2199  *
2200  * Local functions follow
2201  *
2202  * ----------------------------------------------------------------------
2203  */
2204
2205
2206 #ifdef NUMERIC_DEBUG
2207
2208 /* ----------
2209  * dump_numeric() - Dump a value in the db storage format for debugging
2210  * ----------
2211  */
2212 static void
2213 dump_numeric(char *str, Numeric num)
2214 {
2215         int                     i;
2216
2217         printf("%s: NUMERIC w=%d r=%d d=%d ", str, num->n_weight, num->n_rscale,
2218                    NUMERIC_DSCALE(num));
2219         switch (NUMERIC_SIGN(num))
2220         {
2221                 case NUMERIC_POS:
2222                         printf("POS");
2223                         break;
2224                 case NUMERIC_NEG:
2225                         printf("NEG");
2226                         break;
2227                 case NUMERIC_NAN:
2228                         printf("NaN");
2229                         break;
2230                 default:
2231                         printf("SIGN=0x%x", NUMERIC_SIGN(num));
2232                         break;
2233         }
2234
2235         for (i = 0; i < num->varlen - NUMERIC_HDRSZ; i++)
2236                 printf(" %d %d", (num->n_data[i] >> 4) & 0x0f, num->n_data[i] & 0x0f);
2237         printf("\n");
2238 }
2239
2240
2241 /* ----------
2242  * dump_var() - Dump a value in the variable format for debugging
2243  * ----------
2244  */
2245 static void
2246 dump_var(char *str, NumericVar *var)
2247 {
2248         int                     i;
2249
2250         printf("%s: VAR w=%d r=%d d=%d ", str, var->weight, var->rscale,
2251                    var->dscale);
2252         switch (var->sign)
2253         {
2254                 case NUMERIC_POS:
2255                         printf("POS");
2256                         break;
2257                 case NUMERIC_NEG:
2258                         printf("NEG");
2259                         break;
2260                 case NUMERIC_NAN:
2261                         printf("NaN");
2262                         break;
2263                 default:
2264                         printf("SIGN=0x%x", var->sign);
2265                         break;
2266         }
2267
2268         for (i = 0; i < var->ndigits; i++)
2269                 printf(" %d", var->digits[i]);
2270
2271         printf("\n");
2272 }
2273
2274 #endif   /* NUMERIC_DEBUG */
2275
2276
2277 /* ----------
2278  * alloc_var() -
2279  *
2280  *      Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2281  * ----------
2282  */
2283 static void
2284 alloc_var(NumericVar *var, int ndigits)
2285 {
2286         digitbuf_free(var->buf);
2287         var->buf = digitbuf_alloc(ndigits + 1);
2288         var->buf[0] = 0;
2289         var->digits = var->buf + 1;
2290         var->ndigits = ndigits;
2291 }
2292
2293
2294 /* ----------
2295  * free_var() -
2296  *
2297  *      Return the digit buffer of a variable to the free pool
2298  * ----------
2299  */
2300 static void
2301 free_var(NumericVar *var)
2302 {
2303         digitbuf_free(var->buf);
2304         var->buf = NULL;
2305         var->digits = NULL;
2306         var->sign = NUMERIC_NAN;
2307 }
2308
2309
2310 /* ----------
2311  * zero_var() -
2312  *
2313  *      Set a variable to ZERO.
2314  *      Note: rscale and dscale are not touched.
2315  * ----------
2316  */
2317 static void
2318 zero_var(NumericVar *var)
2319 {
2320         digitbuf_free(var->buf);
2321         var->buf = NULL;
2322         var->digits = NULL;
2323         var->ndigits = 0;
2324         var->weight = 0;                        /* by convention; doesn't really matter */
2325         var->sign = NUMERIC_POS;        /* anything but NAN... */
2326 }
2327
2328
2329 /* ----------
2330  * set_var_from_str()
2331  *
2332  *      Parse a string and put the number into a variable
2333  * ----------
2334  */
2335 static void
2336 set_var_from_str(char *str, NumericVar *dest)
2337 {
2338         char       *cp = str;
2339         bool            have_dp = FALSE;
2340         int                     i = 0;
2341
2342         while (*cp)
2343         {
2344                 if (!isspace((unsigned char) *cp))
2345                         break;
2346                 cp++;
2347         }
2348
2349         alloc_var(dest, strlen(cp));
2350         dest->weight = -1;
2351         dest->dscale = 0;
2352         dest->sign = NUMERIC_POS;
2353
2354         switch (*cp)
2355         {
2356                 case '+':
2357                         dest->sign = NUMERIC_POS;
2358                         cp++;
2359                         break;
2360
2361                 case '-':
2362                         dest->sign = NUMERIC_NEG;
2363                         cp++;
2364                         break;
2365         }
2366
2367         if (*cp == '.')
2368         {
2369                 have_dp = TRUE;
2370                 cp++;
2371         }
2372
2373         if (!isdigit((unsigned char) *cp))
2374                 elog(ERROR, "Bad numeric input format '%s'", str);
2375
2376         while (*cp)
2377         {
2378                 if (isdigit((unsigned char) *cp))
2379                 {
2380                         dest->digits[i++] = *cp++ - '0';
2381                         if (!have_dp)
2382                                 dest->weight++;
2383                         else
2384                                 dest->dscale++;
2385                 }
2386                 else if (*cp == '.')
2387                 {
2388                         if (have_dp)
2389                                 elog(ERROR, "Bad numeric input format '%s'", str);
2390                         have_dp = TRUE;
2391                         cp++;
2392                 }
2393                 else
2394                         break;
2395         }
2396         dest->ndigits = i;
2397
2398         /* Handle exponent, if any */
2399         if (*cp == 'e' || *cp == 'E')
2400         {
2401                 long            exponent;
2402                 char       *endptr;
2403
2404                 cp++;
2405                 exponent = strtol(cp, &endptr, 10);
2406                 if (endptr == cp)
2407                         elog(ERROR, "Bad numeric input format '%s'", str);
2408                 cp = endptr;
2409                 if (exponent > NUMERIC_MAX_PRECISION ||
2410                         exponent < -NUMERIC_MAX_PRECISION)
2411                         elog(ERROR, "Bad numeric input format '%s'", str);
2412                 dest->weight += (int) exponent;
2413                 dest->dscale -= (int) exponent;
2414                 if (dest->dscale < 0)
2415                         dest->dscale = 0;
2416         }
2417
2418         /* Should be nothing left but spaces */
2419         while (*cp)
2420         {
2421                 if (!isspace((unsigned char) *cp))
2422                         elog(ERROR, "Bad numeric input format '%s'", str);
2423                 cp++;
2424         }
2425
2426         /* Strip any leading zeroes */
2427         while (dest->ndigits > 0 && *(dest->digits) == 0)
2428         {
2429                 (dest->digits)++;
2430                 (dest->weight)--;
2431                 (dest->ndigits)--;
2432         }
2433         if (dest->ndigits == 0)
2434                 dest->weight = 0;
2435
2436         dest->rscale = dest->dscale;
2437 }
2438
2439
2440 /*
2441  * set_var_from_num() -
2442  *
2443  *      Parse back the packed db format into a variable
2444  *
2445  */
2446 static void
2447 set_var_from_num(Numeric num, NumericVar *dest)
2448 {
2449         NumericDigit *digit;
2450         int                     i;
2451         int                     n;
2452
2453         n = num->varlen - NUMERIC_HDRSZ;        /* number of digit-pairs in packed
2454                                                                                  * fmt */
2455
2456         alloc_var(dest, n * 2);
2457
2458         dest->weight = num->n_weight;
2459         dest->rscale = num->n_rscale;
2460         dest->dscale = NUMERIC_DSCALE(num);
2461         dest->sign = NUMERIC_SIGN(num);
2462
2463         digit = dest->digits;
2464
2465         for (i = 0; i < n; i++)
2466         {
2467                 unsigned char digitpair = num->n_data[i];
2468
2469                 *digit++ = (digitpair >> 4) & 0x0f;
2470                 *digit++ = digitpair & 0x0f;
2471         }
2472 }
2473
2474
2475 /* ----------
2476  * set_var_from_var() -
2477  *
2478  *      Copy one variable into another
2479  * ----------
2480  */
2481 static void
2482 set_var_from_var(NumericVar *value, NumericVar *dest)
2483 {
2484         NumericDigit *newbuf;
2485
2486         newbuf = digitbuf_alloc(value->ndigits + 1);
2487         newbuf[0] = 0;                          /* spare digit for rounding */
2488         memcpy(newbuf + 1, value->digits, value->ndigits);
2489
2490         digitbuf_free(dest->buf);
2491
2492         memcpy(dest, value, sizeof(NumericVar));
2493         dest->buf = newbuf;
2494         dest->digits = newbuf + 1;
2495 }
2496
2497
2498 /* ----------
2499  * get_str_from_var() -
2500  *
2501  *      Convert a var to text representation (guts of numeric_out).
2502  *      CAUTION: var's contents may be modified by rounding!
2503  *      Caller must have checked for NaN case.
2504  *      Returns a palloc'd string.
2505  * ----------
2506  */
2507 static char *
2508 get_str_from_var(NumericVar *var, int dscale)
2509 {
2510         char       *str;
2511         char       *cp;
2512         int                     i;
2513         int                     d;
2514
2515         /* ----------
2516          * Check if we must round up before printing the value and
2517          * do so.
2518          * ----------
2519          */
2520         i = dscale + var->weight + 1;
2521         if (i >= 0 && var->ndigits > i)
2522         {
2523                 int                     carry = (var->digits[i] > 4) ? 1 : 0;
2524
2525                 var->ndigits = i;
2526
2527                 while (carry)
2528                 {
2529                         carry += var->digits[--i];
2530                         var->digits[i] = carry % 10;
2531                         carry /= 10;
2532                 }
2533
2534                 if (i < 0)
2535                 {
2536                         Assert(i == -1);        /* better not have added more than 1 digit */
2537                         Assert(var->digits > var->buf);
2538                         var->digits--;
2539                         var->ndigits++;
2540                         var->weight++;
2541                 }
2542         }
2543         else
2544                 var->ndigits = MAX(0, MIN(i, var->ndigits));
2545
2546         /* ----------
2547          * Allocate space for the result
2548          * ----------
2549          */
2550         str = palloc(MAX(0, dscale) + MAX(0, var->weight) + 4);
2551         cp = str;
2552
2553         /* ----------
2554          * Output a dash for negative values
2555          * ----------
2556          */
2557         if (var->sign == NUMERIC_NEG)
2558                 *cp++ = '-';
2559
2560         /* ----------
2561          * Output all digits before the decimal point
2562          * ----------
2563          */
2564         i = MAX(var->weight, 0);
2565         d = 0;
2566
2567         while (i >= 0)
2568         {
2569                 if (i <= var->weight && d < var->ndigits)
2570                         *cp++ = var->digits[d++] + '0';
2571                 else
2572                         *cp++ = '0';
2573                 i--;
2574         }
2575
2576         /* ----------
2577          * If requested, output a decimal point and all the digits
2578          * that follow it.
2579          * ----------
2580          */
2581         if (dscale > 0)
2582         {
2583                 *cp++ = '.';
2584                 while (i >= -dscale)
2585                 {
2586                         if (i <= var->weight && d < var->ndigits)
2587                                 *cp++ = var->digits[d++] + '0';
2588                         else
2589                                 *cp++ = '0';
2590                         i--;
2591                 }
2592         }
2593
2594         /* ----------
2595          * terminate the string and return it
2596          * ----------
2597          */
2598         *cp = '\0';
2599         return str;
2600 }
2601
2602
2603 /* ----------
2604  * make_result() -
2605  *
2606  *      Create the packed db numeric format in palloc()'d memory from
2607  *      a variable.  The var's rscale determines the number of digits kept.
2608  * ----------
2609  */
2610 static Numeric
2611 make_result(NumericVar *var)
2612 {
2613         Numeric         result;
2614         NumericDigit *digit = var->digits;
2615         int                     weight = var->weight;
2616         int                     sign = var->sign;
2617         int                     n;
2618         int                     i,
2619                                 j;
2620
2621         if (sign == NUMERIC_NAN)
2622         {
2623                 result = (Numeric) palloc(NUMERIC_HDRSZ);
2624
2625                 result->varlen = NUMERIC_HDRSZ;
2626                 result->n_weight = 0;
2627                 result->n_rscale = 0;
2628                 result->n_sign_dscale = NUMERIC_NAN;
2629
2630                 dump_numeric("make_result()", result);
2631                 return result;
2632         }
2633
2634         n = MAX(0, MIN(var->ndigits, var->weight + var->rscale + 1));
2635
2636         /* truncate leading zeroes */
2637         while (n > 0 && *digit == 0)
2638         {
2639                 digit++;
2640                 weight--;
2641                 n--;
2642         }
2643         /* truncate trailing zeroes */
2644         while (n > 0 && digit[n - 1] == 0)
2645                 n--;
2646
2647         /* If zero result, force to weight=0 and positive sign */
2648         if (n == 0)
2649         {
2650                 weight = 0;
2651                 sign = NUMERIC_POS;
2652         }
2653
2654         result = (Numeric) palloc(NUMERIC_HDRSZ + (n + 1) / 2);
2655         result->varlen = NUMERIC_HDRSZ + (n + 1) / 2;
2656         result->n_weight = weight;
2657         result->n_rscale = var->rscale;
2658         result->n_sign_dscale = sign |
2659                 ((uint16) var->dscale & NUMERIC_DSCALE_MASK);
2660
2661         i = 0;
2662         j = 0;
2663         while (j < n)
2664         {
2665                 unsigned char digitpair = digit[j++] << 4;
2666
2667                 if (j < n)
2668                         digitpair |= digit[j++];
2669                 result->n_data[i++] = digitpair;
2670         }
2671
2672         dump_numeric("make_result()", result);
2673         return result;
2674 }
2675
2676
2677 /* ----------
2678  * apply_typmod() -
2679  *
2680  *      Do bounds checking and rounding according to the attributes
2681  *      typmod field.
2682  * ----------
2683  */
2684 static void
2685 apply_typmod(NumericVar *var, int32 typmod)
2686 {
2687         int                     precision;
2688         int                     scale;
2689         int                     maxweight;
2690         int                     i;
2691
2692         /* Do nothing if we have a default typmod (-1) */
2693         if (typmod < (int32) (VARHDRSZ))
2694                 return;
2695
2696         typmod -= VARHDRSZ;
2697         precision = (typmod >> 16) & 0xffff;
2698         scale = typmod & 0xffff;
2699         maxweight = precision - scale;
2700
2701         /* Round to target scale */
2702         i = scale + var->weight + 1;
2703         if (i >= 0 && var->ndigits > i)
2704         {
2705                 int                     carry = (var->digits[i] > 4) ? 1 : 0;
2706
2707                 var->ndigits = i;
2708
2709                 while (carry)
2710                 {
2711                         carry += var->digits[--i];
2712                         var->digits[i] = carry % 10;
2713                         carry /= 10;
2714                 }
2715
2716                 if (i < 0)
2717                 {
2718                         Assert(i == -1);        /* better not have added more than 1 digit */
2719                         Assert(var->digits > var->buf);
2720                         var->digits--;
2721                         var->ndigits++;
2722                         var->weight++;
2723                 }
2724         }
2725         else
2726                 var->ndigits = MAX(0, MIN(i, var->ndigits));
2727
2728         /* ----------
2729          * Check for overflow - note we can't do this before rounding,
2730          * because rounding could raise the weight.  Also note that the
2731          * var's weight could be inflated by leading zeroes, which will
2732          * be stripped before storage but perhaps might not have been yet.
2733          * In any case, we must recognize a true zero, whose weight doesn't
2734          * mean anything.
2735          * ----------
2736          */
2737         if (var->weight >= maxweight)
2738         {
2739                 /* Determine true weight; and check for all-zero result */
2740                 int                     tweight = var->weight;
2741
2742                 for (i = 0; i < var->ndigits; i++)
2743                 {
2744                         if (var->digits[i])
2745                                 break;
2746                         tweight--;
2747                 }
2748
2749                 if (tweight >= maxweight && i < var->ndigits)
2750                         elog(ERROR, "overflow on numeric "
2751                           "ABS(value) >= 10^%d for field with precision %d scale %d",
2752                                  tweight, precision, scale);
2753         }
2754
2755         var->rscale = scale;
2756         var->dscale = scale;
2757 }
2758
2759
2760 /* ----------
2761  * cmp_var() -
2762  *
2763  *      Compare two values on variable level
2764  * ----------
2765  */
2766 static int
2767 cmp_var(NumericVar *var1, NumericVar *var2)
2768 {
2769         if (var1->ndigits == 0)
2770         {
2771                 if (var2->ndigits == 0)
2772                         return 0;
2773                 if (var2->sign == NUMERIC_NEG)
2774                         return 1;
2775                 return -1;
2776         }
2777         if (var2->ndigits == 0)
2778         {
2779                 if (var1->sign == NUMERIC_POS)
2780                         return 1;
2781                 return -1;
2782         }
2783
2784         if (var1->sign == NUMERIC_POS)
2785         {
2786                 if (var2->sign == NUMERIC_NEG)
2787                         return 1;
2788                 return cmp_abs(var1, var2);
2789         }
2790
2791         if (var2->sign == NUMERIC_POS)
2792                 return -1;
2793
2794         return cmp_abs(var2, var1);
2795 }
2796
2797
2798 /* ----------
2799  * add_var() -
2800  *
2801  *      Full version of add functionality on variable level (handling signs).
2802  *      result might point to one of the operands too without danger.
2803  * ----------
2804  */
2805 static void
2806 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2807 {
2808         /* ----------
2809          * Decide on the signs of the two variables what to do
2810          * ----------
2811          */
2812         if (var1->sign == NUMERIC_POS)
2813         {
2814                 if (var2->sign == NUMERIC_POS)
2815                 {
2816                         /* ----------
2817                          * Both are positive
2818                          * result = +(ABS(var1) + ABS(var2))
2819                          * ----------
2820                          */
2821                         add_abs(var1, var2, result);
2822                         result->sign = NUMERIC_POS;
2823                 }
2824                 else
2825                 {
2826                         /* ----------
2827                          * var1 is positive, var2 is negative
2828                          * Must compare absolute values
2829                          * ----------
2830                          */
2831                         switch (cmp_abs(var1, var2))
2832                         {
2833                                 case 0:
2834                                         /* ----------
2835                                          * ABS(var1) == ABS(var2)
2836                                          * result = ZERO
2837                                          * ----------
2838                                          */
2839                                         zero_var(result);
2840                                         result->rscale = MAX(var1->rscale, var2->rscale);
2841                                         result->dscale = MAX(var1->dscale, var2->dscale);
2842                                         break;
2843
2844                                 case 1:
2845                                         /* ----------
2846                                          * ABS(var1) > ABS(var2)
2847                                          * result = +(ABS(var1) - ABS(var2))
2848                                          * ----------
2849                                          */
2850                                         sub_abs(var1, var2, result);
2851                                         result->sign = NUMERIC_POS;
2852                                         break;
2853
2854                                 case -1:
2855                                         /* ----------
2856                                          * ABS(var1) < ABS(var2)
2857                                          * result = -(ABS(var2) - ABS(var1))
2858                                          * ----------
2859                                          */
2860                                         sub_abs(var2, var1, result);
2861                                         result->sign = NUMERIC_NEG;
2862                                         break;
2863                         }
2864                 }
2865         }
2866         else
2867         {
2868                 if (var2->sign == NUMERIC_POS)
2869                 {
2870                         /* ----------
2871                          * var1 is negative, var2 is positive
2872                          * Must compare absolute values
2873                          * ----------
2874                          */
2875                         switch (cmp_abs(var1, var2))
2876                         {
2877                                 case 0:
2878                                         /* ----------
2879                                          * ABS(var1) == ABS(var2)
2880                                          * result = ZERO
2881                                          * ----------
2882                                          */
2883                                         zero_var(result);
2884                                         result->rscale = MAX(var1->rscale, var2->rscale);
2885                                         result->dscale = MAX(var1->dscale, var2->dscale);
2886                                         break;
2887
2888                                 case 1:
2889                                         /* ----------
2890                                          * ABS(var1) > ABS(var2)
2891                                          * result = -(ABS(var1) - ABS(var2))
2892                                          * ----------
2893                                          */
2894                                         sub_abs(var1, var2, result);
2895                                         result->sign = NUMERIC_NEG;
2896                                         break;
2897
2898                                 case -1:
2899                                         /* ----------
2900                                          * ABS(var1) < ABS(var2)
2901                                          * result = +(ABS(var2) - ABS(var1))
2902                                          * ----------
2903                                          */
2904                                         sub_abs(var2, var1, result);
2905                                         result->sign = NUMERIC_POS;
2906                                         break;
2907                         }
2908                 }
2909                 else
2910                 {
2911                         /* ----------
2912                          * Both are negative
2913                          * result = -(ABS(var1) + ABS(var2))
2914                          * ----------
2915                          */
2916                         add_abs(var1, var2, result);
2917                         result->sign = NUMERIC_NEG;
2918                 }
2919         }
2920 }
2921
2922
2923 /* ----------
2924  * sub_var() -
2925  *
2926  *      Full version of sub functionality on variable level (handling signs).
2927  *      result might point to one of the operands too without danger.
2928  * ----------
2929  */
2930 static void
2931 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2932 {
2933         /* ----------
2934          * Decide on the signs of the two variables what to do
2935          * ----------
2936          */
2937         if (var1->sign == NUMERIC_POS)
2938         {
2939                 if (var2->sign == NUMERIC_NEG)
2940                 {
2941                         /* ----------
2942                          * var1 is positive, var2 is negative
2943                          * result = +(ABS(var1) + ABS(var2))
2944                          * ----------
2945                          */
2946                         add_abs(var1, var2, result);
2947                         result->sign = NUMERIC_POS;
2948                 }
2949                 else
2950                 {
2951                         /* ----------
2952                          * Both are positive
2953                          * Must compare absolute values
2954                          * ----------
2955                          */
2956                         switch (cmp_abs(var1, var2))
2957                         {
2958                                 case 0:
2959                                         /* ----------
2960                                          * ABS(var1) == ABS(var2)
2961                                          * result = ZERO
2962                                          * ----------
2963                                          */
2964                                         zero_var(result);
2965                                         result->rscale = MAX(var1->rscale, var2->rscale);
2966                                         result->dscale = MAX(var1->dscale, var2->dscale);
2967                                         break;
2968
2969                                 case 1:
2970                                         /* ----------
2971                                          * ABS(var1) > ABS(var2)
2972                                          * result = +(ABS(var1) - ABS(var2))
2973                                          * ----------
2974                                          */
2975                                         sub_abs(var1, var2, result);
2976                                         result->sign = NUMERIC_POS;
2977                                         break;
2978
2979                                 case -1:
2980                                         /* ----------
2981                                          * ABS(var1) < ABS(var2)
2982                                          * result = -(ABS(var2) - ABS(var1))
2983                                          * ----------
2984                                          */
2985                                         sub_abs(var2, var1, result);
2986                                         result->sign = NUMERIC_NEG;
2987                                         break;
2988                         }
2989                 }
2990         }
2991         else
2992         {
2993                 if (var2->sign == NUMERIC_NEG)
2994                 {
2995                         /* ----------
2996                          * Both are negative
2997                          * Must compare absolute values
2998                          * ----------
2999                          */
3000                         switch (cmp_abs(var1, var2))
3001                         {
3002                                 case 0:
3003                                         /* ----------
3004                                          * ABS(var1) == ABS(var2)
3005                                          * result = ZERO
3006                                          * ----------
3007                                          */
3008                                         zero_var(result);
3009                                         result->rscale = MAX(var1->rscale, var2->rscale);
3010                                         result->dscale = MAX(var1->dscale, var2->dscale);
3011                                         break;
3012
3013                                 case 1:
3014                                         /* ----------
3015                                          * ABS(var1) > ABS(var2)
3016                                          * result = -(ABS(var1) - ABS(var2))
3017                                          * ----------
3018                                          */
3019                                         sub_abs(var1, var2, result);
3020                                         result->sign = NUMERIC_NEG;
3021                                         break;
3022
3023                                 case -1:
3024                                         /* ----------
3025                                          * ABS(var1) < ABS(var2)
3026                                          * result = +(ABS(var2) - ABS(var1))
3027                                          * ----------
3028                                          */
3029                                         sub_abs(var2, var1, result);
3030                                         result->sign = NUMERIC_POS;
3031                                         break;
3032                         }
3033                 }
3034                 else
3035                 {
3036                         /* ----------
3037                          * var1 is negative, var2 is positive
3038                          * result = -(ABS(var1) + ABS(var2))
3039                          * ----------
3040                          */
3041                         add_abs(var1, var2, result);
3042                         result->sign = NUMERIC_NEG;
3043                 }
3044         }
3045 }
3046
3047
3048 /* ----------
3049  * mul_var() -
3050  *
3051  *      Multiplication on variable level. Product of var1 * var2 is stored
3052  *      in result.
3053  * ----------
3054  */
3055 static void
3056 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3057 {
3058         NumericDigit *res_buf;
3059         NumericDigit *res_digits;
3060         int                     res_ndigits;
3061         int                     res_weight;
3062         int                     res_sign;
3063         int                     i,
3064                                 ri,
3065                                 i1,
3066                                 i2;
3067         long            sum = 0;
3068
3069         res_weight = var1->weight + var2->weight + 2;
3070         res_ndigits = var1->ndigits + var2->ndigits + 1;
3071         if (var1->sign == var2->sign)
3072                 res_sign = NUMERIC_POS;
3073         else
3074                 res_sign = NUMERIC_NEG;
3075
3076         res_buf = digitbuf_alloc(res_ndigits);
3077         res_digits = res_buf;
3078         memset(res_digits, 0, res_ndigits);
3079
3080         ri = res_ndigits;
3081         for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
3082         {
3083                 sum = 0;
3084                 i = --ri;
3085
3086                 for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
3087                 {
3088                         sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
3089                         res_digits[i--] = sum % 10;
3090                         sum /= 10;
3091                 }
3092                 res_digits[i] = sum;
3093         }
3094
3095         i = res_weight + global_rscale + 2;
3096         if (i >= 0 && i < res_ndigits)
3097         {
3098                 sum = (res_digits[i] > 4) ? 1 : 0;
3099                 res_ndigits = i;
3100                 i--;
3101                 while (sum)
3102                 {
3103                         sum += res_digits[i];
3104                         res_digits[i--] = sum % 10;
3105                         sum /= 10;
3106                 }
3107         }
3108
3109         while (res_ndigits > 0 && *res_digits == 0)
3110         {
3111                 res_digits++;
3112                 res_weight--;
3113                 res_ndigits--;
3114         }
3115         while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3116                 res_ndigits--;
3117
3118         if (res_ndigits == 0)
3119         {
3120                 res_sign = NUMERIC_POS;
3121                 res_weight = 0;
3122         }
3123
3124         digitbuf_free(result->buf);
3125         result->buf = res_buf;
3126         result->digits = res_digits;
3127         result->ndigits = res_ndigits;
3128         result->weight = res_weight;
3129         result->rscale = global_rscale;
3130         result->sign = res_sign;
3131 }
3132
3133
3134 /* ----------
3135  * div_var() -
3136  *
3137  *      Division on variable level.
3138  * ----------
3139  */
3140 static void
3141 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3142 {
3143         NumericDigit *res_digits;
3144         int                     res_ndigits;
3145         int                     res_sign;
3146         int                     res_weight;
3147         NumericVar      dividend;
3148         NumericVar      divisor[10];
3149         int                     ndigits_tmp;
3150         int                     weight_tmp;
3151         int                     rscale_tmp;
3152         int                     ri;
3153         int                     i;
3154         long            guess;
3155         long            first_have;
3156         long            first_div;
3157         int                     first_nextdigit;
3158         int                     stat = 0;
3159
3160         /* ----------
3161          * First of all division by zero check
3162          * ----------
3163          */
3164         ndigits_tmp = var2->ndigits + 1;
3165         if (ndigits_tmp == 1)
3166                 elog(ERROR, "division by zero on numeric");
3167
3168         /* ----------
3169          * Determine the result sign, weight and number of digits to calculate
3170          * ----------
3171          */
3172         if (var1->sign == var2->sign)
3173                 res_sign = NUMERIC_POS;
3174         else
3175                 res_sign = NUMERIC_NEG;
3176         res_weight = var1->weight - var2->weight + 1;
3177         res_ndigits = global_rscale + res_weight;
3178         if (res_ndigits <= 0)
3179                 res_ndigits = 1;
3180
3181         /* ----------
3182          * Now result zero check
3183          * ----------
3184          */
3185         if (var1->ndigits == 0)
3186         {
3187                 zero_var(result);
3188                 result->rscale = global_rscale;
3189                 return;
3190         }
3191
3192         /* ----------
3193          * Initialize local variables
3194          * ----------
3195          */
3196         init_var(&dividend);
3197         for (i = 1; i < 10; i++)
3198                 init_var(&divisor[i]);
3199
3200         /* ----------
3201          * Make a copy of the divisor which has one leading zero digit
3202          * ----------
3203          */
3204         divisor[1].ndigits = ndigits_tmp;
3205         divisor[1].rscale = var2->ndigits;
3206         divisor[1].sign = NUMERIC_POS;
3207         divisor[1].buf = digitbuf_alloc(ndigits_tmp);
3208         divisor[1].digits = divisor[1].buf;
3209         divisor[1].digits[0] = 0;
3210         memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
3211
3212         /* ----------
3213          * Make a copy of the dividend
3214          * ----------
3215          */
3216         dividend.ndigits = var1->ndigits;
3217         dividend.weight = 0;
3218         dividend.rscale = var1->ndigits;
3219         dividend.sign = NUMERIC_POS;
3220         dividend.buf = digitbuf_alloc(var1->ndigits);
3221         dividend.digits = dividend.buf;
3222         memcpy(dividend.digits, var1->digits, var1->ndigits);
3223
3224         /* ----------
3225          * Setup the result
3226          * ----------
3227          */
3228         digitbuf_free(result->buf);
3229         result->buf = digitbuf_alloc(res_ndigits + 2);
3230         res_digits = result->buf;
3231         result->digits = res_digits;
3232         result->ndigits = res_ndigits;
3233         result->weight = res_weight;
3234         result->rscale = global_rscale;
3235         result->sign = res_sign;
3236         res_digits[0] = 0;
3237
3238         first_div = divisor[1].digits[1] * 10;
3239         if (ndigits_tmp > 2)
3240                 first_div += divisor[1].digits[2];
3241
3242         first_have = 0;
3243         first_nextdigit = 0;
3244
3245         weight_tmp = 1;
3246         rscale_tmp = divisor[1].rscale;
3247
3248         for (ri = 0; ri <= res_ndigits; ri++)
3249         {
3250                 first_have = first_have * 10;
3251                 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
3252                         first_have += dividend.digits[first_nextdigit];
3253                 first_nextdigit++;
3254
3255                 guess = (first_have * 10) / first_div + 1;
3256                 if (guess > 9)
3257                         guess = 9;
3258
3259                 while (guess > 0)
3260                 {
3261                         if (divisor[guess].buf == NULL)
3262                         {
3263                                 int                     i;
3264                                 long            sum = 0;
3265
3266                                 memcpy(&divisor[guess], &divisor[1], sizeof(NumericVar));
3267                                 divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
3268                                 divisor[guess].digits = divisor[guess].buf;
3269                                 for (i = divisor[1].ndigits - 1; i >= 0; i--)
3270                                 {
3271                                         sum += divisor[1].digits[i] * guess;
3272                                         divisor[guess].digits[i] = sum % 10;
3273                                         sum /= 10;
3274                                 }
3275                         }
3276
3277                         divisor[guess].weight = weight_tmp;
3278                         divisor[guess].rscale = rscale_tmp;
3279
3280                         stat = cmp_abs(&dividend, &divisor[guess]);
3281                         if (stat >= 0)
3282                                 break;
3283
3284                         guess--;
3285                 }
3286
3287                 res_digits[ri + 1] = guess;
3288                 if (stat == 0)
3289                 {
3290                         ri++;
3291                         break;
3292                 }
3293
3294                 weight_tmp--;
3295                 rscale_tmp++;
3296
3297                 if (guess == 0)
3298                         continue;
3299
3300                 sub_abs(&dividend, &divisor[guess], &dividend);
3301
3302                 first_nextdigit = dividend.weight - weight_tmp;
3303                 first_have = 0;
3304                 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
3305                         first_have = dividend.digits[first_nextdigit];
3306                 first_nextdigit++;
3307         }
3308
3309         result->ndigits = ri + 1;
3310         if (ri == res_ndigits + 1)
3311         {
3312                 int                     carry = (res_digits[ri] > 4) ? 1 : 0;
3313
3314                 result->ndigits = ri;
3315                 res_digits[ri] = 0;
3316
3317                 while (carry && ri > 0)
3318                 {
3319                         carry += res_digits[--ri];
3320                         res_digits[ri] = carry % 10;
3321                         carry /= 10;
3322                 }
3323         }
3324
3325         while (result->ndigits > 0 && *(result->digits) == 0)
3326         {
3327                 (result->digits)++;
3328                 (result->weight)--;
3329                 (result->ndigits)--;
3330         }
3331         while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
3332                 (result->ndigits)--;
3333         if (result->ndigits == 0)
3334                 result->sign = NUMERIC_POS;
3335
3336         /*
3337          * Tidy up
3338          */
3339         digitbuf_free(dividend.buf);
3340         for (i = 1; i < 10; i++)
3341                 digitbuf_free(divisor[i].buf);
3342 }
3343
3344
3345 /* ----------
3346  * mod_var() -
3347  *
3348  *      Calculate the modulo of two numerics at variable level
3349  * ----------
3350  */
3351 static void
3352 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3353 {
3354         NumericVar      tmp;
3355         int                     save_global_rscale;
3356
3357         init_var(&tmp);
3358
3359         /* ----------
3360          * We do this using the equation
3361          *              mod(x,y) = x - trunc(x/y)*y
3362          * We fiddle a bit with global_rscale to control result precision.
3363          * ----------
3364          */
3365         save_global_rscale = global_rscale;
3366         global_rscale = var2->rscale + 2;
3367
3368         div_var(var1, var2, &tmp);
3369
3370         /* do trunc() by forgetting digits to the right of the decimal point */
3371         tmp.ndigits = MAX(0, MIN(tmp.ndigits, tmp.weight + 1));
3372         tmp.rscale = var2->rscale;
3373
3374         global_rscale = var2->rscale;
3375         mul_var(var2, &tmp, &tmp);
3376
3377         sub_var(var1, &tmp, result);
3378
3379         global_rscale = save_global_rscale;
3380         free_var(&tmp);
3381 }
3382
3383
3384 /* ----------
3385  * ceil_var() -
3386  *
3387  *      Return the smallest integer greater than or equal to the argument
3388  *      on variable level
3389  * ----------
3390  */
3391 static void
3392 ceil_var(NumericVar *var, NumericVar *result)
3393 {
3394         NumericVar      tmp;
3395
3396         init_var(&tmp);
3397         set_var_from_var(var, &tmp);
3398
3399         tmp.rscale = 0;
3400         tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3401         if (tmp.sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
3402                 add_var(&tmp, &const_one, &tmp);
3403
3404         set_var_from_var(&tmp, result);
3405         free_var(&tmp);
3406 }
3407
3408
3409 /* ----------
3410  * floor_var() -
3411  *
3412  *      Return the largest integer equal to or less than the argument
3413  *      on variable level
3414  * ----------
3415  */
3416 static void
3417 floor_var(NumericVar *var, NumericVar *result)
3418 {
3419         NumericVar      tmp;
3420
3421         init_var(&tmp);
3422         set_var_from_var(var, &tmp);
3423
3424         tmp.rscale = 0;
3425         tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3426         if (tmp.sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
3427                 sub_var(&tmp, &const_one, &tmp);
3428
3429         set_var_from_var(&tmp, result);
3430         free_var(&tmp);
3431 }
3432
3433
3434 /* ----------
3435  * sqrt_var() -
3436  *
3437  *      Compute the square root of x using Newtons algorithm
3438  * ----------
3439  */
3440 static void
3441 sqrt_var(NumericVar *arg, NumericVar *result)
3442 {
3443         NumericVar      tmp_arg;
3444         NumericVar      tmp_val;
3445         NumericVar      last_val;
3446         int                     res_rscale;
3447         int                     save_global_rscale;
3448         int                     stat;
3449
3450         save_global_rscale = global_rscale;
3451         global_rscale += 8;
3452         res_rscale = global_rscale;
3453
3454         stat = cmp_var(arg, &const_zero);
3455         if (stat == 0)
3456         {
3457                 set_var_from_var(&const_zero, result);
3458                 result->rscale = res_rscale;
3459                 result->sign = NUMERIC_POS;
3460                 return;
3461         }
3462
3463         if (stat < 0)
3464                 elog(ERROR, "math error on numeric - cannot compute SQRT of negative value");
3465
3466         init_var(&tmp_arg);
3467         init_var(&tmp_val);
3468         init_var(&last_val);
3469
3470         set_var_from_var(arg, &tmp_arg);
3471         set_var_from_var(result, &last_val);
3472
3473         /* ----------
3474          * Initialize the result to the first guess
3475          * ----------
3476          */
3477         digitbuf_free(result->buf);
3478         result->buf = digitbuf_alloc(1);
3479         result->digits = result->buf;
3480         result->digits[0] = tmp_arg.digits[0] / 2;
3481         if (result->digits[0] == 0)
3482                 result->digits[0] = 1;
3483         result->ndigits = 1;
3484         result->weight = tmp_arg.weight / 2;
3485         result->rscale = res_rscale;
3486         result->sign = NUMERIC_POS;
3487
3488         for (;;)
3489         {
3490                 div_var(&tmp_arg, result, &tmp_val);
3491
3492                 add_var(result, &tmp_val, result);
3493                 div_var(result, &const_two, result);
3494
3495                 if (cmp_var(&last_val, result) == 0)
3496                         break;
3497                 set_var_from_var(result, &last_val);
3498         }
3499
3500         free_var(&last_val);
3501         free_var(&tmp_val);
3502         free_var(&tmp_arg);
3503
3504         global_rscale = save_global_rscale;
3505         div_var(result, &const_one, result);
3506 }
3507
3508
3509 /* ----------
3510  * exp_var() -
3511  *
3512  *      Raise e to the power of x
3513  * ----------
3514  */
3515 static void
3516 exp_var(NumericVar *arg, NumericVar *result)
3517 {
3518         NumericVar      x;
3519         NumericVar      xpow;
3520         NumericVar      ifac;
3521         NumericVar      elem;
3522         NumericVar      ni;
3523         int                     d;
3524         int                     i;
3525         int                     ndiv2 = 0;
3526         bool            xneg = FALSE;
3527         int                     save_global_rscale;
3528
3529         init_var(&x);
3530         init_var(&xpow);
3531         init_var(&ifac);
3532         init_var(&elem);
3533         init_var(&ni);
3534
3535         set_var_from_var(arg, &x);
3536
3537         if (x.sign == NUMERIC_NEG)
3538         {
3539                 xneg = TRUE;
3540                 x.sign = NUMERIC_POS;
3541         }
3542
3543         save_global_rscale = global_rscale;
3544         global_rscale = 0;
3545         for (i = x.weight, d = 0; i >= 0; i--, d++)
3546         {
3547                 global_rscale *= 10;
3548                 if (d < x.ndigits)
3549                         global_rscale += x.digits[d];
3550                 if (global_rscale >= 1000)
3551                         elog(ERROR, "argument for EXP() too big");
3552         }
3553
3554         global_rscale = global_rscale / 2 + save_global_rscale + 8;
3555
3556         while (cmp_var(&x, &const_one) > 0)
3557         {
3558                 ndiv2++;
3559                 global_rscale++;
3560                 div_var(&x, &const_two, &x);
3561         }
3562
3563         add_var(&const_one, &x, result);
3564         set_var_from_var(&x, &xpow);
3565         set_var_from_var(&const_one, &ifac);
3566         set_var_from_var(&const_one, &ni);
3567
3568         for (i = 2;; i++)
3569         {
3570                 add_var(&ni, &const_one, &ni);
3571                 mul_var(&xpow, &x, &xpow);
3572                 mul_var(&ifac, &ni, &ifac);
3573                 div_var(&xpow, &ifac, &elem);
3574
3575                 if (elem.ndigits == 0)
3576                         break;
3577
3578                 add_var(result, &elem, result);
3579         }
3580
3581         while (ndiv2-- > 0)
3582                 mul_var(result, result, result);
3583
3584         global_rscale = save_global_rscale;
3585         if (xneg)
3586                 div_var(&const_one, result, result);
3587         else
3588                 div_var(result, &const_one, result);
3589
3590         result->sign = NUMERIC_POS;
3591
3592         free_var(&x);
3593         free_var(&xpow);
3594         free_var(&ifac);
3595         free_var(&elem);
3596         free_var(&ni);
3597 }
3598
3599
3600 /* ----------
3601  * ln_var() -
3602  *
3603  *      Compute the natural log of x
3604  * ----------
3605  */
3606 static void
3607 ln_var(NumericVar *arg, NumericVar *result)
3608 {
3609         NumericVar      x;
3610         NumericVar      xx;
3611         NumericVar      ni;
3612         NumericVar      elem;
3613         NumericVar      fact;
3614         int                     i;
3615         int                     save_global_rscale;
3616
3617         if (cmp_var(arg, &const_zero) <= 0)
3618                 elog(ERROR, "math error on numeric - cannot compute LN of value <= zero");
3619
3620         save_global_rscale = global_rscale;
3621         global_rscale += 8;
3622
3623         init_var(&x);
3624         init_var(&xx);
3625         init_var(&ni);
3626         init_var(&elem);
3627         init_var(&fact);
3628
3629         set_var_from_var(&const_two, &fact);
3630         set_var_from_var(arg, &x);
3631
3632         while (cmp_var(&x, &const_two) >= 0)
3633         {
3634                 sqrt_var(&x, &x);
3635                 mul_var(&fact, &const_two, &fact);
3636         }
3637         set_var_from_str("0.5", &elem);
3638         while (cmp_var(&x, &elem) <= 0)
3639         {
3640                 sqrt_var(&x, &x);
3641                 mul_var(&fact, &const_two, &fact);
3642         }
3643
3644         sub_var(&x, &const_one, result);
3645         add_var(&x, &const_one, &elem);
3646         div_var(result, &elem, result);
3647         set_var_from_var(result, &xx);
3648         mul_var(result, result, &x);
3649
3650         set_var_from_var(&const_one, &ni);
3651
3652         for (i = 2;; i++)
3653         {
3654                 add_var(&ni, &const_two, &ni);
3655                 mul_var(&xx, &x, &xx);
3656                 div_var(&xx, &ni, &elem);
3657
3658                 if (cmp_var(&elem, &const_zero) == 0)
3659                         break;
3660
3661                 add_var(result, &elem, result);
3662         }
3663
3664         global_rscale = save_global_rscale;
3665         mul_var(result, &fact, result);
3666
3667         free_var(&x);
3668         free_var(&xx);
3669         free_var(&ni);
3670         free_var(&elem);
3671         free_var(&fact);
3672 }
3673
3674
3675 /* ----------
3676  * log_var() -
3677  *
3678  *      Compute the logarithm of x in a given base
3679  * ----------
3680  */
3681 static void
3682 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
3683 {
3684         NumericVar      ln_base;
3685         NumericVar      ln_num;
3686
3687         global_rscale += 8;
3688
3689         init_var(&ln_base);
3690         init_var(&ln_num);
3691
3692         ln_var(base, &ln_base);
3693         ln_var(num, &ln_num);
3694
3695         global_rscale -= 8;
3696
3697         div_var(&ln_num, &ln_base, result);
3698
3699         free_var(&ln_num);
3700         free_var(&ln_base);
3701 }
3702
3703
3704 /* ----------
3705  * power_var() -
3706  *
3707  *      Raise base to the power of exp
3708  * ----------
3709  */
3710 static void
3711 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
3712 {
3713         NumericVar      ln_base;
3714         NumericVar      ln_num;
3715         int                     save_global_rscale;
3716
3717         save_global_rscale = global_rscale;
3718         global_rscale += global_rscale / 3 + 8;
3719
3720         init_var(&ln_base);
3721         init_var(&ln_num);
3722
3723         ln_var(base, &ln_base);
3724         mul_var(&ln_base, exp, &ln_num);
3725
3726         global_rscale = save_global_rscale;
3727
3728         exp_var(&ln_num, result);
3729
3730         free_var(&ln_num);
3731         free_var(&ln_base);
3732
3733 }
3734
3735
3736 /* ----------------------------------------------------------------------
3737  *
3738  * Following are the lowest level functions that operate unsigned
3739  * on the variable level
3740  *
3741  * ----------------------------------------------------------------------
3742  */
3743
3744
3745 /* ----------
3746  * cmp_abs() -
3747  *
3748  *      Compare the absolute values of var1 and var2
3749  *      Returns:        -1 for ABS(var1) < ABS(var2)
3750  *                              0  for ABS(var1) == ABS(var2)
3751  *                              1  for ABS(var1) > ABS(var2)
3752  * ----------
3753  */
3754 static int
3755 cmp_abs(NumericVar *var1, NumericVar *var2)
3756 {
3757         int                     i1 = 0;
3758         int                     i2 = 0;
3759         int                     w1 = var1->weight;
3760         int                     w2 = var2->weight;
3761         int                     stat;
3762
3763         while (w1 > w2 && i1 < var1->ndigits)
3764         {
3765                 if (var1->digits[i1++] != 0)
3766                         return 1;
3767                 w1--;
3768         }
3769         while (w2 > w1 && i2 < var2->ndigits)
3770         {
3771                 if (var2->digits[i2++] != 0)
3772                         return -1;
3773                 w2--;
3774         }
3775
3776         if (w1 == w2)
3777         {
3778                 while (i1 < var1->ndigits && i2 < var2->ndigits)
3779                 {
3780                         stat = var1->digits[i1++] - var2->digits[i2++];
3781                         if (stat)
3782                         {
3783                                 if (stat > 0)
3784                                         return 1;
3785                                 return -1;
3786                         }
3787                 }
3788         }
3789
3790         while (i1 < var1->ndigits)
3791         {
3792                 if (var1->digits[i1++] != 0)
3793                         return 1;
3794         }
3795         while (i2 < var2->ndigits)
3796         {
3797                 if (var2->digits[i2++] != 0)
3798                         return -1;
3799         }
3800
3801         return 0;
3802 }
3803
3804
3805 /* ----------
3806  * add_abs() -
3807  *
3808  *      Add the absolute values of two variables into result.
3809  *      result might point to one of the operands without danger.
3810  * ----------
3811  */
3812 static void
3813 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3814 {
3815         NumericDigit *res_buf;
3816         NumericDigit *res_digits;
3817         int                     res_ndigits;
3818         int                     res_weight;
3819         int                     res_rscale;
3820         int                     res_dscale;
3821         int                     i,
3822                                 i1,
3823                                 i2;
3824         int                     carry = 0;
3825
3826         /* copy these values into local vars for speed in inner loop */
3827         int                     var1ndigits = var1->ndigits;
3828         int                     var2ndigits = var2->ndigits;
3829         NumericDigit *var1digits = var1->digits;
3830         NumericDigit *var2digits = var2->digits;
3831
3832         res_weight = MAX(var1->weight, var2->weight) + 1;
3833         res_rscale = MAX(var1->rscale, var2->rscale);
3834         res_dscale = MAX(var1->dscale, var2->dscale);
3835         res_ndigits = res_rscale + res_weight + 1;
3836         if (res_ndigits <= 0)
3837                 res_ndigits = 1;
3838
3839         res_buf = digitbuf_alloc(res_ndigits);
3840         res_digits = res_buf;
3841
3842         i1 = res_rscale + var1->weight + 1;
3843         i2 = res_rscale + var2->weight + 1;
3844         for (i = res_ndigits - 1; i >= 0; i--)
3845         {
3846                 i1--;
3847                 i2--;
3848                 if (i1 >= 0 && i1 < var1ndigits)
3849                         carry += var1digits[i1];
3850                 if (i2 >= 0 && i2 < var2ndigits)
3851                         carry += var2digits[i2];
3852
3853                 if (carry >= 10)
3854                 {
3855                         res_digits[i] = carry - 10;
3856                         carry = 1;
3857                 }
3858                 else
3859                 {
3860                         res_digits[i] = carry;
3861                         carry = 0;
3862                 }
3863         }
3864
3865         Assert(carry == 0);                     /* else we failed to allow for carry out */
3866
3867         while (res_ndigits > 0 && *res_digits == 0)
3868         {
3869                 res_digits++;
3870                 res_weight--;
3871                 res_ndigits--;
3872         }
3873         while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3874                 res_ndigits--;
3875
3876         if (res_ndigits == 0)
3877                 res_weight = 0;
3878
3879         digitbuf_free(result->buf);
3880         result->ndigits = res_ndigits;
3881         result->buf = res_buf;
3882         result->digits = res_digits;
3883         result->weight = res_weight;
3884         result->rscale = res_rscale;
3885         result->dscale = res_dscale;
3886 }
3887
3888
3889 /* ----------
3890  * sub_abs() -
3891  *
3892  *      Subtract the absolute value of var2 from the absolute value of var1
3893  *      and store in result. result might point to one of the operands
3894  *      without danger.
3895  *
3896  *      ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
3897  * ----------
3898  */
3899 static void
3900 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3901 {
3902         NumericDigit *res_buf;
3903         NumericDigit *res_digits;
3904         int                     res_ndigits;
3905         int                     res_weight;
3906         int                     res_rscale;
3907         int                     res_dscale;
3908         int                     i,
3909                                 i1,
3910                                 i2;
3911         int                     borrow = 0;
3912
3913         /* copy these values into local vars for speed in inner loop */
3914         int                     var1ndigits = var1->ndigits;
3915         int                     var2ndigits = var2->ndigits;
3916         NumericDigit *var1digits = var1->digits;
3917         NumericDigit *var2digits = var2->digits;
3918
3919         res_weight = var1->weight;
3920         res_rscale = MAX(var1->rscale, var2->rscale);
3921         res_dscale = MAX(var1->dscale, var2->dscale);
3922         res_ndigits = res_rscale + res_weight + 1;
3923         if (res_ndigits <= 0)
3924                 res_ndigits = 1;
3925
3926         res_buf = digitbuf_alloc(res_ndigits);
3927         res_digits = res_buf;
3928
3929         i1 = res_rscale + var1->weight + 1;
3930         i2 = res_rscale + var2->weight + 1;
3931         for (i = res_ndigits - 1; i >= 0; i--)
3932         {
3933                 i1--;
3934                 i2--;
3935                 if (i1 >= 0 && i1 < var1ndigits)
3936                         borrow += var1digits[i1];
3937                 if (i2 >= 0 && i2 < var2ndigits)
3938                         borrow -= var2digits[i2];
3939
3940                 if (borrow < 0)
3941                 {
3942                         res_digits[i] = borrow + 10;
3943                         borrow = -1;
3944                 }
3945                 else
3946                 {
3947                         res_digits[i] = borrow;
3948                         borrow = 0;
3949                 }
3950         }
3951
3952         Assert(borrow == 0);            /* else caller gave us var1 < var2 */
3953
3954         while (res_ndigits > 0 && *res_digits == 0)
3955         {
3956                 res_digits++;
3957                 res_weight--;
3958                 res_ndigits--;
3959         }
3960         while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3961                 res_ndigits--;
3962
3963         if (res_ndigits == 0)
3964                 res_weight = 0;
3965
3966         digitbuf_free(result->buf);
3967         result->ndigits = res_ndigits;
3968         result->buf = res_buf;
3969         result->digits = res_digits;
3970         result->weight = res_weight;
3971         result->rscale = res_rscale;
3972         result->dscale = res_dscale;
3973 }