PostgreSQL Source Code  git master
numeric.h File Reference
#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)
 

Macro Definition Documentation

◆ NUMERIC_MAX_DISPLAY_SCALE

#define NUMERIC_MAX_DISPLAY_SCALE   NUMERIC_MAX_PRECISION

Definition at line 39 of file numeric.h.

◆ NUMERIC_MAX_PRECISION

#define NUMERIC_MAX_PRECISION   1000

Definition at line 31 of file numeric.h.

◆ NUMERIC_MAX_RESULT_SCALE

#define NUMERIC_MAX_RESULT_SCALE   (NUMERIC_MAX_PRECISION * 2)

Definition at line 42 of file numeric.h.

◆ NUMERIC_MAX_SCALE

#define NUMERIC_MAX_SCALE   1000

Definition at line 34 of file numeric.h.

◆ NUMERIC_MIN_DISPLAY_SCALE

#define NUMERIC_MIN_DISPLAY_SCALE   0

Definition at line 40 of file numeric.h.

◆ NUMERIC_MIN_SCALE

#define NUMERIC_MIN_SCALE   (-1000)

Definition at line 33 of file numeric.h.

◆ NUMERIC_MIN_SIG_DIGITS

#define NUMERIC_MIN_SIG_DIGITS   16

Definition at line 49 of file numeric.h.

◆ PG_GETARG_NUMERIC

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

Definition at line 77 of file numeric.h.

◆ PG_GETARG_NUMERIC_COPY

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

Definition at line 78 of file numeric.h.

◆ PG_RETURN_NUMERIC

#define PG_RETURN_NUMERIC (   x)    return NumericGetDatum(x)

Definition at line 79 of file numeric.h.

Typedef Documentation

◆ Numeric

typedef struct NumericData* Numeric

Definition at line 53 of file numeric.h.

Function Documentation

◆ DatumGetNumeric()

◆ DatumGetNumericCopy()

static Numeric DatumGetNumericCopy ( Datum  X)
inlinestatic

Definition at line 66 of file numeric.h.

67 {
68  return (Numeric) PG_DETOAST_DATUM_COPY(X);
69 }
#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 4253 of file numeric.c.

4254 {
4255  Numeric res;
4256  NumericVar result;
4257  int rscale;
4258  int w;
4259  int m;
4260 
4261  init_var(&result);
4262 
4263  /* result scale */
4264  rscale = log10val2 < 0 ? 0 : log10val2;
4265 
4266  /* how much to decrease the weight by */
4267  w = log10val2 / DEC_DIGITS;
4268  /* how much is left to divide by */
4269  m = log10val2 % DEC_DIGITS;
4270  if (m < 0)
4271  {
4272  m += DEC_DIGITS;
4273  w--;
4274  }
4275 
4276  /*
4277  * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4278  * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4279  * one more.
4280  */
4281  if (m > 0)
4282  {
4283 #if DEC_DIGITS == 4
4284  static const int pow10[] = {1, 10, 100, 1000};
4285 #elif DEC_DIGITS == 2
4286  static const int pow10[] = {1, 10};
4287 #elif DEC_DIGITS == 1
4288  static const int pow10[] = {1};
4289 #else
4290 #error unsupported NBASE
4291 #endif
4292  int64 factor = pow10[DEC_DIGITS - m];
4293  int64 new_val1;
4294 
4295  StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4296 
4297  if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4298  {
4299 #ifdef HAVE_INT128
4300  /* do the multiplication using 128-bit integers */
4301  int128 tmp;
4302 
4303  tmp = (int128) val1 * (int128) factor;
4304 
4305  int128_to_numericvar(tmp, &result);
4306 #else
4307  /* do the multiplication using numerics */
4308  NumericVar tmp;
4309 
4310  init_var(&tmp);
4311 
4312  int64_to_numericvar(val1, &result);
4313  int64_to_numericvar(factor, &tmp);
4314  mul_var(&result, &tmp, &result, 0);
4315 
4316  free_var(&tmp);
4317 #endif
4318  }
4319  else
4320  int64_to_numericvar(new_val1, &result);
4321 
4322  w++;
4323  }
4324  else
4325  int64_to_numericvar(val1, &result);
4326 
4327  result.weight -= w;
4328  result.dscale = rscale;
4329 
4330  res = make_result(&result);
4331 
4332  free_var(&result);
4333 
4334  return res;
4335 }
static void free_var(NumericVar *var)
Definition: numeric.c:6899
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8599
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:8034
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7821
#define DEC_DIGITS
Definition: numeric.c:98
#define init_var(v)
Definition: numeric.c:485
#define unlikely(x)
Definition: c.h:295
#define lengthof(array)
Definition: c.h:772
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:920
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:215
int dscale
Definition: numeric.c:309
int weight
Definition: numeric.c:307

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 2866 of file numeric.c.

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

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 3143 of file numeric.c.

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

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 4346 of file numeric.c.

4347 {
4348  NumericVar x;
4349  int32 result;
4350 
4351  if (have_error)
4352  *have_error = false;
4353 
4354  if (NUMERIC_IS_SPECIAL(num))
4355  {
4356  if (have_error)
4357  {
4358  *have_error = true;
4359  return 0;
4360  }
4361  else
4362  {
4363  if (NUMERIC_IS_NAN(num))
4364  ereport(ERROR,
4365  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4366  errmsg("cannot convert NaN to %s", "integer")));
4367  else
4368  ereport(ERROR,
4369  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4370  errmsg("cannot convert infinity to %s", "integer")));
4371  }
4372  }
4373 
4374  /* Convert to variable format, then convert to int4 */
4375  init_var_from_num(num, &x);
4376 
4377  if (!numericvar_to_int32(&x, &result))
4378  {
4379  if (have_error)
4380  {
4381  *have_error = true;
4382  return 0;
4383  }
4384  else
4385  {
4386  ereport(ERROR,
4387  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4388  errmsg("integer out of range")));
4389  }
4390  }
4391 
4392  return result;
4393 }
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition: numeric.c:4409
signed int int32
Definition: c.h:478
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 getArrayIndex(), and numeric_int4().

◆ numeric_is_inf()

bool numeric_is_inf ( Numeric  num)

Definition at line 852 of file numeric.c.

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

References NUMERIC_IS_INF.

Referenced by PLyNumber_ToJsonbValue().

◆ numeric_is_nan()

bool numeric_is_nan ( Numeric  num)

Definition at line 841 of file numeric.c.

842 {
843  return NUMERIC_IS_NAN(num);
844 }

References NUMERIC_IS_NAN.

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

◆ numeric_maximum_size()

int32 numeric_maximum_size ( int32  typmod)

Definition at line 943 of file numeric.c.

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

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 3367 of file numeric.c.

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

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 3022 of file numeric.c.

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

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 1016 of file numeric.c.

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

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

Referenced by make_scalar_key().

◆ numeric_out_sci()

char* numeric_out_sci ( Numeric  num,
int  scale 
)

Definition at line 982 of file numeric.c.

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

References get_str_from_var_sci(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, pstrdup(), scale, generate_unaccent_rules::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 2944 of file numeric.c.

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

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()