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