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

4230 {
4231  Numeric res;
4232  NumericVar result;
4233  int64 saved_val1 = val1;
4234  int w;
4235  int m;
4236 
4237  /* how much to decrease the weight by */
4238  w = log10val2 / DEC_DIGITS;
4239  /* how much is left */
4240  m = log10val2 % DEC_DIGITS;
4241 
4242  /*
4243  * If there is anything left, multiply the dividend by what's left, then
4244  * shift the weight by one more.
4245  */
4246  if (m > 0)
4247  {
4248  static int pow10[] = {1, 10, 100, 1000};
4249 
4250  StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4251 
4252  if (unlikely(pg_mul_s64_overflow(val1, pow10[DEC_DIGITS - m], &val1)))
4253  {
4254  /*
4255  * If it doesn't fit, do the whole computation in numeric the slow
4256  * way. Note that va1l may have been overwritten, so use
4257  * saved_val1 instead.
4258  */
4259  int val2 = 1;
4260 
4261  for (int i = 0; i < log10val2; i++)
4262  val2 *= 10;
4263  res = numeric_div_opt_error(int64_to_numeric(saved_val1), int64_to_numeric(val2), NULL);
4266  Int32GetDatum(log10val2)));
4267  return res;
4268  }
4269  w++;
4270  }
4271 
4272  init_var(&result);
4273 
4274  int64_to_numericvar(val1, &result);
4275 
4276  result.weight -= w;
4277  result.dscale += w * DEC_DIGITS - (DEC_DIGITS - m);
4278 
4279  res = make_result(&result);
4280 
4281  free_var(&result);
4282 
4283  return res;
4284 }
static void free_var(NumericVar *var)
Definition: numeric.c:6848
Datum numeric_round(PG_FUNCTION_ARGS)
Definition: numeric.c:1533
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3132
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4208
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:7923
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7710
#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
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:215
int i
Definition: isn.c:73
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:60
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:72
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
int dscale
Definition: numeric.c:309
int weight
Definition: numeric.c:307

References DatumGetNumeric(), DEC_DIGITS, DirectFunctionCall2, NumericVar::dscale, free_var(), i, init_var, Int32GetDatum(), int64_to_numeric(), int64_to_numericvar(), lengthof, make_result(), numeric_div_opt_error(), numeric_round(), NumericGetDatum(), 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 2855 of file numeric.c.

2856 {
2857  NumericVar arg1;
2858  NumericVar arg2;
2859  NumericVar result;
2860  Numeric res;
2861 
2862  /*
2863  * Handle NaN and infinities
2864  */
2865  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2866  {
2867  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2868  return make_result(&const_nan);
2869  if (NUMERIC_IS_PINF(num1))
2870  {
2871  if (NUMERIC_IS_NINF(num2))
2872  return make_result(&const_nan); /* Inf + -Inf */
2873  else
2874  return make_result(&const_pinf);
2875  }
2876  if (NUMERIC_IS_NINF(num1))
2877  {
2878  if (NUMERIC_IS_PINF(num2))
2879  return make_result(&const_nan); /* -Inf + Inf */
2880  else
2881  return make_result(&const_ninf);
2882  }
2883  /* by here, num1 must be finite, so num2 is not */
2884  if (NUMERIC_IS_PINF(num2))
2885  return make_result(&const_pinf);
2886  Assert(NUMERIC_IS_NINF(num2));
2887  return make_result(&const_ninf);
2888  }
2889 
2890  /*
2891  * Unpack the values, let add_var() compute the result and return it.
2892  */
2893  init_var_from_num(num1, &arg1);
2894  init_var_from_num(num2, &arg2);
2895 
2896  init_var(&result);
2897  add_var(&arg1, &arg2, &result);
2898 
2899  res = make_result_opt_error(&result, have_error);
2900 
2901  free_var(&result);
2902 
2903  return res;
2904 }
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:8250
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:173
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7270
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:205
static Numeric make_result_opt_error(const NumericVar *var, bool *have_error)
Definition: numeric.c:7601
#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 3132 of file numeric.c.

3133 {
3134  NumericVar arg1;
3135  NumericVar arg2;
3136  NumericVar result;
3137  Numeric res;
3138  int rscale;
3139 
3140  if (have_error)
3141  *have_error = false;
3142 
3143  /*
3144  * Handle NaN and infinities
3145  */
3146  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3147  {
3148  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3149  return make_result(&const_nan);
3150  if (NUMERIC_IS_PINF(num1))
3151  {
3152  if (NUMERIC_IS_SPECIAL(num2))
3153  return make_result(&const_nan); /* Inf / [-]Inf */
3154  switch (numeric_sign_internal(num2))
3155  {
3156  case 0:
3157  if (have_error)
3158  {
3159  *have_error = true;
3160  return NULL;
3161  }
3162  ereport(ERROR,
3163  (errcode(ERRCODE_DIVISION_BY_ZERO),
3164  errmsg("division by zero")));
3165  break;
3166  case 1:
3167  return make_result(&const_pinf);
3168  case -1:
3169  return make_result(&const_ninf);
3170  }
3171  Assert(false);
3172  }
3173  if (NUMERIC_IS_NINF(num1))
3174  {
3175  if (NUMERIC_IS_SPECIAL(num2))
3176  return make_result(&const_nan); /* -Inf / [-]Inf */
3177  switch (numeric_sign_internal(num2))
3178  {
3179  case 0:
3180  if (have_error)
3181  {
3182  *have_error = true;
3183  return NULL;
3184  }
3185  ereport(ERROR,
3186  (errcode(ERRCODE_DIVISION_BY_ZERO),
3187  errmsg("division by zero")));
3188  break;
3189  case 1:
3190  return make_result(&const_ninf);
3191  case -1:
3192  return make_result(&const_pinf);
3193  }
3194  Assert(false);
3195  }
3196  /* by here, num1 must be finite, so num2 is not */
3197 
3198  /*
3199  * POSIX would have us return zero or minus zero if num1 is zero, and
3200  * otherwise throw an underflow error. But the numeric type doesn't
3201  * really do underflow, so let's just return zero.
3202  */
3203  return make_result(&const_zero);
3204  }
3205 
3206  /*
3207  * Unpack the arguments
3208  */
3209  init_var_from_num(num1, &arg1);
3210  init_var_from_num(num2, &arg2);
3211 
3212  init_var(&result);
3213 
3214  /*
3215  * Select scale for division result
3216  */
3217  rscale = select_div_scale(&arg1, &arg2);
3218 
3219  /*
3220  * If "have_error" is provided, check for division by zero here
3221  */
3222  if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3223  {
3224  *have_error = true;
3225  return NULL;
3226  }
3227 
3228  /*
3229  * Do the divide and return the result
3230  */
3231  div_var(&arg1, &arg2, &result, rscale, true);
3232 
3233  res = make_result_opt_error(&result, have_error);
3234 
3235  free_var(&result);
3236 
3237  return res;
3238 }
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:9596
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:8696
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(), int64_div_fast_to_numeric(), 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 4295 of file numeric.c.

4296 {
4297  NumericVar x;
4298  int32 result;
4299 
4300  if (have_error)
4301  *have_error = false;
4302 
4303  if (NUMERIC_IS_SPECIAL(num))
4304  {
4305  if (have_error)
4306  {
4307  *have_error = true;
4308  return 0;
4309  }
4310  else
4311  {
4312  if (NUMERIC_IS_NAN(num))
4313  ereport(ERROR,
4314  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4315  errmsg("cannot convert NaN to %s", "integer")));
4316  else
4317  ereport(ERROR,
4318  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4319  errmsg("cannot convert infinity to %s", "integer")));
4320  }
4321  }
4322 
4323  /* Convert to variable format, then convert to int4 */
4324  init_var_from_num(num, &x);
4325 
4326  if (!numericvar_to_int32(&x, &result))
4327  {
4328  if (have_error)
4329  {
4330  *have_error = true;
4331  return 0;
4332  }
4333  else
4334  {
4335  ereport(ERROR,
4336  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4337  errmsg("integer out of range")));
4338  }
4339  }
4340 
4341  return result;
4342 }
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition: numeric.c:4358
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 3356 of file numeric.c.

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

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

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

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:7313
char * pstrdup(const char *in)
Definition: mcxt.c:1624

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:7466
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 2933 of file numeric.c.

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

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