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

4158 {
4159  Numeric res;
4160  NumericVar result;
4161  int64 saved_val1 = val1;
4162  int w;
4163  int m;
4164 
4165  /* how much to decrease the weight by */
4166  w = log10val2 / DEC_DIGITS;
4167  /* how much is left */
4168  m = log10val2 % DEC_DIGITS;
4169 
4170  /*
4171  * If there is anything left, multiply the dividend by what's left, then
4172  * shift the weight by one more.
4173  */
4174  if (m > 0)
4175  {
4176  static int pow10[] = {1, 10, 100, 1000};
4177 
4178  StaticAssertStmt(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4179  if (unlikely(pg_mul_s64_overflow(val1, pow10[DEC_DIGITS - m], &val1)))
4180  {
4181  /*
4182  * If it doesn't fit, do the whole computation in numeric the slow
4183  * way. Note that va1l may have been overwritten, so use
4184  * saved_val1 instead.
4185  */
4186  int val2 = 1;
4187 
4188  for (int i = 0; i < log10val2; i++)
4189  val2 *= 10;
4190  res = numeric_div_opt_error(int64_to_numeric(saved_val1), int64_to_numeric(val2), NULL);
4193  Int32GetDatum(log10val2)));
4194  return res;
4195  }
4196  w++;
4197  }
4198 
4199  init_var(&result);
4200 
4201  int64_to_numericvar(val1, &result);
4202 
4203  result.weight -= w;
4204  result.dscale += w * DEC_DIGITS - (DEC_DIGITS - m);
4205 
4206  res = make_result(&result);
4207 
4208  free_var(&result);
4209 
4210  return res;
4211 }
static void free_var(NumericVar *var)
Definition: numeric.c:6773
Datum numeric_round(PG_FUNCTION_ARGS)
Definition: numeric.c:1461
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3060
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4136
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:7651
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7446
#define DEC_DIGITS
Definition: numeric.c:99
#define init_var(v)
Definition: numeric.c:486
#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:310
int weight
Definition: numeric.c:308

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

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

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

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

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

781 {
782  return NUMERIC_IS_INF(num);
783 }
#define NUMERIC_IS_INF(n)
Definition: numeric.c:208

References NUMERIC_IS_INF.

Referenced by PLyNumber_ToJsonbValue().

◆ numeric_is_nan()

bool numeric_is_nan ( Numeric  num)

Definition at line 769 of file numeric.c.

770 {
771  return NUMERIC_IS_NAN(num);
772 }

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

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

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

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

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

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

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

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

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

911 {
912  NumericVar x;
913  char *str;
914 
915  /*
916  * Handle NaN and infinities
917  */
918  if (NUMERIC_IS_SPECIAL(num))
919  {
920  if (NUMERIC_IS_PINF(num))
921  return pstrdup("Infinity");
922  else if (NUMERIC_IS_NINF(num))
923  return pstrdup("-Infinity");
924  else
925  return pstrdup("NaN");
926  }
927 
928  init_var_from_num(num, &x);
929 
931 
932  return str;
933 }
static char * get_str_from_var_sci(const NumericVar *var, int rscale)
Definition: numeric.c:7202
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 2861 of file numeric.c.

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

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