Skip to content

Commit e46f24a

Browse files
author
Nikita Glukhov
committed
Add numeric_get_small(), small_to_numeric()
1 parent 58a9031 commit e46f24a

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

src/backend/utils/adt/numeric.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3175,6 +3175,79 @@ numeric_float4(PG_FUNCTION_ARGS)
31753175
}
31763176

31773177

3178+
bool
3179+
numeric_get_small(Numeric value, uint32 *out)
3180+
{
3181+
NumericDigit *digits;
3182+
uint32 result;
3183+
int weight,
3184+
ndigits,
3185+
i;
3186+
3187+
if (NUMERIC_SIGN(value) == NUMERIC_NAN)
3188+
return false;
3189+
3190+
if (NUMERIC_DSCALE(value) != 0)
3191+
return false;
3192+
3193+
weight = NUMERIC_WEIGHT(value);
3194+
if (weight > 2)
3195+
return false;
3196+
3197+
digits = NUMERIC_DIGITS(value);
3198+
if (weight == 2 && digits[0] > 20)
3199+
return false;
3200+
3201+
ndigits = NUMERIC_NDIGITS(value);
3202+
result = 0;
3203+
for (i = 0; i <= weight; i++)
3204+
{
3205+
result *= NBASE;
3206+
if (i < ndigits)
3207+
result += digits[i];
3208+
}
3209+
3210+
if (NUMERIC_SIGN(value) == NUMERIC_NEG)
3211+
result = -result;
3212+
3213+
*out = result;
3214+
3215+
return true;
3216+
}
3217+
3218+
Numeric
3219+
small_to_numeric(uint32 value)
3220+
{
3221+
NumericDigit digits[3];
3222+
Numeric result;
3223+
Size len;
3224+
int weight;
3225+
bool sign;
3226+
3227+
sign = (int32) value < 0;
3228+
if (sign)
3229+
value = -value;
3230+
3231+
digits[0] = (value / NBASE / NBASE) % NBASE;
3232+
digits[1] = (value / NBASE) % NBASE;
3233+
digits[2] = value % NBASE;
3234+
3235+
weight = digits[0] ? 2 : digits[1] ? 1 : 0;
3236+
3237+
len = NUMERIC_HDRSZ_SHORT + (weight + 1) * sizeof(NumericDigit);
3238+
result = (Numeric) palloc(len);
3239+
SET_VARSIZE(result, len);
3240+
result->choice.n_short.n_header =
3241+
(sign ? NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK : NUMERIC_SHORT) |
3242+
(weight & NUMERIC_SHORT_WEIGHT_MASK);
3243+
3244+
memcpy(NUMERIC_DIGITS(result), digits + (2 - weight),
3245+
(weight + 1) * sizeof(NumericDigit));
3246+
3247+
return result;
3248+
}
3249+
3250+
31783251
/* ----------------------------------------------------------------------
31793252
*
31803253
* Aggregate functions

src/include/utils/numeric.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,7 @@ extern bool numeric_is_nan(Numeric num);
6060
int32 numeric_maximum_size(int32 typmod);
6161
extern char *numeric_out_sci(Numeric num, int scale);
6262
extern char *numeric_normalize(Numeric num);
63+
extern bool numeric_get_small(Numeric value, uint32 *out);
64+
extern Numeric small_to_numeric(uint32 value);
6365

6466
#endif /* _PG_NUMERIC_H_ */

0 commit comments

Comments
 (0)