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 DatumGetNumeric(X)   ((Numeric) PG_DETOAST_DATUM(X))
 
#define DatumGetNumericCopy(X)   ((Numeric) PG_DETOAST_DATUM_COPY(X))
 
#define NumericGetDatum(X)   PointerGetDatum(X)
 
#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

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 *error)
 

Macro Definition Documentation

◆ DatumGetNumeric

#define DatumGetNumeric (   X)    ((Numeric) PG_DETOAST_DATUM(X))

Definition at line 59 of file numeric.h.

◆ DatumGetNumericCopy

#define DatumGetNumericCopy (   X)    ((Numeric) PG_DETOAST_DATUM_COPY(X))

Definition at line 60 of file numeric.h.

◆ 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.

◆ NumericGetDatum

#define NumericGetDatum (   X)    PointerGetDatum(X)

Definition at line 61 of file numeric.h.

◆ PG_GETARG_NUMERIC

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

Definition at line 62 of file numeric.h.

◆ PG_GETARG_NUMERIC_COPY

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

Definition at line 63 of file numeric.h.

◆ PG_RETURN_NUMERIC

#define PG_RETURN_NUMERIC (   x)    return NumericGetDatum(x)

Definition at line 64 of file numeric.h.

Typedef Documentation

◆ Numeric

typedef struct NumericData* Numeric

Definition at line 53 of file numeric.h.

Function Documentation

◆ int64_div_fast_to_numeric()

Numeric int64_div_fast_to_numeric ( int64  val1,
int  log10val2 
)

Definition at line 4158 of file numeric.c.

4159 {
4160  Numeric res;
4161  NumericVar result;
4162  int64 saved_val1 = val1;
4163  int w;
4164  int m;
4165 
4166  /* how much to decrease the weight by */
4167  w = log10val2 / DEC_DIGITS;
4168  /* how much is left */
4169  m = log10val2 % DEC_DIGITS;
4170 
4171  /*
4172  * If there is anything left, multiply the dividend by what's left, then
4173  * shift the weight by one more.
4174  */
4175  if (m > 0)
4176  {
4177  static int pow10[] = {1, 10, 100, 1000};
4178 
4179  StaticAssertStmt(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4180  if (unlikely(pg_mul_s64_overflow(val1, pow10[DEC_DIGITS - m], &val1)))
4181  {
4182  /*
4183  * If it doesn't fit, do the whole computation in numeric the slow
4184  * way. Note that va1l may have been overwritten, so use
4185  * saved_val1 instead.
4186  */
4187  int val2 = 1;
4188 
4189  for (int i = 0; i < log10val2; i++)
4190  val2 *= 10;
4191  res = numeric_div_opt_error(int64_to_numeric(saved_val1), int64_to_numeric(val2), NULL);
4194  Int32GetDatum(log10val2)));
4195  return res;
4196  }
4197  w++;
4198  }
4199 
4200  init_var(&result);
4201 
4202  int64_to_numericvar(val1, &result);
4203 
4204  result.weight -= w;
4205  result.dscale += w * DEC_DIGITS - (DEC_DIGITS - m);
4206 
4207  res = make_result(&result);
4208 
4209  free_var(&result);
4210 
4211  return res;
4212 }
static void free_var(NumericVar *var)
Definition: numeric.c:6774
Datum numeric_round(PG_FUNCTION_ARGS)
Definition: numeric.c:1462
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3061
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4137
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:7652
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7447
#define DEC_DIGITS
Definition: numeric.c:98
#define init_var(v)
Definition: numeric.c:485
#define unlikely(x)
Definition: c.h:273
#define lengthof(array)
Definition: c.h:734
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:918
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:633
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:215
int i
Definition: isn.c:73
#define DatumGetNumeric(X)
Definition: numeric.h:59
#define NumericGetDatum(X)
Definition: numeric.h:61
#define Int32GetDatum(X)
Definition: postgres.h:523
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, StaticAssertStmt, 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 2784 of file numeric.c.

2785 {
2786  NumericVar arg1;
2787  NumericVar arg2;
2788  NumericVar result;
2789  Numeric res;
2790 
2791  /*
2792  * Handle NaN and infinities
2793  */
2794  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2795  {
2796  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2797  return make_result(&const_nan);
2798  if (NUMERIC_IS_PINF(num1))
2799  {
2800  if (NUMERIC_IS_NINF(num2))
2801  return make_result(&const_nan); /* Inf + -Inf */
2802  else
2803  return make_result(&const_pinf);
2804  }
2805  if (NUMERIC_IS_NINF(num1))
2806  {
2807  if (NUMERIC_IS_PINF(num2))
2808  return make_result(&const_nan); /* -Inf + Inf */
2809  else
2810  return make_result(&const_ninf);
2811  }
2812  /* by here, num1 must be finite, so num2 is not */
2813  if (NUMERIC_IS_PINF(num2))
2814  return make_result(&const_pinf);
2815  Assert(NUMERIC_IS_NINF(num2));
2816  return make_result(&const_ninf);
2817  }
2818 
2819  /*
2820  * Unpack the values, let add_var() compute the result and return it.
2821  */
2822  init_var_from_num(num1, &arg1);
2823  init_var_from_num(num2, &arg2);
2824 
2825  init_var(&result);
2826  add_var(&arg1, &arg2, &result);
2827 
2828  res = make_result_opt_error(&result, have_error);
2829 
2830  free_var(&result);
2831 
2832  return res;
2833 }
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:7979
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:173
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7007
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:205
static Numeric make_result_opt_error(const NumericVar *var, bool *error)
Definition: numeric.c:7338
#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 3061 of file numeric.c.

3062 {
3063  NumericVar arg1;
3064  NumericVar arg2;
3065  NumericVar result;
3066  Numeric res;
3067  int rscale;
3068 
3069  if (have_error)
3070  *have_error = false;
3071 
3072  /*
3073  * Handle NaN and infinities
3074  */
3075  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3076  {
3077  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3078  return make_result(&const_nan);
3079  if (NUMERIC_IS_PINF(num1))
3080  {
3081  if (NUMERIC_IS_SPECIAL(num2))
3082  return make_result(&const_nan); /* Inf / [-]Inf */
3083  switch (numeric_sign_internal(num2))
3084  {
3085  case 0:
3086  if (have_error)
3087  {
3088  *have_error = true;
3089  return NULL;
3090  }
3091  ereport(ERROR,
3092  (errcode(ERRCODE_DIVISION_BY_ZERO),
3093  errmsg("division by zero")));
3094  break;
3095  case 1:
3096  return make_result(&const_pinf);
3097  case -1:
3098  return make_result(&const_ninf);
3099  }
3100  Assert(false);
3101  }
3102  if (NUMERIC_IS_NINF(num1))
3103  {
3104  if (NUMERIC_IS_SPECIAL(num2))
3105  return make_result(&const_nan); /* -Inf / [-]Inf */
3106  switch (numeric_sign_internal(num2))
3107  {
3108  case 0:
3109  if (have_error)
3110  {
3111  *have_error = true;
3112  return NULL;
3113  }
3114  ereport(ERROR,
3115  (errcode(ERRCODE_DIVISION_BY_ZERO),
3116  errmsg("division by zero")));
3117  break;
3118  case 1:
3119  return make_result(&const_ninf);
3120  case -1:
3121  return make_result(&const_pinf);
3122  }
3123  Assert(false);
3124  }
3125  /* by here, num1 must be finite, so num2 is not */
3126 
3127  /*
3128  * POSIX would have us return zero or minus zero if num1 is zero, and
3129  * otherwise throw an underflow error. But the numeric type doesn't
3130  * really do underflow, so let's just return zero.
3131  */
3132  return make_result(&const_zero);
3133  }
3134 
3135  /*
3136  * Unpack the arguments
3137  */
3138  init_var_from_num(num1, &arg1);
3139  init_var_from_num(num2, &arg2);
3140 
3141  init_var(&result);
3142 
3143  /*
3144  * Select scale for division result
3145  */
3146  rscale = select_div_scale(&arg1, &arg2);
3147 
3148  /*
3149  * If "have_error" is provided, check for division by zero here
3150  */
3151  if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3152  {
3153  *have_error = true;
3154  return NULL;
3155  }
3156 
3157  /*
3158  * Do the divide and return the result
3159  */
3160  div_var(&arg1, &arg2, &result, rscale, true);
3161 
3162  res = make_result_opt_error(&result, have_error);
3163 
3164  free_var(&result);
3165 
3166  return res;
3167 }
static int numeric_sign_internal(Numeric num)
Definition: numeric.c:1397
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9162
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:8425
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
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 error 
)

Definition at line 4223 of file numeric.c.

4224 {
4225  NumericVar x;
4226  int32 result;
4227 
4228  if (have_error)
4229  *have_error = false;
4230 
4231  if (NUMERIC_IS_SPECIAL(num))
4232  {
4233  if (have_error)
4234  {
4235  *have_error = true;
4236  return 0;
4237  }
4238  else
4239  {
4240  if (NUMERIC_IS_NAN(num))
4241  ereport(ERROR,
4242  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4243  errmsg("cannot convert NaN to %s", "integer")));
4244  else
4245  ereport(ERROR,
4246  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4247  errmsg("cannot convert infinity to %s", "integer")));
4248  }
4249  }
4250 
4251  /* Convert to variable format, then convert to int4 */
4252  init_var_from_num(num, &x);
4253 
4254  if (!numericvar_to_int32(&x, &result))
4255  {
4256  if (have_error)
4257  {
4258  *have_error = true;
4259  return 0;
4260  }
4261  else
4262  {
4263  ereport(ERROR,
4264  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4265  errmsg("integer out of range")));
4266  }
4267  }
4268 
4269  return result;
4270 }
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition: numeric.c:4286
signed int int32
Definition: c.h:429
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 781 of file numeric.c.

782 {
783  return NUMERIC_IS_INF(num);
784 }
#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 770 of file numeric.c.

771 {
772  return NUMERIC_IS_NAN(num);
773 }

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

873 {
874  int precision;
875  int numeric_digits;
876 
877  if (!is_valid_numeric_typmod(typmod))
878  return -1;
879 
880  /* precision (ie, max # of digits) is in upper bits of typmod */
881  precision = numeric_typmod_precision(typmod);
882 
883  /*
884  * This formula computes the maximum number of NumericDigits we could need
885  * in order to store the specified number of decimal digits. Because the
886  * weight is stored as a number of NumericDigits rather than a number of
887  * decimal digits, it's possible that the first NumericDigit will contain
888  * only a single decimal digit. Thus, the first two decimal digits can
889  * require two NumericDigits to store, but it isn't until we reach
890  * DEC_DIGITS + 2 decimal digits that we potentially need a third
891  * NumericDigit.
892  */
893  numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
894 
895  /*
896  * In most cases, the size of a numeric will be smaller than the value
897  * computed below, because the varlena header will typically get toasted
898  * down to a single byte before being stored on disk, and it may also be
899  * possible to use a short numeric header. But our job here is to compute
900  * the worst case.
901  */
902  return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
903 }
static bool is_valid_numeric_typmod(int32 typmod)
Definition: numeric.c:835
int16 NumericDigit
Definition: numeric.c:102
#define NUMERIC_HDRSZ
Definition: numeric.c:175
static int numeric_typmod_precision(int32 typmod)
Definition: numeric.c:846

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

3286 {
3287  Numeric res;
3288  NumericVar arg1;
3289  NumericVar arg2;
3290  NumericVar result;
3291 
3292  if (have_error)
3293  *have_error = false;
3294 
3295  /*
3296  * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3297  * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3298  * returning NaN. We choose to throw error only for y-is-zero.
3299  */
3300  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3301  {
3302  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3303  return make_result(&const_nan);
3304  if (NUMERIC_IS_INF(num1))
3305  {
3306  if (numeric_sign_internal(num2) == 0)
3307  {
3308  if (have_error)
3309  {
3310  *have_error = true;
3311  return NULL;
3312  }
3313  ereport(ERROR,
3314  (errcode(ERRCODE_DIVISION_BY_ZERO),
3315  errmsg("division by zero")));
3316  }
3317  /* Inf % any nonzero = NaN */
3318  return make_result(&const_nan);
3319  }
3320  /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3321  return duplicate_numeric(num1);
3322  }
3323 
3324  init_var_from_num(num1, &arg1);
3325  init_var_from_num(num2, &arg2);
3326 
3327  init_var(&result);
3328 
3329  /*
3330  * If "have_error" is provided, check for division by zero here
3331  */
3332  if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3333  {
3334  *have_error = true;
3335  return NULL;
3336  }
3337 
3338  mod_var(&arg1, &arg2, &result);
3339 
3340  res = make_result_opt_error(&result, NULL);
3341 
3342  free_var(&result);
3343 
3344  return res;
3345 }
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9231
static Numeric duplicate_numeric(Numeric num)
Definition: numeric.c:7319

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

2941 {
2942  NumericVar arg1;
2943  NumericVar arg2;
2944  NumericVar result;
2945  Numeric res;
2946 
2947  /*
2948  * Handle NaN and infinities
2949  */
2950  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2951  {
2952  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2953  return make_result(&const_nan);
2954  if (NUMERIC_IS_PINF(num1))
2955  {
2956  switch (numeric_sign_internal(num2))
2957  {
2958  case 0:
2959  return make_result(&const_nan); /* Inf * 0 */
2960  case 1:
2961  return make_result(&const_pinf);
2962  case -1:
2963  return make_result(&const_ninf);
2964  }
2965  Assert(false);
2966  }
2967  if (NUMERIC_IS_NINF(num1))
2968  {
2969  switch (numeric_sign_internal(num2))
2970  {
2971  case 0:
2972  return make_result(&const_nan); /* -Inf * 0 */
2973  case 1:
2974  return make_result(&const_ninf);
2975  case -1:
2976  return make_result(&const_pinf);
2977  }
2978  Assert(false);
2979  }
2980  /* by here, num1 must be finite, so num2 is not */
2981  if (NUMERIC_IS_PINF(num2))
2982  {
2983  switch (numeric_sign_internal(num1))
2984  {
2985  case 0:
2986  return make_result(&const_nan); /* 0 * Inf */
2987  case 1:
2988  return make_result(&const_pinf);
2989  case -1:
2990  return make_result(&const_ninf);
2991  }
2992  Assert(false);
2993  }
2994  Assert(NUMERIC_IS_NINF(num2));
2995  switch (numeric_sign_internal(num1))
2996  {
2997  case 0:
2998  return make_result(&const_nan); /* 0 * -Inf */
2999  case 1:
3000  return make_result(&const_ninf);
3001  case -1:
3002  return make_result(&const_pinf);
3003  }
3004  Assert(false);
3005  }
3006 
3007  /*
3008  * Unpack the values, let mul_var() compute the result and return it.
3009  * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3010  * case of numeric_mul(), which is invoked for the * operator on numerics,
3011  * we request exact representation for the product (rscale = sum(dscale of
3012  * arg1, dscale of arg2)). If the exact result has more digits after the
3013  * decimal point than can be stored in a numeric, we round it. Rounding
3014  * after computing the exact result ensures that the final result is
3015  * correctly rounded (rounding in mul_var() using a truncated product
3016  * would not guarantee this).
3017  */
3018  init_var_from_num(num1, &arg1);
3019  init_var_from_num(num2, &arg2);
3020 
3021  init_var(&result);
3022  mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3023 
3024  if (result.dscale > NUMERIC_DSCALE_MAX)
3025  round_var(&result, NUMERIC_DSCALE_MAX);
3026 
3027  res = make_result_opt_error(&result, have_error);
3028 
3029  free_var(&result);
3030 
3031  return res;
3032 }
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8217
#define NUMERIC_DSCALE_MAX
Definition: numeric.c:235
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10943

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

946 {
947  NumericVar x;
948  char *str;
949  int last;
950 
951  /*
952  * Handle NaN and infinities
953  */
954  if (NUMERIC_IS_SPECIAL(num))
955  {
956  if (NUMERIC_IS_PINF(num))
957  return pstrdup("Infinity");
958  else if (NUMERIC_IS_NINF(num))
959  return pstrdup("-Infinity");
960  else
961  return pstrdup("NaN");
962  }
963 
964  init_var_from_num(num, &x);
965 
966  str = get_str_from_var(&x);
967 
968  /* If there's no decimal point, there's certainly nothing to remove. */
969  if (strchr(str, '.') != NULL)
970  {
971  /*
972  * Back up over trailing fractional zeroes. Since there is a decimal
973  * point, this loop will terminate safely.
974  */
975  last = strlen(str) - 1;
976  while (str[last] == '0')
977  last--;
978 
979  /* We want to get rid of the decimal point too, if it's now last. */
980  if (str[last] == '.')
981  last--;
982 
983  /* Delete whatever we backed up over. */
984  str[last + 1] = '\0';
985  }
986 
987  return str;
988 }
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:7050
char * pstrdup(const char *in)
Definition: mcxt.c:1305

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

912 {
913  NumericVar x;
914  char *str;
915 
916  /*
917  * Handle NaN and infinities
918  */
919  if (NUMERIC_IS_SPECIAL(num))
920  {
921  if (NUMERIC_IS_PINF(num))
922  return pstrdup("Infinity");
923  else if (NUMERIC_IS_NINF(num))
924  return pstrdup("-Infinity");
925  else
926  return pstrdup("NaN");
927  }
928 
929  init_var_from_num(num, &x);
930 
932 
933  return str;
934 }
static char * get_str_from_var_sci(const NumericVar *var, int rscale)
Definition: numeric.c:7203
int scale
Definition: pgbench.c:194

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

2863 {
2864  NumericVar arg1;
2865  NumericVar arg2;
2866  NumericVar result;
2867  Numeric res;
2868 
2869  /*
2870  * Handle NaN and infinities
2871  */
2872  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2873  {
2874  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2875  return make_result(&const_nan);
2876  if (NUMERIC_IS_PINF(num1))
2877  {
2878  if (NUMERIC_IS_PINF(num2))
2879  return make_result(&const_nan); /* Inf - Inf */
2880  else
2881  return make_result(&const_pinf);
2882  }
2883  if (NUMERIC_IS_NINF(num1))
2884  {
2885  if (NUMERIC_IS_NINF(num2))
2886  return make_result(&const_nan); /* -Inf - -Inf */
2887  else
2888  return make_result(&const_ninf);
2889  }
2890  /* by here, num1 must be finite, so num2 is not */
2891  if (NUMERIC_IS_PINF(num2))
2892  return make_result(&const_ninf);
2893  Assert(NUMERIC_IS_NINF(num2));
2894  return make_result(&const_pinf);
2895  }
2896 
2897  /*
2898  * Unpack the values, let sub_var() compute the result and return it.
2899  */
2900  init_var_from_num(num1, &arg1);
2901  init_var_from_num(num2, &arg2);
2902 
2903  init_var(&result);
2904  sub_var(&arg1, &arg2, &result);
2905 
2906  res = make_result_opt_error(&result, have_error);
2907 
2908  free_var(&result);
2909 
2910  return res;
2911 }
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8096

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