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 17:13:01 Functions: 96.6 % 29 28 1 28 1 28
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 100.0 % 2 2 2
Legend: Lines: hit not hit (240..) days: 86.2 % 723 623 41 48 11 32 332 259 57 324
Function coverage date bins:
(240..) days: 48.3 % 58 28 1 28 1 28

 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(&dividend);
  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(&dividend, &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(&dividend, &divisor[guess], &dividend) != 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                 : }
        

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