1 #include "postgres_fe.h"
6 #include "pgtypes_error.h"
8 #define Max(x, y) ((x) > (y) ? (x) : (y))
9 #define Min(x, y) ((x) < (y) ? (x) : (y))
11 #define init_var(v) memset(v,0,sizeof(Numeric))
13 #define digitbuf_alloc(size) ((NumericDigit *) pgtypes_alloc(size))
14 #define digitbuf_free(buf) \
20 #include "pgtypes_numeric.h"
26 * Do bounds checking and rounding according to the attributes
31 apply_typmod(Numeric *var, long typmod)
38 /* Do nothing if we have a default typmod (-1) */
39 if (typmod < (long) (VARHDRSZ))
43 precision = (typmod >> 16) & 0xffff;
44 scale = typmod & 0xffff;
45 maxweight = precision - scale;
47 /* Round to target scale */
48 i = scale + var->weight + 1;
49 if (i >= 0 && var->ndigits > i)
51 int carry = (var->digits[i] > 4) ? 1 : 0;
57 carry += var->digits[--i];
58 var->digits[i] = carry % 10;
70 var->ndigits = Max(0, Min(i, var->ndigits));
73 * Check for overflow - note we can't do this before rounding, because
74 * rounding could raise the weight. Also note that the var's weight
75 * could be inflated by leading zeroes, which will be stripped before
76 * storage but perhaps might not have been yet. In any case, we must
77 * recognize a true zero, whose weight doesn't mean anything.
79 if (var->weight >= maxweight)
81 /* Determine true weight; and check for all-zero result */
82 int tweight = var->weight;
84 for (i = 0; i < var->ndigits; i++)
91 if (tweight >= maxweight && i < var->ndigits)
93 errno = PGTYPES_NUM_OVERFLOW;
107 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
111 alloc_var(Numeric *var, int ndigits)
113 digitbuf_free(var->buf);
114 var->buf = digitbuf_alloc(ndigits + 1);
115 if (var->buf == NULL)
118 var->digits = var->buf + 1;
119 var->ndigits = ndigits;
124 PGTYPESnumeric_new(void)
128 if ((var = (Numeric *) pgtypes_alloc(sizeof(Numeric))) == NULL)
131 if (alloc_var(var, 0) < 0)
140 * Parse a string and put the number into a variable
144 set_var_from_str(char *str, char **ptr, Numeric *dest)
146 bool have_dp = FALSE;
152 if (!isspace((unsigned char) *(*ptr)))
157 if (alloc_var(dest, strlen((*ptr))) < 0)
161 dest->sign = NUMERIC_POS;
166 dest->sign = NUMERIC_POS;
171 dest->sign = NUMERIC_NEG;
182 if (!isdigit((unsigned char) *(*ptr)))
184 errno = PGTYPES_NUM_BAD_NUMERIC;
190 if (isdigit((unsigned char) *(*ptr)))
192 dest->digits[i++] = *(*ptr)++ - '0';
198 else if (*(*ptr) == '.')
202 errno = PGTYPES_NUM_BAD_NUMERIC;
213 /* Handle exponent, if any */
214 if (*(*ptr) == 'e' || *(*ptr) == 'E')
220 exponent = strtol((*ptr), &endptr, 10);
221 if (endptr == (*ptr))
223 errno = PGTYPES_NUM_BAD_NUMERIC;
227 if (exponent > NUMERIC_MAX_PRECISION ||
228 exponent < -NUMERIC_MAX_PRECISION)
230 errno = PGTYPES_NUM_BAD_NUMERIC;
233 dest->weight += (int) exponent;
234 dest->dscale -= (int) exponent;
235 if (dest->dscale < 0)
239 /* Should be nothing left but spaces */
242 if (!isspace((unsigned char) *(*ptr)))
244 errno = PGTYPES_NUM_BAD_NUMERIC;
250 /* Strip any leading zeroes */
251 while (dest->ndigits > 0 && *(dest->digits) == 0)
257 if (dest->ndigits == 0)
260 dest->rscale = dest->dscale;
266 * get_str_from_var() -
268 * Convert a var to text representation (guts of numeric_out).
269 * CAUTION: var's contents may be modified by rounding!
273 get_str_from_var(Numeric *var, int dscale)
281 * Check if we must round up before printing the value and do so.
283 i = dscale + var->weight + 1;
284 if (i >= 0 && var->ndigits > i)
286 int carry = (var->digits[i] > 4) ? 1 : 0;
292 carry += var->digits[--i];
293 var->digits[i] = carry % 10;
305 var->ndigits = Max(0, Min(i, var->ndigits));
308 * Allocate space for the result
310 if ((str = (char *) pgtypes_alloc(Max(0, dscale) + Max(0, var->weight) + 4)) == NULL)
315 * Output a dash for negative values
317 if (var->sign == NUMERIC_NEG)
321 * Output all digits before the decimal point
323 i = Max(var->weight, 0);
328 if (i <= var->weight && d < var->ndigits)
329 *cp++ = var->digits[d++] + '0';
336 * If requested, output a decimal point and all the digits that follow
344 if (i <= var->weight && d < var->ndigits)
345 *cp++ = var->digits[d++] + '0';
353 * terminate the string and return it
360 PGTYPESnumeric_from_asc(char *str, char **endptr)
362 Numeric *value = (Numeric *) pgtypes_alloc(sizeof(Numeric));
369 char **ptr = (endptr != NULL) ? endptr : &realptr;
374 ret = set_var_from_str(str, ptr, value);
379 ret = apply_typmod(value, typmod);
387 PGTYPESnumeric_to_asc(Numeric *num, int dscale)
390 dscale = num->dscale;
392 return (get_str_from_var(num, dscale));
398 * Set a variable to ZERO.
399 * Note: rscale and dscale are not touched.
403 zero_var(Numeric *var)
405 digitbuf_free(var->buf);
409 var->weight = 0; /* by convention; doesn't really matter */
410 var->sign = NUMERIC_POS; /* anything but NAN... */
414 PGTYPESnumeric_free(Numeric *var)
416 digitbuf_free(var->buf);
423 * Compare the absolute values of var1 and var2
424 * Returns: -1 for ABS(var1) < ABS(var2)
425 * 0 for ABS(var1) == ABS(var2)
426 * 1 for ABS(var1) > ABS(var2)
430 cmp_abs(Numeric *var1, Numeric *var2)
434 int w1 = var1->weight;
435 int w2 = var2->weight;
438 while (w1 > w2 && i1 < var1->ndigits)
440 if (var1->digits[i1++] != 0)
444 while (w2 > w1 && i2 < var2->ndigits)
446 if (var2->digits[i2++] != 0)
453 while (i1 < var1->ndigits && i2 < var2->ndigits)
455 stat = var1->digits[i1++] - var2->digits[i2++];
465 while (i1 < var1->ndigits)
467 if (var1->digits[i1++] != 0)
470 while (i2 < var2->ndigits)
472 if (var2->digits[i2++] != 0)
483 * Add the absolute values of two variables into result.
484 * result might point to one of the operands without danger.
488 add_abs(Numeric *var1, Numeric *var2, Numeric *result)
490 NumericDigit *res_buf;
491 NumericDigit *res_digits;
501 /* copy these values into local vars for speed in inner loop */
502 int var1ndigits = var1->ndigits;
503 int var2ndigits = var2->ndigits;
504 NumericDigit *var1digits = var1->digits;
505 NumericDigit *var2digits = var2->digits;
507 res_weight = Max(var1->weight, var2->weight) + 1;
508 res_rscale = Max(var1->rscale, var2->rscale);
509 res_dscale = Max(var1->dscale, var2->dscale);
510 res_ndigits = res_rscale + res_weight + 1;
511 if (res_ndigits <= 0)
514 if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
516 res_digits = res_buf;
518 i1 = res_rscale + var1->weight + 1;
519 i2 = res_rscale + var2->weight + 1;
520 for (i = res_ndigits - 1; i >= 0; i--)
524 if (i1 >= 0 && i1 < var1ndigits)
525 carry += var1digits[i1];
526 if (i2 >= 0 && i2 < var2ndigits)
527 carry += var2digits[i2];
531 res_digits[i] = carry - 10;
536 res_digits[i] = carry;
541 while (res_ndigits > 0 && *res_digits == 0)
547 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
550 if (res_ndigits == 0)
553 digitbuf_free(result->buf);
554 result->ndigits = res_ndigits;
555 result->buf = res_buf;
556 result->digits = res_digits;
557 result->weight = res_weight;
558 result->rscale = res_rscale;
559 result->dscale = res_dscale;
568 * Subtract the absolute value of var2 from the absolute value of var1
569 * and store in result. result might point to one of the operands
572 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
576 sub_abs(Numeric *var1, Numeric *var2, Numeric *result)
578 NumericDigit *res_buf;
579 NumericDigit *res_digits;
589 /* copy these values into local vars for speed in inner loop */
590 int var1ndigits = var1->ndigits;
591 int var2ndigits = var2->ndigits;
592 NumericDigit *var1digits = var1->digits;
593 NumericDigit *var2digits = var2->digits;
595 res_weight = var1->weight;
596 res_rscale = Max(var1->rscale, var2->rscale);
597 res_dscale = Max(var1->dscale, var2->dscale);
598 res_ndigits = res_rscale + res_weight + 1;
599 if (res_ndigits <= 0)
602 if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
604 res_digits = res_buf;
606 i1 = res_rscale + var1->weight + 1;
607 i2 = res_rscale + var2->weight + 1;
608 for (i = res_ndigits - 1; i >= 0; i--)
612 if (i1 >= 0 && i1 < var1ndigits)
613 borrow += var1digits[i1];
614 if (i2 >= 0 && i2 < var2ndigits)
615 borrow -= var2digits[i2];
619 res_digits[i] = borrow + 10;
624 res_digits[i] = borrow;
629 while (res_ndigits > 0 && *res_digits == 0)
635 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
638 if (res_ndigits == 0)
641 digitbuf_free(result->buf);
642 result->ndigits = res_ndigits;
643 result->buf = res_buf;
644 result->digits = res_digits;
645 result->weight = res_weight;
646 result->rscale = res_rscale;
647 result->dscale = res_dscale;
655 * Full version of add functionality on variable level (handling signs).
656 * result might point to one of the operands too without danger.
660 PGTYPESnumeric_add(Numeric *var1, Numeric *var2, Numeric *result)
663 * Decide on the signs of the two variables what to do
665 if (var1->sign == NUMERIC_POS)
667 if (var2->sign == NUMERIC_POS)
670 * Both are positive result = +(ABS(var1) + ABS(var2))
672 if (add_abs(var1, var2, result) != 0)
674 result->sign = NUMERIC_POS;
679 * var1 is positive, var2 is negative Must compare absolute
682 switch (cmp_abs(var1, var2))
686 * ABS(var1) == ABS(var2)
691 result->rscale = Max(var1->rscale, var2->rscale);
692 result->dscale = Max(var1->dscale, var2->dscale);
697 * ABS(var1) > ABS(var2)
698 * result = +(ABS(var1) - ABS(var2))
701 if (sub_abs(var1, var2, result) != 0)
703 result->sign = NUMERIC_POS;
708 * ABS(var1) < ABS(var2)
709 * result = -(ABS(var2) - ABS(var1))
712 if (sub_abs(var2, var1, result) != 0)
714 result->sign = NUMERIC_NEG;
721 if (var2->sign == NUMERIC_POS)
724 * var1 is negative, var2 is positive
725 * Must compare absolute values
728 switch (cmp_abs(var1, var2))
732 * ABS(var1) == ABS(var2)
737 result->rscale = Max(var1->rscale, var2->rscale);
738 result->dscale = Max(var1->dscale, var2->dscale);
743 * ABS(var1) > ABS(var2)
744 * result = -(ABS(var1) - ABS(var2))
747 if (sub_abs(var1, var2, result) != 0)
749 result->sign = NUMERIC_NEG;
754 * ABS(var1) < ABS(var2)
755 * result = +(ABS(var2) - ABS(var1))
758 if (sub_abs(var2, var1, result) != 0)
760 result->sign = NUMERIC_POS;
768 * result = -(ABS(var1) + ABS(var2))
771 if (add_abs(var1, var2, result) != 0)
773 result->sign = NUMERIC_NEG;
784 * Full version of sub functionality on variable level (handling signs).
785 * result might point to one of the operands too without danger.
789 PGTYPESnumeric_sub(Numeric *var1, Numeric *var2, Numeric *result)
792 * Decide on the signs of the two variables what to do
794 if (var1->sign == NUMERIC_POS)
796 if (var2->sign == NUMERIC_NEG)
799 * var1 is positive, var2 is negative
800 * result = +(ABS(var1) + ABS(var2))
803 if (add_abs(var1, var2, result) != 0)
805 result->sign = NUMERIC_POS;
811 * Must compare absolute values
814 switch (cmp_abs(var1, var2))
818 * ABS(var1) == ABS(var2)
823 result->rscale = Max(var1->rscale, var2->rscale);
824 result->dscale = Max(var1->dscale, var2->dscale);
829 * ABS(var1) > ABS(var2)
830 * result = +(ABS(var1) - ABS(var2))
833 if (sub_abs(var1, var2, result) != 0)
835 result->sign = NUMERIC_POS;
840 * ABS(var1) < ABS(var2)
841 * result = -(ABS(var2) - ABS(var1))
844 if (sub_abs(var2, var1, result) != 0)
846 result->sign = NUMERIC_NEG;
853 if (var2->sign == NUMERIC_NEG)
857 * Must compare absolute values
860 switch (cmp_abs(var1, var2))
864 * ABS(var1) == ABS(var2)
869 result->rscale = Max(var1->rscale, var2->rscale);
870 result->dscale = Max(var1->dscale, var2->dscale);
875 * ABS(var1) > ABS(var2)
876 * result = -(ABS(var1) - ABS(var2))
879 if (sub_abs(var1, var2, result) != 0)
881 result->sign = NUMERIC_NEG;
886 * ABS(var1) < ABS(var2)
887 * result = +(ABS(var2) - ABS(var1))
890 if (sub_abs(var2, var1, result) != 0)
892 result->sign = NUMERIC_POS;
899 * var1 is negative, var2 is positive
900 * result = -(ABS(var1) + ABS(var2))
903 if (add_abs(var1, var2, result) != 0)
905 result->sign = NUMERIC_NEG;
915 * Multiplication on variable level. Product of var1 * var2 is stored
916 * in result. Accuracy of result is determined by global_rscale.
920 PGTYPESnumeric_mul(Numeric *var1, Numeric *var2, Numeric *result)
922 NumericDigit *res_buf;
923 NumericDigit *res_digits;
932 int global_rscale = var1->rscale + var2->rscale;
934 res_weight = var1->weight + var2->weight + 2;
935 res_ndigits = var1->ndigits + var2->ndigits + 1;
936 if (var1->sign == var2->sign)
937 res_sign = NUMERIC_POS;
939 res_sign = NUMERIC_NEG;
941 if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
943 res_digits = res_buf;
944 memset(res_digits, 0, res_ndigits);
947 for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
952 for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
954 sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
955 res_digits[i--] = sum % 10;
961 i = res_weight + global_rscale + 2;
962 if (i >= 0 && i < res_ndigits)
964 sum = (res_digits[i] > 4) ? 1 : 0;
969 sum += res_digits[i];
970 res_digits[i--] = sum % 10;
975 while (res_ndigits > 0 && *res_digits == 0)
981 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
984 if (res_ndigits == 0)
986 res_sign = NUMERIC_POS;
990 digitbuf_free(result->buf);
991 result->buf = res_buf;
992 result->digits = res_digits;
993 result->ndigits = res_ndigits;
994 result->weight = res_weight;
995 result->rscale = global_rscale;
996 result->sign = res_sign;
997 result->dscale = var1->dscale + var2->dscale;
1003 * Default scale selection for division
1005 * Returns the appropriate display scale for the division result,
1006 * and sets global_rscale to the result scale to use during div_var.
1008 * Note that this must be called before div_var.
1011 select_div_scale(Numeric *var1, Numeric *var2, int *rscale)
1017 NumericDigit firstdigit1,
1023 * The result scale of a division isn't specified in any SQL standard.
1024 * For PostgreSQL we select a display scale that will give at least
1025 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
1026 * result no less accurate than float8; but use a scale not less than
1027 * either input's display scale.
1030 /* Get the actual (normalized) weight and first digit of each input */
1032 weight1 = 0; /* values to use if var1 is zero */
1034 for (i = 0; i < var1->ndigits; i++)
1036 firstdigit1 = var1->digits[i];
1037 if (firstdigit1 != 0)
1039 weight1 = var1->weight - i;
1044 weight2 = 0; /* values to use if var2 is zero */
1046 for (i = 0; i < var2->ndigits; i++)
1048 firstdigit2 = var2->digits[i];
1049 if (firstdigit2 != 0)
1051 weight2 = var2->weight - i;
1057 * Estimate weight of quotient. If the two first digits are equal, we
1058 * can't be sure, but assume that var1 is less than var2.
1060 qweight = weight1 - weight2;
1061 if (firstdigit1 <= firstdigit2)
1064 /* Select display scale */
1065 res_dscale = NUMERIC_MIN_SIG_DIGITS - qweight;
1066 res_dscale = Max(res_dscale, var1->dscale);
1067 res_dscale = Max(res_dscale, var2->dscale);
1068 res_dscale = Max(res_dscale, NUMERIC_MIN_DISPLAY_SCALE);
1069 res_dscale = Min(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1071 /* Select result scale */
1072 *rscale = res_rscale = res_dscale + 4;
1078 PGTYPESnumeric_div(Numeric *var1, Numeric *var2, Numeric *result)
1080 NumericDigit *res_digits;
1085 Numeric divisor[10];
1094 int first_nextdigit;
1097 int res_dscale = select_div_scale(var1, var2, &rscale);
1100 * First of all division by zero check
1102 ndigits_tmp = var2->ndigits + 1;
1103 if (ndigits_tmp == 1)
1105 errno = PGTYPES_NUM_DIVIDE_ZERO;
1110 * Determine the result sign, weight and number of digits to calculate
1112 if (var1->sign == var2->sign)
1113 res_sign = NUMERIC_POS;
1115 res_sign = NUMERIC_NEG;
1116 res_weight = var1->weight - var2->weight + 1;
1117 res_ndigits = rscale + res_weight;
1118 if (res_ndigits <= 0)
1122 * Now result zero check
1124 if (var1->ndigits == 0)
1127 result->rscale = rscale;
1132 * Initialize local variables
1134 init_var(÷nd);
1135 for (i = 1; i < 10; i++)
1136 init_var(&divisor[i]);
1139 * Make a copy of the divisor which has one leading zero digit
1141 divisor[1].ndigits = ndigits_tmp;
1142 divisor[1].rscale = var2->ndigits;
1143 divisor[1].sign = NUMERIC_POS;
1144 divisor[1].buf = digitbuf_alloc(ndigits_tmp);
1145 divisor[1].digits = divisor[1].buf;
1146 divisor[1].digits[0] = 0;
1147 memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
1150 * Make a copy of the dividend
1152 dividend.ndigits = var1->ndigits;
1153 dividend.weight = 0;
1154 dividend.rscale = var1->ndigits;
1155 dividend.sign = NUMERIC_POS;
1156 dividend.buf = digitbuf_alloc(var1->ndigits);
1157 dividend.digits = dividend.buf;
1158 memcpy(dividend.digits, var1->digits, var1->ndigits);
1163 digitbuf_free(result->buf);
1164 result->buf = digitbuf_alloc(res_ndigits + 2);
1165 res_digits = result->buf;
1166 result->digits = res_digits;
1167 result->ndigits = res_ndigits;
1168 result->weight = res_weight;
1169 result->rscale = rscale;
1170 result->sign = res_sign;
1173 first_div = divisor[1].digits[1] * 10;
1174 if (ndigits_tmp > 2)
1175 first_div += divisor[1].digits[2];
1178 first_nextdigit = 0;
1181 rscale_tmp = divisor[1].rscale;
1183 for (ri = 0; ri <= res_ndigits; ri++)
1185 first_have = first_have * 10;
1186 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1187 first_have += dividend.digits[first_nextdigit];
1190 guess = (first_have * 10) / first_div + 1;
1196 if (divisor[guess].buf == NULL)
1201 memcpy(&divisor[guess], &divisor[1], sizeof(Numeric));
1202 divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
1203 divisor[guess].digits = divisor[guess].buf;
1204 for (i = divisor[1].ndigits - 1; i >= 0; i--)
1206 sum += divisor[1].digits[i] * guess;
1207 divisor[guess].digits[i] = sum % 10;
1212 divisor[guess].weight = weight_tmp;
1213 divisor[guess].rscale = rscale_tmp;
1215 stat = cmp_abs(÷nd, &divisor[guess]);
1222 res_digits[ri + 1] = guess;
1235 sub_abs(÷nd, &divisor[guess], ÷nd);
1237 first_nextdigit = dividend.weight - weight_tmp;
1239 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1240 first_have = dividend.digits[first_nextdigit];
1244 result->ndigits = ri + 1;
1245 if (ri == res_ndigits + 1)
1247 int carry = (res_digits[ri] > 4) ? 1 : 0;
1249 result->ndigits = ri;
1252 while (carry && ri > 0)
1254 carry += res_digits[--ri];
1255 res_digits[ri] = carry % 10;
1260 while (result->ndigits > 0 && *(result->digits) == 0)
1264 (result->ndigits)--;
1266 while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
1267 (result->ndigits)--;
1268 if (result->ndigits == 0)
1269 result->sign = NUMERIC_POS;
1274 digitbuf_free(dividend.buf);
1275 for (i = 1; i < 10; i++)
1276 digitbuf_free(divisor[i].buf);
1278 result->dscale = res_dscale;
1284 PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2)
1287 /* use cmp_abs function to calculate the result */
1289 /* both are positive: normal comparation with cmp_abs */
1290 if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_POS)
1291 return cmp_abs(var1, var2);
1293 /* both are negative: return the inverse of the normal comparation */
1294 if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_NEG)
1297 * instead of inverting the result, we invert the paramter
1300 return cmp_abs(var2, var1);
1303 /* one is positive, one is negative: trivial */
1304 if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_NEG)
1306 if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_POS)
1309 errno = PGTYPES_NUM_BAD_NUMERIC;
1315 PGTYPESnumeric_from_int(signed int int_val, Numeric *var)
1317 /* implicit conversion */
1318 signed long int long_int = int_val;
1320 return PGTYPESnumeric_from_long(long_int, var);
1324 PGTYPESnumeric_from_long(signed long int long_val, Numeric *var)
1326 /* calculate the size of the long int number */
1327 /* a number n needs log_10 n digits */
1330 * however we multiply by 10 each time and compare instead of
1331 * calculating the logarithm
1336 signed long int abs_long_val = long_val;
1337 signed long int extract;
1338 signed long int reach_limit;
1340 if (abs_long_val < 0)
1343 var->sign = NUMERIC_NEG;
1346 var->sign = NUMERIC_POS;
1353 } while ((reach_limit - 1) < abs_long_val);
1355 /* always add a .0 */
1358 if (alloc_var(var, size) < 0)
1363 var->weight = size - 2;
1369 extract = abs_long_val - (abs_long_val % reach_limit);
1370 var->digits[i] = extract / reach_limit;
1371 abs_long_val -= extract;
1375 * we can abandon if abs_long_val reaches 0, because the memory is
1376 * initialized properly and filled with '0', so converting 10000
1377 * in only one step is no problem
1379 } while (abs_long_val > 0);
1385 PGTYPESnumeric_copy(Numeric *src, Numeric *dst)
1391 dst->weight = src->weight;
1392 dst->rscale = src->rscale;
1393 dst->dscale = src->dscale;
1394 dst->sign = src->sign;
1396 if (alloc_var(dst, src->ndigits) != 0)
1399 for (i = 0; i < src->ndigits; i++)
1400 dst->digits[i] = src->digits[i];
1406 PGTYPESnumeric_from_double(double d, Numeric *dst)
1411 if (sprintf(buffer, "%f", d) == 0)
1414 if ((tmp = PGTYPESnumeric_from_asc(buffer, NULL)) == NULL)
1416 if (PGTYPESnumeric_copy(tmp, dst) != 0)
1418 PGTYPESnumeric_free(tmp);
1423 numericvar_to_double_no_overflow(Numeric *var, double *dp)
1429 if ((tmp = get_str_from_var(var, var->dscale)) == NULL)
1432 /* unlike float8in, we ignore ERANGE from strtod */
1433 val = strtod(tmp, &endptr);
1434 if (*endptr != '\0')
1436 /* shouldn't happen ... */
1438 errno = PGTYPES_NUM_BAD_NUMERIC;
1447 PGTYPESnumeric_to_double(Numeric *nv, double *dp)
1452 if ((i = numericvar_to_double_no_overflow(nv, &tmp)) != 0)
1459 PGTYPESnumeric_to_int(Numeric *nv, int *ip)
1464 if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0)
1467 if (l < -INT_MAX || l > INT_MAX)
1469 errno = PGTYPES_NUM_OVERFLOW;
1478 PGTYPESnumeric_to_long(Numeric *nv, long *lp)
1483 for (i = 1; i < nv->weight + 2; i++)
1488 if (nv->buf[i] >= 5)
1493 if (l > LONG_MAX || l < 0)
1495 errno = PGTYPES_NUM_OVERFLOW;
1499 if (nv->sign == NUMERIC_NEG)
1506 PGTYPESnumeric_to_decimal(Numeric *src, Decimal * dst)
1510 if (src->ndigits > DECSIZE)
1512 errno = PGTYPES_NUM_OVERFLOW;
1516 dst->weight = src->weight;
1517 dst->rscale = src->rscale;
1518 dst->dscale = src->dscale;
1519 dst->sign = src->sign;
1520 dst->ndigits = src->ndigits;
1522 for (i = 0; i < src->ndigits; i++)
1523 dst->digits[i] = src->digits[i];
1529 PGTYPESnumeric_from_decimal(Decimal * src, Numeric *dst)
1535 dst->weight = src->weight;
1536 dst->rscale = src->rscale;
1537 dst->dscale = src->dscale;
1538 dst->sign = src->sign;
1540 if (alloc_var(dst, src->ndigits) != 0)
1543 for (i = 0; i < src->ndigits; i++)
1544 dst->digits[i] = src->digits[i];