PostgreSQL Source Code  git master
numeric.h File Reference
#include "common/pg_prng.h"
#include "fmgr.h"
Include dependency graph for numeric.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define NUMERIC_MAX_PRECISION   1000
 
#define NUMERIC_MIN_SCALE   (-1000)
 
#define NUMERIC_MAX_SCALE   1000
 
#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION
 
#define NUMERIC_MIN_DISPLAY_SCALE   0
 
#define NUMERIC_MAX_RESULT_SCALE   (NUMERIC_MAX_PRECISION * 2)
 
#define NUMERIC_MIN_SIG_DIGITS   16
 
#define PG_GETARG_NUMERIC(n)   DatumGetNumeric(PG_GETARG_DATUM(n))
 
#define PG_GETARG_NUMERIC_COPY(n)   DatumGetNumericCopy(PG_GETARG_DATUM(n))
 
#define PG_RETURN_NUMERIC(x)   return NumericGetDatum(x)
 

Typedefs

typedef struct NumericDataNumeric
 

Functions

static Numeric DatumGetNumeric (Datum X)
 
static Numeric DatumGetNumericCopy (Datum X)
 
static Datum NumericGetDatum (Numeric X)
 
bool numeric_is_nan (Numeric num)
 
bool numeric_is_inf (Numeric num)
 
int32 numeric_maximum_size (int32 typmod)
 
char * numeric_out_sci (Numeric num, int scale)
 
char * numeric_normalize (Numeric num)
 
Numeric int64_to_numeric (int64 val)
 
Numeric int64_div_fast_to_numeric (int64 val1, int log10val2)
 
Numeric numeric_add_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Numeric numeric_sub_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Numeric numeric_mul_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Numeric numeric_div_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Numeric numeric_mod_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
int32 numeric_int4_opt_error (Numeric num, bool *have_error)
 
int64 numeric_int8_opt_error (Numeric num, bool *have_error)
 
Numeric random_numeric (pg_prng_state *state, Numeric rmin, Numeric rmax)
 

Macro Definition Documentation

◆ NUMERIC_MAX_DISPLAY_SCALE

#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION

Definition at line 40 of file numeric.h.

◆ NUMERIC_MAX_PRECISION

#define NUMERIC_MAX_PRECISION   1000

Definition at line 32 of file numeric.h.

◆ NUMERIC_MAX_RESULT_SCALE

#define NUMERIC_MAX_RESULT_SCALE   (NUMERIC_MAX_PRECISION * 2)

Definition at line 43 of file numeric.h.

◆ NUMERIC_MAX_SCALE

#define NUMERIC_MAX_SCALE   1000

Definition at line 35 of file numeric.h.

◆ NUMERIC_MIN_DISPLAY_SCALE

#define NUMERIC_MIN_DISPLAY_SCALE   0

Definition at line 41 of file numeric.h.

◆ NUMERIC_MIN_SCALE

#define NUMERIC_MIN_SCALE   (-1000)

Definition at line 34 of file numeric.h.

◆ NUMERIC_MIN_SIG_DIGITS

#define NUMERIC_MIN_SIG_DIGITS   16

Definition at line 50 of file numeric.h.

◆ PG_GETARG_NUMERIC

#define PG_GETARG_NUMERIC (   n)    DatumGetNumeric(PG_GETARG_DATUM(n))

Definition at line 78 of file numeric.h.

◆ PG_GETARG_NUMERIC_COPY

#define PG_GETARG_NUMERIC_COPY (   n)    DatumGetNumericCopy(PG_GETARG_DATUM(n))

Definition at line 79 of file numeric.h.

◆ PG_RETURN_NUMERIC

#define PG_RETURN_NUMERIC (   x)    return NumericGetDatum(x)

Definition at line 80 of file numeric.h.

Typedef Documentation

◆ Numeric

typedef struct NumericData* Numeric

Definition at line 54 of file numeric.h.

Function Documentation

◆ DatumGetNumeric()

◆ DatumGetNumericCopy()

static Numeric DatumGetNumericCopy ( Datum  X)
inlinestatic

Definition at line 67 of file numeric.h.

68 {
69  return (Numeric) PG_DETOAST_DATUM_COPY(X);
70 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242

References PG_DETOAST_DATUM_COPY.

Referenced by jsonb_numeric().

◆ int64_div_fast_to_numeric()

Numeric int64_div_fast_to_numeric ( int64  val1,
int  log10val2 
)

Definition at line 4304 of file numeric.c.

4305 {
4306  Numeric res;
4307  NumericVar result;
4308  int rscale;
4309  int w;
4310  int m;
4311 
4312  init_var(&result);
4313 
4314  /* result scale */
4315  rscale = log10val2 < 0 ? 0 : log10val2;
4316 
4317  /* how much to decrease the weight by */
4318  w = log10val2 / DEC_DIGITS;
4319  /* how much is left to divide by */
4320  m = log10val2 % DEC_DIGITS;
4321  if (m < 0)
4322  {
4323  m += DEC_DIGITS;
4324  w--;
4325  }
4326 
4327  /*
4328  * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4329  * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4330  * one more.
4331  */
4332  if (m > 0)
4333  {
4334 #if DEC_DIGITS == 4
4335  static const int pow10[] = {1, 10, 100, 1000};
4336 #elif DEC_DIGITS == 2
4337  static const int pow10[] = {1, 10};
4338 #elif DEC_DIGITS == 1
4339  static const int pow10[] = {1};
4340 #else
4341 #error unsupported NBASE
4342 #endif
4343  int64 factor = pow10[DEC_DIGITS - m];
4344  int64 new_val1;
4345 
4346  StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4347 
4348  if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4349  {
4350 #ifdef HAVE_INT128
4351  /* do the multiplication using 128-bit integers */
4352  int128 tmp;
4353 
4354  tmp = (int128) val1 * (int128) factor;
4355 
4356  int128_to_numericvar(tmp, &result);
4357 #else
4358  /* do the multiplication using numerics */
4359  NumericVar tmp;
4360 
4361  init_var(&tmp);
4362 
4363  int64_to_numericvar(val1, &result);
4364  int64_to_numericvar(factor, &tmp);
4365  mul_var(&result, &tmp, &result, 0);
4366 
4367  free_var(&tmp);
4368 #endif
4369  }
4370  else
4371  int64_to_numericvar(new_val1, &result);
4372 
4373  w++;
4374  }
4375  else
4376  int64_to_numericvar(val1, &result);
4377 
4378  result.weight -= w;
4379  result.dscale = rscale;
4380 
4381  res = make_result(&result);
4382 
4383  free_var(&result);
4384 
4385  return res;
4386 }
static void free_var(NumericVar *var)
Definition: numeric.c:6969
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8669
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:8104
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7891
#define DEC_DIGITS
Definition: numeric.c:97
#define init_var(v)
Definition: numeric.c:484
#define unlikely(x)
Definition: c.h:311
#define lengthof(array)
Definition: c.h:788
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:936
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:219
int dscale
Definition: numeric.c:308
int weight
Definition: numeric.c:306

References DEC_DIGITS, NumericVar::dscale, free_var(), init_var, int64_to_numericvar(), lengthof, make_result(), mul_var(), pg_mul_s64_overflow(), res, StaticAssertDecl, unlikely, and NumericVar::weight.

Referenced by interval_part_common(), time_part_common(), timestamp_part_common(), timestamptz_part_common(), and timetz_part_common().

◆ int64_to_numeric()

◆ numeric_add_opt_error()

Numeric numeric_add_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 2867 of file numeric.c.

2868 {
2869  NumericVar arg1;
2870  NumericVar arg2;
2871  NumericVar result;
2872  Numeric res;
2873 
2874  /*
2875  * Handle NaN and infinities
2876  */
2877  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2878  {
2879  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2880  return make_result(&const_nan);
2881  if (NUMERIC_IS_PINF(num1))
2882  {
2883  if (NUMERIC_IS_NINF(num2))
2884  return make_result(&const_nan); /* Inf + -Inf */
2885  else
2886  return make_result(&const_pinf);
2887  }
2888  if (NUMERIC_IS_NINF(num1))
2889  {
2890  if (NUMERIC_IS_PINF(num2))
2891  return make_result(&const_nan); /* -Inf + Inf */
2892  else
2893  return make_result(&const_ninf);
2894  }
2895  /* by here, num1 must be finite, so num2 is not */
2896  if (NUMERIC_IS_PINF(num2))
2897  return make_result(&const_pinf);
2898  Assert(NUMERIC_IS_NINF(num2));
2899  return make_result(&const_ninf);
2900  }
2901 
2902  /*
2903  * Unpack the values, let add_var() compute the result and return it.
2904  */
2905  init_var_from_num(num1, &arg1);
2906  init_var_from_num(num2, &arg2);
2907 
2908  init_var(&result);
2909  add_var(&arg1, &arg2, &result);
2910 
2911  res = make_result_opt_error(&result, have_error);
2912 
2913  free_var(&result);
2914 
2915  return res;
2916 }
static const NumericVar const_pinf
Definition: numeric.c:452
static const NumericVar const_ninf
Definition: numeric.c:455
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8431
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:172
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7451
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:204
static Numeric make_result_opt_error(const NumericVar *var, bool *have_error)
Definition: numeric.c:7782
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:205
static const NumericVar const_nan
Definition: numeric.c:449
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:203
#define Assert(condition)
Definition: c.h:858

References add_var(), Assert, const_nan, const_ninf, const_pinf, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, and res.

Referenced by executeItemOptUnwrapTarget(), interval_part_common(), numeric_add(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_div_opt_error()

Numeric numeric_div_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 3144 of file numeric.c.

3145 {
3146  NumericVar arg1;
3147  NumericVar arg2;
3148  NumericVar result;
3149  Numeric res;
3150  int rscale;
3151 
3152  if (have_error)
3153  *have_error = false;
3154 
3155  /*
3156  * Handle NaN and infinities
3157  */
3158  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3159  {
3160  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3161  return make_result(&const_nan);
3162  if (NUMERIC_IS_PINF(num1))
3163  {
3164  if (NUMERIC_IS_SPECIAL(num2))
3165  return make_result(&const_nan); /* Inf / [-]Inf */
3166  switch (numeric_sign_internal(num2))
3167  {
3168  case 0:
3169  if (have_error)
3170  {
3171  *have_error = true;
3172  return NULL;
3173  }
3174  ereport(ERROR,
3175  (errcode(ERRCODE_DIVISION_BY_ZERO),
3176  errmsg("division by zero")));
3177  break;
3178  case 1:
3179  return make_result(&const_pinf);
3180  case -1:
3181  return make_result(&const_ninf);
3182  }
3183  Assert(false);
3184  }
3185  if (NUMERIC_IS_NINF(num1))
3186  {
3187  if (NUMERIC_IS_SPECIAL(num2))
3188  return make_result(&const_nan); /* -Inf / [-]Inf */
3189  switch (numeric_sign_internal(num2))
3190  {
3191  case 0:
3192  if (have_error)
3193  {
3194  *have_error = true;
3195  return NULL;
3196  }
3197  ereport(ERROR,
3198  (errcode(ERRCODE_DIVISION_BY_ZERO),
3199  errmsg("division by zero")));
3200  break;
3201  case 1:
3202  return make_result(&const_ninf);
3203  case -1:
3204  return make_result(&const_pinf);
3205  }
3206  Assert(false);
3207  }
3208  /* by here, num1 must be finite, so num2 is not */
3209 
3210  /*
3211  * POSIX would have us return zero or minus zero if num1 is zero, and
3212  * otherwise throw an underflow error. But the numeric type doesn't
3213  * really do underflow, so let's just return zero.
3214  */
3215  return make_result(&const_zero);
3216  }
3217 
3218  /*
3219  * Unpack the arguments
3220  */
3221  init_var_from_num(num1, &arg1);
3222  init_var_from_num(num2, &arg2);
3223 
3224  init_var(&result);
3225 
3226  /*
3227  * Select scale for division result
3228  */
3229  rscale = select_div_scale(&arg1, &arg2);
3230 
3231  /*
3232  * If "have_error" is provided, check for division by zero here
3233  */
3234  if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3235  {
3236  *have_error = true;
3237  return NULL;
3238  }
3239 
3240  /*
3241  * Do the divide and return the result
3242  */
3243  div_var(&arg1, &arg2, &result, rscale, true);
3244 
3245  res = make_result_opt_error(&result, have_error);
3246 
3247  free_var(&result);
3248 
3249  return res;
3250 }
static int numeric_sign_internal(Numeric num)
Definition: numeric.c:1469
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9777
static const NumericVar const_zero
Definition: numeric.c:415
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8877
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int ndigits
Definition: numeric.c:305
NumericDigit * digits
Definition: numeric.c:310

References Assert, const_nan, const_ninf, const_pinf, const_zero, NumericVar::digits, div_var(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), NumericVar::ndigits, NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), res, and select_div_scale().

Referenced by executeItemOptUnwrapTarget(), numeric_div(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_int4_opt_error()

int32 numeric_int4_opt_error ( Numeric  num,
bool have_error 
)

Definition at line 4397 of file numeric.c.

4398 {
4399  NumericVar x;
4400  int32 result;
4401 
4402  if (have_error)
4403  *have_error = false;
4404 
4405  if (NUMERIC_IS_SPECIAL(num))
4406  {
4407  if (have_error)
4408  {
4409  *have_error = true;
4410  return 0;
4411  }
4412  else
4413  {
4414  if (NUMERIC_IS_NAN(num))
4415  ereport(ERROR,
4416  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4417  errmsg("cannot convert NaN to %s", "integer")));
4418  else
4419  ereport(ERROR,
4420  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4421  errmsg("cannot convert infinity to %s", "integer")));
4422  }
4423  }
4424 
4425  /* Convert to variable format, then convert to int4 */
4426  init_var_from_num(num, &x);
4427 
4428  if (!numericvar_to_int32(&x, &result))
4429  {
4430  if (have_error)
4431  {
4432  *have_error = true;
4433  return 0;
4434  }
4435  else
4436  {
4437  ereport(ERROR,
4438  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4439  errmsg("integer out of range")));
4440  }
4441  }
4442 
4443  return result;
4444 }
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition: numeric.c:4460
signed int int32
Definition: c.h:494
int x
Definition: isn.c:71

References ereport, errcode(), errmsg(), ERROR, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_int32(), and x.

Referenced by executeDateTimeMethod(), executeItemOptUnwrapTarget(), getArrayIndex(), and numeric_int4().

◆ numeric_int8_opt_error()

int64 numeric_int8_opt_error ( Numeric  num,
bool have_error 
)

Definition at line 4485 of file numeric.c.

4486 {
4487  NumericVar x;
4488  int64 result;
4489 
4490  if (have_error)
4491  *have_error = false;
4492 
4493  if (NUMERIC_IS_SPECIAL(num))
4494  {
4495  if (have_error)
4496  {
4497  *have_error = true;
4498  return 0;
4499  }
4500  else
4501  {
4502  if (NUMERIC_IS_NAN(num))
4503  ereport(ERROR,
4504  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4505  errmsg("cannot convert NaN to %s", "bigint")));
4506  else
4507  ereport(ERROR,
4508  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4509  errmsg("cannot convert infinity to %s", "bigint")));
4510  }
4511  }
4512 
4513  /* Convert to variable format, then convert to int8 */
4514  init_var_from_num(num, &x);
4515 
4516  if (!numericvar_to_int64(&x, &result))
4517  {
4518  if (have_error)
4519  {
4520  *have_error = true;
4521  return 0;
4522  }
4523  else
4524  {
4525  ereport(ERROR,
4526  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4527  errmsg("bigint out of range")));
4528  }
4529  }
4530 
4531  return result;
4532 }
static bool numericvar_to_int64(const NumericVar *var, int64 *result)
Definition: numeric.c:8029

References ereport, errcode(), errmsg(), ERROR, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_int64(), and x.

Referenced by executeItemOptUnwrapTarget(), and numeric_int8().

◆ numeric_is_inf()

bool numeric_is_inf ( Numeric  num)

Definition at line 853 of file numeric.c.

854 {
855  return NUMERIC_IS_INF(num);
856 }
#define NUMERIC_IS_INF(n)
Definition: numeric.c:206

References NUMERIC_IS_INF.

Referenced by executeItemOptUnwrapTarget(), and PLyNumber_ToJsonbValue().

◆ numeric_is_nan()

bool numeric_is_nan ( Numeric  num)

Definition at line 842 of file numeric.c.

843 {
844  return NUMERIC_IS_NAN(num);
845 }

References NUMERIC_IS_NAN.

Referenced by executeItemOptUnwrapTarget(), gbt_numeric_penalty(), pg_lsn_mii(), pg_lsn_pli(), and PLyNumber_ToJsonbValue().

◆ numeric_maximum_size()

int32 numeric_maximum_size ( int32  typmod)

Definition at line 944 of file numeric.c.

945 {
946  int precision;
947  int numeric_digits;
948 
949  if (!is_valid_numeric_typmod(typmod))
950  return -1;
951 
952  /* precision (ie, max # of digits) is in upper bits of typmod */
953  precision = numeric_typmod_precision(typmod);
954 
955  /*
956  * This formula computes the maximum number of NumericDigits we could need
957  * in order to store the specified number of decimal digits. Because the
958  * weight is stored as a number of NumericDigits rather than a number of
959  * decimal digits, it's possible that the first NumericDigit will contain
960  * only a single decimal digit. Thus, the first two decimal digits can
961  * require two NumericDigits to store, but it isn't until we reach
962  * DEC_DIGITS + 2 decimal digits that we potentially need a third
963  * NumericDigit.
964  */
965  numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
966 
967  /*
968  * In most cases, the size of a numeric will be smaller than the value
969  * computed below, because the varlena header will typically get toasted
970  * down to a single byte before being stored on disk, and it may also be
971  * possible to use a short numeric header. But our job here is to compute
972  * the worst case.
973  */
974  return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
975 }
static bool is_valid_numeric_typmod(int32 typmod)
Definition: numeric.c:907
int16 NumericDigit
Definition: numeric.c:101
#define NUMERIC_HDRSZ
Definition: numeric.c:174
static int numeric_typmod_precision(int32 typmod)
Definition: numeric.c:918

References DEC_DIGITS, is_valid_numeric_typmod(), NUMERIC_HDRSZ, and numeric_typmod_precision().

Referenced by type_maximum_size().

◆ numeric_mod_opt_error()

Numeric numeric_mod_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 3368 of file numeric.c.

3369 {
3370  Numeric res;
3371  NumericVar arg1;
3372  NumericVar arg2;
3373  NumericVar result;
3374 
3375  if (have_error)
3376  *have_error = false;
3377 
3378  /*
3379  * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3380  * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3381  * returning NaN. We choose to throw error only for y-is-zero.
3382  */
3383  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3384  {
3385  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3386  return make_result(&const_nan);
3387  if (NUMERIC_IS_INF(num1))
3388  {
3389  if (numeric_sign_internal(num2) == 0)
3390  {
3391  if (have_error)
3392  {
3393  *have_error = true;
3394  return NULL;
3395  }
3396  ereport(ERROR,
3397  (errcode(ERRCODE_DIVISION_BY_ZERO),
3398  errmsg("division by zero")));
3399  }
3400  /* Inf % any nonzero = NaN */
3401  return make_result(&const_nan);
3402  }
3403  /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3404  return duplicate_numeric(num1);
3405  }
3406 
3407  init_var_from_num(num1, &arg1);
3408  init_var_from_num(num2, &arg2);
3409 
3410  init_var(&result);
3411 
3412  /*
3413  * If "have_error" is provided, check for division by zero here
3414  */
3415  if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3416  {
3417  *have_error = true;
3418  return NULL;
3419  }
3420 
3421  mod_var(&arg1, &arg2, &result);
3422 
3423  res = make_result_opt_error(&result, NULL);
3424 
3425  free_var(&result);
3426 
3427  return res;
3428 }
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9846
static Numeric duplicate_numeric(Numeric num)
Definition: numeric.c:7763

References const_nan, NumericVar::digits, duplicate_numeric(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), mod_var(), NumericVar::ndigits, NUMERIC_IS_INF, NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numeric_sign_internal(), and res.

Referenced by executeItemOptUnwrapTarget(), and numeric_mod().

◆ numeric_mul_opt_error()

Numeric numeric_mul_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 3023 of file numeric.c.

3024 {
3025  NumericVar arg1;
3026  NumericVar arg2;
3027  NumericVar result;
3028  Numeric res;
3029 
3030  /*
3031  * Handle NaN and infinities
3032  */
3033  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3034  {
3035  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3036  return make_result(&const_nan);
3037  if (NUMERIC_IS_PINF(num1))
3038  {
3039  switch (numeric_sign_internal(num2))
3040  {
3041  case 0:
3042  return make_result(&const_nan); /* Inf * 0 */
3043  case 1:
3044  return make_result(&const_pinf);
3045  case -1:
3046  return make_result(&const_ninf);
3047  }
3048  Assert(false);
3049  }
3050  if (NUMERIC_IS_NINF(num1))
3051  {
3052  switch (numeric_sign_internal(num2))
3053  {
3054  case 0:
3055  return make_result(&const_nan); /* -Inf * 0 */
3056  case 1:
3057  return make_result(&const_ninf);
3058  case -1:
3059  return make_result(&const_pinf);
3060  }
3061  Assert(false);
3062  }
3063  /* by here, num1 must be finite, so num2 is not */
3064  if (NUMERIC_IS_PINF(num2))
3065  {
3066  switch (numeric_sign_internal(num1))
3067  {
3068  case 0:
3069  return make_result(&const_nan); /* 0 * Inf */
3070  case 1:
3071  return make_result(&const_pinf);
3072  case -1:
3073  return make_result(&const_ninf);
3074  }
3075  Assert(false);
3076  }
3077  Assert(NUMERIC_IS_NINF(num2));
3078  switch (numeric_sign_internal(num1))
3079  {
3080  case 0:
3081  return make_result(&const_nan); /* 0 * -Inf */
3082  case 1:
3083  return make_result(&const_ninf);
3084  case -1:
3085  return make_result(&const_pinf);
3086  }
3087  Assert(false);
3088  }
3089 
3090  /*
3091  * Unpack the values, let mul_var() compute the result and return it.
3092  * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3093  * case of numeric_mul(), which is invoked for the * operator on numerics,
3094  * we request exact representation for the product (rscale = sum(dscale of
3095  * arg1, dscale of arg2)). If the exact result has more digits after the
3096  * decimal point than can be stored in a numeric, we round it. Rounding
3097  * after computing the exact result ensures that the final result is
3098  * correctly rounded (rounding in mul_var() using a truncated product
3099  * would not guarantee this).
3100  */
3101  init_var_from_num(num1, &arg1);
3102  init_var_from_num(num2, &arg2);
3103 
3104  init_var(&result);
3105  mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3106 
3107  if (result.dscale > NUMERIC_DSCALE_MAX)
3108  round_var(&result, NUMERIC_DSCALE_MAX);
3109 
3110  res = make_result_opt_error(&result, have_error);
3111 
3112  free_var(&result);
3113 
3114  return res;
3115 }
#define NUMERIC_DSCALE_MAX
Definition: numeric.c:234
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:11749

References Assert, const_nan, const_ninf, const_pinf, NumericVar::dscale, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), mul_var(), NUMERIC_DSCALE_MAX, NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), res, and round_var().

Referenced by executeItemOptUnwrapTarget(), and numeric_mul().

◆ numeric_normalize()

char* numeric_normalize ( Numeric  num)

Definition at line 1017 of file numeric.c.

1018 {
1019  NumericVar x;
1020  char *str;
1021  int last;
1022 
1023  /*
1024  * Handle NaN and infinities
1025  */
1026  if (NUMERIC_IS_SPECIAL(num))
1027  {
1028  if (NUMERIC_IS_PINF(num))
1029  return pstrdup("Infinity");
1030  else if (NUMERIC_IS_NINF(num))
1031  return pstrdup("-Infinity");
1032  else
1033  return pstrdup("NaN");
1034  }
1035 
1036  init_var_from_num(num, &x);
1037 
1038  str = get_str_from_var(&x);
1039 
1040  /* If there's no decimal point, there's certainly nothing to remove. */
1041  if (strchr(str, '.') != NULL)
1042  {
1043  /*
1044  * Back up over trailing fractional zeroes. Since there is a decimal
1045  * point, this loop will terminate safely.
1046  */
1047  last = strlen(str) - 1;
1048  while (str[last] == '0')
1049  last--;
1050 
1051  /* We want to get rid of the decimal point too, if it's now last. */
1052  if (str[last] == '.')
1053  last--;
1054 
1055  /* Delete whatever we backed up over. */
1056  str[last + 1] = '\0';
1057  }
1058 
1059  return str;
1060 }
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:7494
const char * str
char * pstrdup(const char *in)
Definition: mcxt.c:1695

References get_str_from_var(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, pstrdup(), str, and x.

Referenced by make_scalar_key().

◆ numeric_out_sci()

char* numeric_out_sci ( Numeric  num,
int  scale 
)

Definition at line 983 of file numeric.c.

984 {
985  NumericVar x;
986  char *str;
987 
988  /*
989  * Handle NaN and infinities
990  */
991  if (NUMERIC_IS_SPECIAL(num))
992  {
993  if (NUMERIC_IS_PINF(num))
994  return pstrdup("Infinity");
995  else if (NUMERIC_IS_NINF(num))
996  return pstrdup("-Infinity");
997  else
998  return pstrdup("NaN");
999  }
1000 
1001  init_var_from_num(num, &x);
1002 
1004 
1005  return str;
1006 }
static char * get_str_from_var_sci(const NumericVar *var, int rscale)
Definition: numeric.c:7647
int scale
Definition: pgbench.c:181

References get_str_from_var_sci(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, pstrdup(), scale, str, and x.

Referenced by int8_to_char(), and numeric_to_char().

◆ numeric_sub_opt_error()

Numeric numeric_sub_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 2945 of file numeric.c.

2946 {
2947  NumericVar arg1;
2948  NumericVar arg2;
2949  NumericVar result;
2950  Numeric res;
2951 
2952  /*
2953  * Handle NaN and infinities
2954  */
2955  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2956  {
2957  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2958  return make_result(&const_nan);
2959  if (NUMERIC_IS_PINF(num1))
2960  {
2961  if (NUMERIC_IS_PINF(num2))
2962  return make_result(&const_nan); /* Inf - Inf */
2963  else
2964  return make_result(&const_pinf);
2965  }
2966  if (NUMERIC_IS_NINF(num1))
2967  {
2968  if (NUMERIC_IS_NINF(num2))
2969  return make_result(&const_nan); /* -Inf - -Inf */
2970  else
2971  return make_result(&const_ninf);
2972  }
2973  /* by here, num1 must be finite, so num2 is not */
2974  if (NUMERIC_IS_PINF(num2))
2975  return make_result(&const_ninf);
2976  Assert(NUMERIC_IS_NINF(num2));
2977  return make_result(&const_pinf);
2978  }
2979 
2980  /*
2981  * Unpack the values, let sub_var() compute the result and return it.
2982  */
2983  init_var_from_num(num1, &arg1);
2984  init_var_from_num(num2, &arg2);
2985 
2986  init_var(&result);
2987  sub_var(&arg1, &arg2, &result);
2988 
2989  res = make_result_opt_error(&result, have_error);
2990 
2991  free_var(&result);
2992 
2993  return res;
2994 }
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8548

References Assert, const_nan, const_ninf, const_pinf, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, res, and sub_var().

Referenced by executeItemOptUnwrapTarget(), numeric_sub(), timestamp_part_common(), and timestamptz_part_common().

◆ NumericGetDatum()

◆ random_numeric()

Numeric random_numeric ( pg_prng_state state,
Numeric  rmin,
Numeric  rmax 
)

Definition at line 4228 of file numeric.c.

4229 {
4230  NumericVar rmin_var;
4231  NumericVar rmax_var;
4232  NumericVar result;
4233  Numeric res;
4234 
4235  /* Range bounds must not be NaN/infinity */
4236  if (NUMERIC_IS_SPECIAL(rmin))
4237  {
4238  if (NUMERIC_IS_NAN(rmin))
4239  ereport(ERROR,
4240  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4241  errmsg("lower bound cannot be NaN"));
4242  else
4243  ereport(ERROR,
4244  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4245  errmsg("lower bound cannot be infinity"));
4246  }
4247  if (NUMERIC_IS_SPECIAL(rmax))
4248  {
4249  if (NUMERIC_IS_NAN(rmax))
4250  ereport(ERROR,
4251  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4252  errmsg("upper bound cannot be NaN"));
4253  else
4254  ereport(ERROR,
4255  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4256  errmsg("upper bound cannot be infinity"));
4257  }
4258 
4259  /* Return a random value in the range [rmin, rmax] */
4260  init_var_from_num(rmin, &rmin_var);
4261  init_var_from_num(rmax, &rmax_var);
4262 
4263  init_var(&result);
4264 
4265  random_var(state, &rmin_var, &rmax_var, &result);
4266 
4267  res = make_result(&result);
4268 
4269  free_var(&result);
4270 
4271  return res;
4272 }
static void random_var(pg_prng_state *state, const NumericVar *rmin, const NumericVar *rmax, NumericVar *result)
Definition: numeric.c:11321
Definition: regguts.h:323

References ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, random_var(), and res.

Referenced by numeric_random().