LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/pgtypeslib - numeric.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 86.2 % 725 625 41 48 11 32 332 2 259 57 324 1
Current Date: 2023-04-08 15:15:32 Functions: 96.6 % 29 28 1 28 1 28
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a