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