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