PostgreSQL Source Code  git master
pgtypes_numeric.h File Reference
#include <pgtypes.h>
Include dependency graph for pgtypes_numeric.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  numeric
 
struct  decimal
 

Macros

#define NUMERIC_POS   0x0000
 
#define NUMERIC_NEG   0x4000
 
#define NUMERIC_NAN   0xC000
 
#define NUMERIC_NULL   0xF000
 
#define NUMERIC_MAX_PRECISION   1000
 
#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION
 
#define NUMERIC_MIN_DISPLAY_SCALE   0
 
#define NUMERIC_MIN_SIG_DIGITS   16
 
#define DECSIZE   30
 

Typedefs

typedef unsigned char NumericDigit
 

Functions

numericPGTYPESnumeric_new (void)
 
decimalPGTYPESdecimal_new (void)
 
void PGTYPESnumeric_free (numeric *)
 
void PGTYPESdecimal_free (decimal *)
 
numericPGTYPESnumeric_from_asc (char *, char **)
 
char * PGTYPESnumeric_to_asc (numeric *, int)
 
int PGTYPESnumeric_add (numeric *, numeric *, numeric *)
 
int PGTYPESnumeric_sub (numeric *, numeric *, numeric *)
 
int PGTYPESnumeric_mul (numeric *, numeric *, numeric *)
 
int PGTYPESnumeric_div (numeric *, numeric *, numeric *)
 
int PGTYPESnumeric_cmp (numeric *, numeric *)
 
int PGTYPESnumeric_from_int (signed int, numeric *)
 
int PGTYPESnumeric_from_long (signed long int, numeric *)
 
int PGTYPESnumeric_copy (numeric *, numeric *)
 
int PGTYPESnumeric_from_double (double, numeric *)
 
int PGTYPESnumeric_to_double (numeric *, double *)
 
int PGTYPESnumeric_to_int (numeric *, int *)
 
int PGTYPESnumeric_to_long (numeric *, long *)
 
int PGTYPESnumeric_to_decimal (numeric *, decimal *)
 
int PGTYPESnumeric_from_decimal (decimal *, numeric *)
 

Macro Definition Documentation

◆ DECSIZE

#define DECSIZE   30

Definition at line 15 of file pgtypes_numeric.h.

Referenced by PGTYPESnumeric_to_decimal().

◆ NUMERIC_MAX_DISPLAY_SCALE

#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION

Definition at line 11 of file pgtypes_numeric.h.

◆ NUMERIC_MAX_PRECISION

#define NUMERIC_MAX_PRECISION   1000

Definition at line 10 of file pgtypes_numeric.h.

◆ NUMERIC_MIN_DISPLAY_SCALE

#define NUMERIC_MIN_DISPLAY_SCALE   0

Definition at line 12 of file pgtypes_numeric.h.

◆ NUMERIC_MIN_SIG_DIGITS

#define NUMERIC_MIN_SIG_DIGITS   16

Definition at line 13 of file pgtypes_numeric.h.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 8 of file pgtypes_numeric.h.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 7 of file pgtypes_numeric.h.

◆ NUMERIC_NULL

#define NUMERIC_NULL   0xF000

Definition at line 9 of file pgtypes_numeric.h.

Referenced by ECPGis_noind_null(), and ECPGset_noind_null().

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 6 of file pgtypes_numeric.h.

Typedef Documentation

◆ NumericDigit

typedef unsigned char NumericDigit

Definition at line 17 of file pgtypes_numeric.h.

Function Documentation

◆ PGTYPESdecimal_free()

void PGTYPESdecimal_free ( decimal )

Definition at line 478 of file numeric.c.

Referenced by main().

479 {
480  free(var);
481 }
#define free(a)
Definition: header.h:65

◆ PGTYPESdecimal_new()

decimal* PGTYPESdecimal_new ( void  )

Definition at line 145 of file numeric.c.

Referenced by main().

146 {
147  decimal *var;
148 
149  if ((var = (decimal *) pgtypes_alloc(sizeof(decimal))) == NULL)
150  return NULL;
151 
152  memset(var, 0, sizeof(decimal));
153 
154  return var;
155 }
char * pgtypes_alloc(long size)
Definition: common.c:10

◆ PGTYPESnumeric_add()

int PGTYPESnumeric_add ( numeric ,
numeric ,
numeric  
)

Definition at line 723 of file numeric.c.

Referenced by decadd(), and main().

724 {
725  /*
726  * Decide on the signs of the two variables what to do
727  */
728  if (var1->sign == NUMERIC_POS)
729  {
730  if (var2->sign == NUMERIC_POS)
731  {
732  /*
733  * Both are positive result = +(ABS(var1) + ABS(var2))
734  */
735  if (add_abs(var1, var2, result) != 0)
736  return -1;
737  result->sign = NUMERIC_POS;
738  }
739  else
740  {
741  /*
742  * var1 is positive, var2 is negative Must compare absolute values
743  */
744  switch (cmp_abs(var1, var2))
745  {
746  case 0:
747  /* ----------
748  * ABS(var1) == ABS(var2)
749  * result = ZERO
750  * ----------
751  */
752  zero_var(result);
753  result->rscale = Max(var1->rscale, var2->rscale);
754  result->dscale = Max(var1->dscale, var2->dscale);
755  break;
756 
757  case 1:
758  /* ----------
759  * ABS(var1) > ABS(var2)
760  * result = +(ABS(var1) - ABS(var2))
761  * ----------
762  */
763  if (sub_abs(var1, var2, result) != 0)
764  return -1;
765  result->sign = NUMERIC_POS;
766  break;
767 
768  case -1:
769  /* ----------
770  * ABS(var1) < ABS(var2)
771  * result = -(ABS(var2) - ABS(var1))
772  * ----------
773  */
774  if (sub_abs(var2, var1, result) != 0)
775  return -1;
776  result->sign = NUMERIC_NEG;
777  break;
778  }
779  }
780  }
781  else
782  {
783  if (var2->sign == NUMERIC_POS)
784  {
785  /* ----------
786  * var1 is negative, var2 is positive
787  * Must compare absolute values
788  * ----------
789  */
790  switch (cmp_abs(var1, var2))
791  {
792  case 0:
793  /* ----------
794  * ABS(var1) == ABS(var2)
795  * result = ZERO
796  * ----------
797  */
798  zero_var(result);
799  result->rscale = Max(var1->rscale, var2->rscale);
800  result->dscale = Max(var1->dscale, var2->dscale);
801  break;
802 
803  case 1:
804  /* ----------
805  * ABS(var1) > ABS(var2)
806  * result = -(ABS(var1) - ABS(var2))
807  * ----------
808  */
809  if (sub_abs(var1, var2, result) != 0)
810  return -1;
811  result->sign = NUMERIC_NEG;
812  break;
813 
814  case -1:
815  /* ----------
816  * ABS(var1) < ABS(var2)
817  * result = +(ABS(var2) - ABS(var1))
818  * ----------
819  */
820  if (sub_abs(var2, var1, result) != 0)
821  return -1;
822  result->sign = NUMERIC_POS;
823  break;
824  }
825  }
826  else
827  {
828  /* ----------
829  * Both are negative
830  * result = -(ABS(var1) + ABS(var2))
831  * ----------
832  */
833  if (add_abs(var1, var2, result) != 0)
834  return -1;
835  result->sign = NUMERIC_NEG;
836  }
837  }
838 
839  return 0;
840 }
static int add_abs(numeric *var1, numeric *var2, numeric *result)
Definition: numeric.c:551
#define NUMERIC_POS
Definition: numeric.c:167
static void zero_var(numeric *var)
Definition: numeric.c:460
#define NUMERIC_NEG
Definition: numeric.c:168
static int cmp_abs(numeric *var1, numeric *var2)
Definition: numeric.c:493
static int sub_abs(numeric *var1, numeric *var2, numeric *result)
Definition: numeric.c:639
#define Max(x, y)
Definition: numeric.c:13

◆ PGTYPESnumeric_cmp()

int PGTYPESnumeric_cmp ( numeric ,
numeric  
)

Definition at line 1368 of file numeric.c.

Referenced by deccmp(), and main().

1369 {
1370  /* use cmp_abs function to calculate the result */
1371 
1372  /* both are positive: normal comparison with cmp_abs */
1373  if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_POS)
1374  return cmp_abs(var1, var2);
1375 
1376  /* both are negative: return the inverse of the normal comparison */
1377  if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_NEG)
1378  {
1379  /*
1380  * instead of inverting the result, we invert the parameter ordering
1381  */
1382  return cmp_abs(var2, var1);
1383  }
1384 
1385  /* one is positive, one is negative: trivial */
1386  if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_NEG)
1387  return 1;
1388  if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_POS)
1389  return -1;
1390 
1391  errno = PGTYPES_NUM_BAD_NUMERIC;
1392  return INT_MAX;
1393 
1394 }
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_NEG
Definition: numeric.c:168
static int cmp_abs(numeric *var1, numeric *var2)
Definition: numeric.c:493
#define PGTYPES_NUM_BAD_NUMERIC
Definition: pgtypes_error.h:4

◆ PGTYPESnumeric_copy()

int PGTYPESnumeric_copy ( numeric ,
numeric  
)

Definition at line 1476 of file numeric.c.

Referenced by ecpg_get_data(), ecpg_store_input(), and main().

1477 {
1478  int i;
1479 
1480  if (dst == NULL)
1481  return -1;
1482  zero_var(dst);
1483 
1484  dst->weight = src->weight;
1485  dst->rscale = src->rscale;
1486  dst->dscale = src->dscale;
1487  dst->sign = src->sign;
1488 
1489  if (alloc_var(dst, src->ndigits) != 0)
1490  return -1;
1491 
1492  for (i = 0; i < src->ndigits; i++)
1493  dst->digits[i] = src->digits[i];
1494 
1495  return 0;
1496 }
static void zero_var(numeric *var)
Definition: numeric.c:460
static int alloc_var(numeric *var, int ndigits)
Definition: numeric.c:115
int i

◆ PGTYPESnumeric_div()

int PGTYPESnumeric_div ( numeric ,
numeric ,
numeric  
)

Definition at line 1139 of file numeric.c.

Referenced by decdiv(), and main().

1140 {
1141  NumericDigit *res_digits;
1142  int res_ndigits;
1143  int res_sign;
1144  int res_weight;
1145  numeric dividend;
1146  numeric divisor[10];
1147  int ndigits_tmp;
1148  int weight_tmp;
1149  int rscale_tmp;
1150  int ri;
1151  int i;
1152  long guess;
1153  long first_have;
1154  long first_div;
1155  int first_nextdigit;
1156  int stat = 0;
1157  int rscale;
1158  int res_dscale = select_div_scale(var1, var2, &rscale);
1159  int err = -1;
1160  NumericDigit *tmp_buf;
1161 
1162  /*
1163  * First of all division by zero check
1164  */
1165  ndigits_tmp = var2->ndigits + 1;
1166  if (ndigits_tmp == 1)
1167  {
1168  errno = PGTYPES_NUM_DIVIDE_ZERO;
1169  return -1;
1170  }
1171 
1172  /*
1173  * Determine the result sign, weight and number of digits to calculate
1174  */
1175  if (var1->sign == var2->sign)
1176  res_sign = NUMERIC_POS;
1177  else
1178  res_sign = NUMERIC_NEG;
1179  res_weight = var1->weight - var2->weight + 1;
1180  res_ndigits = rscale + res_weight;
1181  if (res_ndigits <= 0)
1182  res_ndigits = 1;
1183 
1184  /*
1185  * Now result zero check
1186  */
1187  if (var1->ndigits == 0)
1188  {
1189  zero_var(result);
1190  result->rscale = rscale;
1191  return 0;
1192  }
1193 
1194  /*
1195  * Initialize local variables
1196  */
1197  init_var(&dividend);
1198  for (i = 1; i < 10; i++)
1199  init_var(&divisor[i]);
1200 
1201  /*
1202  * Make a copy of the divisor which has one leading zero digit
1203  */
1204  divisor[1].ndigits = ndigits_tmp;
1205  divisor[1].rscale = var2->ndigits;
1206  divisor[1].sign = NUMERIC_POS;
1207  divisor[1].buf = digitbuf_alloc(ndigits_tmp);
1208  if (divisor[1].buf == NULL)
1209  goto done;
1210  divisor[1].digits = divisor[1].buf;
1211  divisor[1].digits[0] = 0;
1212  memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
1213 
1214  /*
1215  * Make a copy of the dividend
1216  */
1217  dividend.ndigits = var1->ndigits;
1218  dividend.weight = 0;
1219  dividend.rscale = var1->ndigits;
1220  dividend.sign = NUMERIC_POS;
1221  dividend.buf = digitbuf_alloc(var1->ndigits);
1222  if (dividend.buf == NULL)
1223  goto done;
1224  dividend.digits = dividend.buf;
1225  memcpy(dividend.digits, var1->digits, var1->ndigits);
1226 
1227  /*
1228  * Setup the result. Do the allocation in a temporary buffer first, so we
1229  * don't free result->buf unless we have successfully allocated a buffer
1230  * to replace it with.
1231  */
1232  tmp_buf = digitbuf_alloc(res_ndigits + 2);
1233  if (tmp_buf == NULL)
1234  goto done;
1235  digitbuf_free(result->buf);
1236  result->buf = tmp_buf;
1237  res_digits = result->buf;
1238  result->digits = res_digits;
1239  result->ndigits = res_ndigits;
1240  result->weight = res_weight;
1241  result->rscale = rscale;
1242  result->sign = res_sign;
1243  res_digits[0] = 0;
1244 
1245  first_div = divisor[1].digits[1] * 10;
1246  if (ndigits_tmp > 2)
1247  first_div += divisor[1].digits[2];
1248 
1249  first_have = 0;
1250  first_nextdigit = 0;
1251 
1252  weight_tmp = 1;
1253  rscale_tmp = divisor[1].rscale;
1254 
1255  for (ri = 0; ri <= res_ndigits; ri++)
1256  {
1257  first_have = first_have * 10;
1258  if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1259  first_have += dividend.digits[first_nextdigit];
1260  first_nextdigit++;
1261 
1262  guess = (first_have * 10) / first_div + 1;
1263  if (guess > 9)
1264  guess = 9;
1265 
1266  while (guess > 0)
1267  {
1268  if (divisor[guess].buf == NULL)
1269  {
1270  int i;
1271  long sum = 0;
1272 
1273  memcpy(&divisor[guess], &divisor[1], sizeof(numeric));
1274  divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
1275  if (divisor[guess].buf == NULL)
1276  goto done;
1277  divisor[guess].digits = divisor[guess].buf;
1278  for (i = divisor[1].ndigits - 1; i >= 0; i--)
1279  {
1280  sum += divisor[1].digits[i] * guess;
1281  divisor[guess].digits[i] = sum % 10;
1282  sum /= 10;
1283  }
1284  }
1285 
1286  divisor[guess].weight = weight_tmp;
1287  divisor[guess].rscale = rscale_tmp;
1288 
1289  stat = cmp_abs(&dividend, &divisor[guess]);
1290  if (stat >= 0)
1291  break;
1292 
1293  guess--;
1294  }
1295 
1296  res_digits[ri + 1] = guess;
1297  if (stat == 0)
1298  {
1299  ri++;
1300  break;
1301  }
1302 
1303  weight_tmp--;
1304  rscale_tmp++;
1305 
1306  if (guess == 0)
1307  continue;
1308 
1309  if (sub_abs(&dividend, &divisor[guess], &dividend) != 0)
1310  goto done;
1311 
1312  first_nextdigit = dividend.weight - weight_tmp;
1313  first_have = 0;
1314  if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
1315  first_have = dividend.digits[first_nextdigit];
1316  first_nextdigit++;
1317  }
1318 
1319  result->ndigits = ri + 1;
1320  if (ri == res_ndigits + 1)
1321  {
1322  int carry = (res_digits[ri] > 4) ? 1 : 0;
1323 
1324  result->ndigits = ri;
1325  res_digits[ri] = 0;
1326 
1327  while (carry && ri > 0)
1328  {
1329  carry += res_digits[--ri];
1330  res_digits[ri] = carry % 10;
1331  carry /= 10;
1332  }
1333  }
1334 
1335  while (result->ndigits > 0 && *(result->digits) == 0)
1336  {
1337  (result->digits)++;
1338  (result->weight)--;
1339  (result->ndigits)--;
1340  }
1341  while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
1342  (result->ndigits)--;
1343  if (result->ndigits == 0)
1344  result->sign = NUMERIC_POS;
1345 
1346  result->dscale = res_dscale;
1347  err = 0; /* if we've made it this far, return success */
1348 
1349 done:
1350 
1351  /*
1352  * Tidy up
1353  */
1354  if (dividend.buf != NULL)
1355  digitbuf_free(dividend.buf);
1356 
1357  for (i = 1; i < 10; i++)
1358  {
1359  if (divisor[i].buf != NULL)
1360  digitbuf_free(divisor[i].buf);
1361  }
1362 
1363  return err;
1364 }
#define PGTYPES_NUM_DIVIDE_ZERO
Definition: pgtypes_error.h:5
#define NUMERIC_POS
Definition: numeric.c:167
static void zero_var(numeric *var)
Definition: numeric.c:460
NumericDigit * buf
#define NUMERIC_NEG
Definition: numeric.c:168
#define digitbuf_alloc(size)
Definition: numeric.c:18
NumericDigit * digits
static char * buf
Definition: pg_test_fsync.c:67
int16 NumericDigit
Definition: numeric.c:102
#define stat(a, b)
Definition: win32_port.h:255
static int cmp_abs(numeric *var1, numeric *var2)
Definition: numeric.c:493
static int select_div_scale(numeric *var1, numeric *var2, int *rscale)
Definition: numeric.c:1073
static int sub_abs(numeric *var1, numeric *var2, numeric *result)
Definition: numeric.c:639
#define digitbuf_free(buf)
Definition: numeric.c:19
#define init_var(v)
Definition: numeric.c:16
int i
int digits
Definition: informix.c:666

◆ PGTYPESnumeric_free()

void PGTYPESnumeric_free ( numeric )

Definition at line 471 of file numeric.c.

Referenced by deccall2(), deccall3(), deccvasc(), deccvdbl(), deccvint(), deccvlong(), dectoasc(), dectodbl(), dectoint(), dectolong(), ecpg_get_data(), ecpg_set_compat_sqlda(), ecpg_set_native_sqlda(), ecpg_store_input(), main(), and sqlda_common_total_size().

472 {
473  digitbuf_free(var->buf);
474  free(var);
475 }
#define free(a)
Definition: header.h:65
#define digitbuf_free(buf)
Definition: numeric.c:19

◆ PGTYPESnumeric_from_asc()

numeric* PGTYPESnumeric_from_asc ( char *  ,
char **   
)

Definition at line 407 of file numeric.c.

Referenced by deccvasc(), ecpg_get_data(), ecpg_set_compat_sqlda(), ecpg_set_native_sqlda(), main(), and sqlda_common_total_size().

408 {
409  numeric *value = (numeric *) pgtypes_alloc(sizeof(numeric));
410  int ret;
411 
412  char *realptr;
413  char **ptr = (endptr != NULL) ? endptr : &realptr;
414 
415  if (!value)
416  return NULL;
417 
418  ret = set_var_from_str(str, ptr, value);
419  if (ret)
420  {
421  PGTYPESnumeric_free(value);
422  return NULL;
423  }
424 
425  return value;
426 }
void PGTYPESnumeric_free(numeric *var)
Definition: numeric.c:471
static struct @145 value
char * pgtypes_alloc(long size)
Definition: common.c:10
static int set_var_from_str(char *str, char **ptr, numeric *dest)
Definition: numeric.c:164

◆ PGTYPESnumeric_from_decimal()

int PGTYPESnumeric_from_decimal ( decimal ,
numeric  
)

Definition at line 1653 of file numeric.c.

Referenced by deccall2(), deccall3(), dectoasc(), dectodbl(), dectoint(), dectolong(), ecpg_store_input(), and main().

1654 {
1655  int i;
1656 
1657  zero_var(dst);
1658 
1659  dst->weight = src->weight;
1660  dst->rscale = src->rscale;
1661  dst->dscale = src->dscale;
1662  dst->sign = src->sign;
1663 
1664  if (alloc_var(dst, src->ndigits) != 0)
1665  return -1;
1666 
1667  for (i = 0; i < src->ndigits; i++)
1668  dst->digits[i] = src->digits[i];
1669 
1670  return 0;
1671 }
static void zero_var(numeric *var)
Definition: numeric.c:460
static int alloc_var(numeric *var, int ndigits)
Definition: numeric.c:115
int i

◆ PGTYPESnumeric_from_double()

int PGTYPESnumeric_from_double ( double  ,
numeric  
)

Definition at line 1499 of file numeric.c.

Referenced by deccvdbl().

1500 {
1501  char buffer[DBL_DIG + 100];
1502  numeric *tmp;
1503  int i;
1504 
1505  if (sprintf(buffer, "%.*g", DBL_DIG, d) <= 0)
1506  return -1;
1507 
1508  if ((tmp = PGTYPESnumeric_from_asc(buffer, NULL)) == NULL)
1509  return -1;
1510  i = PGTYPESnumeric_copy(tmp, dst);
1511  PGTYPESnumeric_free(tmp);
1512  if (i != 0)
1513  return -1;
1514 
1515  errno = 0;
1516  return 0;
1517 }
void PGTYPESnumeric_free(numeric *var)
Definition: numeric.c:471
#define sprintf
Definition: port.h:194
int PGTYPESnumeric_copy(numeric *src, numeric *dst)
Definition: numeric.c:1476
numeric * PGTYPESnumeric_from_asc(char *str, char **endptr)
Definition: numeric.c:407
int i

◆ PGTYPESnumeric_from_int()

int PGTYPESnumeric_from_int ( signed  int,
numeric  
)

Definition at line 1397 of file numeric.c.

Referenced by deccvint(), and main().

1398 {
1399  /* implicit conversion */
1400  signed long int long_int = int_val;
1401 
1402  return PGTYPESnumeric_from_long(long_int, var);
1403 }
int PGTYPESnumeric_from_long(signed long int long_val, numeric *var)
Definition: numeric.c:1406

◆ PGTYPESnumeric_from_long()

int PGTYPESnumeric_from_long ( signed long  int,
numeric  
)

Definition at line 1406 of file numeric.c.

Referenced by deccvlong(), and main().

1407 {
1408  /* calculate the size of the long int number */
1409  /* a number n needs log_10 n digits */
1410 
1411  /*
1412  * however we multiply by 10 each time and compare instead of calculating
1413  * the logarithm
1414  */
1415 
1416  int size = 0;
1417  int i;
1418  signed long int abs_long_val = long_val;
1419  signed long int extract;
1420  signed long int reach_limit;
1421 
1422  if (abs_long_val < 0)
1423  {
1424  abs_long_val *= -1;
1425  var->sign = NUMERIC_NEG;
1426  }
1427  else
1428  var->sign = NUMERIC_POS;
1429 
1430  reach_limit = 1;
1431  do
1432  {
1433  size++;
1434  reach_limit *= 10;
1435  } while (reach_limit - 1 < abs_long_val && reach_limit <= LONG_MAX / 10);
1436 
1437  if (reach_limit > LONG_MAX / 10)
1438  {
1439  /* add the first digit and a .0 */
1440  size += 2;
1441  }
1442  else
1443  {
1444  /* always add a .0 */
1445  size++;
1446  reach_limit /= 10;
1447  }
1448 
1449  if (alloc_var(var, size) < 0)
1450  return -1;
1451 
1452  var->rscale = 1;
1453  var->dscale = 1;
1454  var->weight = size - 2;
1455 
1456  i = 0;
1457  do
1458  {
1459  extract = abs_long_val - (abs_long_val % reach_limit);
1460  var->digits[i] = extract / reach_limit;
1461  abs_long_val -= extract;
1462  i++;
1463  reach_limit /= 10;
1464 
1465  /*
1466  * we can abandon if abs_long_val reaches 0, because the memory is
1467  * initialized properly and filled with '0', so converting 10000 in
1468  * only one step is no problem
1469  */
1470  } while (abs_long_val > 0);
1471 
1472  return 0;
1473 }
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_NEG
Definition: numeric.c:168
static int alloc_var(numeric *var, int ndigits)
Definition: numeric.c:115
int i

◆ PGTYPESnumeric_mul()

int PGTYPESnumeric_mul ( numeric ,
numeric ,
numeric  
)

Definition at line 982 of file numeric.c.

Referenced by decmul(), and main().

983 {
984  NumericDigit *res_buf;
985  NumericDigit *res_digits;
986  int res_ndigits;
987  int res_weight;
988  int res_sign;
989  int i,
990  ri,
991  i1,
992  i2;
993  long sum = 0;
994  int global_rscale = var1->rscale + var2->rscale;
995 
996  res_weight = var1->weight + var2->weight + 2;
997  res_ndigits = var1->ndigits + var2->ndigits + 1;
998  if (var1->sign == var2->sign)
999  res_sign = NUMERIC_POS;
1000  else
1001  res_sign = NUMERIC_NEG;
1002 
1003  if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
1004  return -1;
1005  res_digits = res_buf;
1006  memset(res_digits, 0, res_ndigits);
1007 
1008  ri = res_ndigits;
1009  for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
1010  {
1011  sum = 0;
1012  i = --ri;
1013 
1014  for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
1015  {
1016  sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
1017  res_digits[i--] = sum % 10;
1018  sum /= 10;
1019  }
1020  res_digits[i] = sum;
1021  }
1022 
1023  i = res_weight + global_rscale + 2;
1024  if (i >= 0 && i < res_ndigits)
1025  {
1026  sum = (res_digits[i] > 4) ? 1 : 0;
1027  res_ndigits = i;
1028  i--;
1029  while (sum)
1030  {
1031  sum += res_digits[i];
1032  res_digits[i--] = sum % 10;
1033  sum /= 10;
1034  }
1035  }
1036 
1037  while (res_ndigits > 0 && *res_digits == 0)
1038  {
1039  res_digits++;
1040  res_weight--;
1041  res_ndigits--;
1042  }
1043  while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
1044  res_ndigits--;
1045 
1046  if (res_ndigits == 0)
1047  {
1048  res_sign = NUMERIC_POS;
1049  res_weight = 0;
1050  }
1051 
1052  digitbuf_free(result->buf);
1053  result->buf = res_buf;
1054  result->digits = res_digits;
1055  result->ndigits = res_ndigits;
1056  result->weight = res_weight;
1057  result->rscale = global_rscale;
1058  result->sign = res_sign;
1059  result->dscale = var1->dscale + var2->dscale;
1060 
1061  return 0;
1062 }
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_NEG
Definition: numeric.c:168
#define digitbuf_alloc(size)
Definition: numeric.c:18
int16 NumericDigit
Definition: numeric.c:102
#define digitbuf_free(buf)
Definition: numeric.c:19
int i

◆ PGTYPESnumeric_new()

numeric* PGTYPESnumeric_new ( void  )

Definition at line 128 of file numeric.c.

Referenced by deccall2(), deccall3(), deccvdbl(), deccvint(), deccvlong(), dectoasc(), dectodbl(), dectoint(), dectolong(), ecpg_get_data(), ecpg_store_input(), and main().

129 {
130  numeric *var;
131 
132  if ((var = (numeric *) pgtypes_alloc(sizeof(numeric))) == NULL)
133  return NULL;
134 
135  if (alloc_var(var, 0) < 0)
136  {
137  free(var);
138  return NULL;
139  }
140 
141  return var;
142 }
char * pgtypes_alloc(long size)
Definition: common.c:10
static int alloc_var(numeric *var, int ndigits)
Definition: numeric.c:115
#define free(a)
Definition: header.h:65

◆ PGTYPESnumeric_sub()

int PGTYPESnumeric_sub ( numeric ,
numeric ,
numeric  
)

Definition at line 851 of file numeric.c.

Referenced by decsub(), and main().

852 {
853  /*
854  * Decide on the signs of the two variables what to do
855  */
856  if (var1->sign == NUMERIC_POS)
857  {
858  if (var2->sign == NUMERIC_NEG)
859  {
860  /* ----------
861  * var1 is positive, var2 is negative
862  * result = +(ABS(var1) + ABS(var2))
863  * ----------
864  */
865  if (add_abs(var1, var2, result) != 0)
866  return -1;
867  result->sign = NUMERIC_POS;
868  }
869  else
870  {
871  /* ----------
872  * Both are positive
873  * Must compare absolute values
874  * ----------
875  */
876  switch (cmp_abs(var1, var2))
877  {
878  case 0:
879  /* ----------
880  * ABS(var1) == ABS(var2)
881  * result = ZERO
882  * ----------
883  */
884  zero_var(result);
885  result->rscale = Max(var1->rscale, var2->rscale);
886  result->dscale = Max(var1->dscale, var2->dscale);
887  break;
888 
889  case 1:
890  /* ----------
891  * ABS(var1) > ABS(var2)
892  * result = +(ABS(var1) - ABS(var2))
893  * ----------
894  */
895  if (sub_abs(var1, var2, result) != 0)
896  return -1;
897  result->sign = NUMERIC_POS;
898  break;
899 
900  case -1:
901  /* ----------
902  * ABS(var1) < ABS(var2)
903  * result = -(ABS(var2) - ABS(var1))
904  * ----------
905  */
906  if (sub_abs(var2, var1, result) != 0)
907  return -1;
908  result->sign = NUMERIC_NEG;
909  break;
910  }
911  }
912  }
913  else
914  {
915  if (var2->sign == NUMERIC_NEG)
916  {
917  /* ----------
918  * Both are negative
919  * Must compare absolute values
920  * ----------
921  */
922  switch (cmp_abs(var1, var2))
923  {
924  case 0:
925  /* ----------
926  * ABS(var1) == ABS(var2)
927  * result = ZERO
928  * ----------
929  */
930  zero_var(result);
931  result->rscale = Max(var1->rscale, var2->rscale);
932  result->dscale = Max(var1->dscale, var2->dscale);
933  break;
934 
935  case 1:
936  /* ----------
937  * ABS(var1) > ABS(var2)
938  * result = -(ABS(var1) - ABS(var2))
939  * ----------
940  */
941  if (sub_abs(var1, var2, result) != 0)
942  return -1;
943  result->sign = NUMERIC_NEG;
944  break;
945 
946  case -1:
947  /* ----------
948  * ABS(var1) < ABS(var2)
949  * result = +(ABS(var2) - ABS(var1))
950  * ----------
951  */
952  if (sub_abs(var2, var1, result) != 0)
953  return -1;
954  result->sign = NUMERIC_POS;
955  break;
956  }
957  }
958  else
959  {
960  /* ----------
961  * var1 is negative, var2 is positive
962  * result = -(ABS(var1) + ABS(var2))
963  * ----------
964  */
965  if (add_abs(var1, var2, result) != 0)
966  return -1;
967  result->sign = NUMERIC_NEG;
968  }
969  }
970 
971  return 0;
972 }
static int add_abs(numeric *var1, numeric *var2, numeric *result)
Definition: numeric.c:551
#define NUMERIC_POS
Definition: numeric.c:167
static void zero_var(numeric *var)
Definition: numeric.c:460
#define NUMERIC_NEG
Definition: numeric.c:168
static int cmp_abs(numeric *var1, numeric *var2)
Definition: numeric.c:493
static int sub_abs(numeric *var1, numeric *var2, numeric *result)
Definition: numeric.c:639
#define Max(x, y)
Definition: numeric.c:13

◆ PGTYPESnumeric_to_asc()

char* PGTYPESnumeric_to_asc ( numeric ,
int   
)

Definition at line 429 of file numeric.c.

Referenced by dectoasc(), ecpg_store_input(), and main().

430 {
431  numeric *numcopy = PGTYPESnumeric_new();
432  char *s;
433 
434  if (numcopy == NULL)
435  return NULL;
436 
437  if (PGTYPESnumeric_copy(num, numcopy) < 0)
438  {
439  PGTYPESnumeric_free(numcopy);
440  return NULL;
441  }
442 
443  if (dscale < 0)
444  dscale = num->dscale;
445 
446  /* get_str_from_var may change its argument */
447  s = get_str_from_var(numcopy, dscale);
448  PGTYPESnumeric_free(numcopy);
449  return s;
450 }
numeric * PGTYPESnumeric_new(void)
Definition: numeric.c:128
void PGTYPESnumeric_free(numeric *var)
Definition: numeric.c:471
int PGTYPESnumeric_copy(numeric *src, numeric *dst)
Definition: numeric.c:1476
static char * get_str_from_var(numeric *var, int dscale)
Definition: numeric.c:312

◆ PGTYPESnumeric_to_decimal()

int PGTYPESnumeric_to_decimal ( numeric ,
decimal  
)

Definition at line 1630 of file numeric.c.

Referenced by deccall3(), deccvasc(), deccvdbl(), deccvint(), deccvlong(), ecpg_get_data(), and main().

1631 {
1632  int i;
1633 
1634  if (src->ndigits > DECSIZE)
1635  {
1636  errno = PGTYPES_NUM_OVERFLOW;
1637  return -1;
1638  }
1639 
1640  dst->weight = src->weight;
1641  dst->rscale = src->rscale;
1642  dst->dscale = src->dscale;
1643  dst->sign = src->sign;
1644  dst->ndigits = src->ndigits;
1645 
1646  for (i = 0; i < src->ndigits; i++)
1647  dst->digits[i] = src->digits[i];
1648 
1649  return 0;
1650 }
#define PGTYPES_NUM_OVERFLOW
Definition: pgtypes_error.h:3
#define DECSIZE
int i

◆ PGTYPESnumeric_to_double()

int PGTYPESnumeric_to_double ( numeric ,
double *   
)

Definition at line 1571 of file numeric.c.

Referenced by dectodbl(), and main().

1572 {
1573  double tmp;
1574 
1575  if (numericvar_to_double(nv, &tmp) != 0)
1576  return -1;
1577  *dp = tmp;
1578  return 0;
1579 }
static int numericvar_to_double(numeric *var, double *dp)
Definition: numeric.c:1520

◆ PGTYPESnumeric_to_int()

int PGTYPESnumeric_to_int ( numeric ,
int *   
)

Definition at line 1582 of file numeric.c.

Referenced by dectoint(), and main().

1583 {
1584  long l;
1585  int i;
1586 
1587  if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0)
1588  return i;
1589 
1590  if (l < -INT_MAX || l > INT_MAX)
1591  {
1592  errno = PGTYPES_NUM_OVERFLOW;
1593  return -1;
1594  }
1595 
1596  *ip = (int) l;
1597  return 0;
1598 }
#define PGTYPES_NUM_OVERFLOW
Definition: pgtypes_error.h:3
int i
int PGTYPESnumeric_to_long(numeric *nv, long *lp)
Definition: numeric.c:1601

◆ PGTYPESnumeric_to_long()

int PGTYPESnumeric_to_long ( numeric ,
long *   
)

Definition at line 1601 of file numeric.c.

Referenced by dectolong(), and main().

1602 {
1603  char *s = PGTYPESnumeric_to_asc(nv, 0);
1604  char *endptr;
1605 
1606  if (s == NULL)
1607  return -1;
1608 
1609  errno = 0;
1610  *lp = strtol(s, &endptr, 10);
1611  if (endptr == s)
1612  {
1613  /* this should not happen actually */
1614  free(s);
1615  return -1;
1616  }
1617  free(s);
1618  if (errno == ERANGE)
1619  {
1620  if (*lp == LONG_MIN)
1621  errno = PGTYPES_NUM_UNDERFLOW;
1622  else
1623  errno = PGTYPES_NUM_OVERFLOW;
1624  return -1;
1625  }
1626  return 0;
1627 }
#define PGTYPES_NUM_OVERFLOW
Definition: pgtypes_error.h:3
#define PGTYPES_NUM_UNDERFLOW
Definition: pgtypes_error.h:6
#define free(a)
Definition: header.h:65
char * PGTYPESnumeric_to_asc(numeric *num, int dscale)
Definition: numeric.c:429