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