diff options
author | Dean Rasheed <dean.a.rasheed@gmail.com> | 2025-03-26 09:35:53 +0000 |
---|---|---|
committer | Dean Rasheed <dean.a.rasheed@gmail.com> | 2025-03-26 09:35:53 +0000 |
commit | a3b6dfd410699a19209be3cb3c7a74e5ff1da830 (patch) | |
tree | 7e98bdbab647c59a2091eaa170d49df0221a2489 /src/backend/utils/adt/float.c | |
parent | 7c82b4f711877b175142bb2b2a6e2c2ee2429441 (diff) | |
download | postgresql-a3b6dfd410699a19209be3cb3c7a74e5ff1da830.tar.gz postgresql-a3b6dfd410699a19209be3cb3c7a74e5ff1da830.zip |
Add support for gamma() and lgamma() functions.
These are useful general-purpose math functions which are included in
POSIX and C99, and are commonly included in other math libraries, so
expose them as SQL-callable functions.
Author: Dean Rasheed <dean.a.rasheed@gmail.com>
Reviewed-by: Stepan Neretin <sncfmgg@gmail.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Dmitry Koval <d.koval@postgrespro.ru>
Reviewed-by: Alexandra Wang <alexandra.wang.oss@gmail.com>
Discussion: https://postgr.es/m/CAEZATCXpGyfjXCirFk9au+FvM0y2Ah+2-0WSJx7MO368ysNUPA@mail.gmail.com
Diffstat (limited to 'src/backend/utils/adt/float.c')
-rw-r--r-- | src/backend/utils/adt/float.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 2bc31eabf29..6d20ae07ae7 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -2786,6 +2786,94 @@ derfc(PG_FUNCTION_ARGS) } +/* ========== GAMMA FUNCTIONS ========== */ + + +/* + * dgamma - returns the gamma function of arg1 + */ +Datum +dgamma(PG_FUNCTION_ARGS) +{ + float8 arg1 = PG_GETARG_FLOAT8(0); + float8 result; + + /* + * Handle NaN and Inf cases explicitly. This simplifies the overflow + * checks on platforms that do not set errno. + */ + if (isnan(arg1)) + result = arg1; + else if (isinf(arg1)) + { + /* Per POSIX, an input of -Inf causes a domain error */ + if (arg1 < 0) + { + float_overflow_error(); + result = get_float8_nan(); /* keep compiler quiet */ + } + else + result = arg1; + } + else + { + /* + * Note: the POSIX/C99 gamma function is called "tgamma", not "gamma". + * + * On some platforms, tgamma() will not set errno but just return Inf, + * NaN, or zero to report overflow/underflow; therefore, test those + * cases explicitly (note that, like the exponential function, the + * gamma function has no zeros). + */ + errno = 0; + result = tgamma(arg1); + + if (errno != 0 || isinf(result) || isnan(result)) + { + if (result != 0.0) + float_overflow_error(); + else + float_underflow_error(); + } + else if (result == 0.0) + float_underflow_error(); + } + + PG_RETURN_FLOAT8(result); +} + + +/* + * dlgamma - natural logarithm of absolute value of gamma of arg1 + */ +Datum +dlgamma(PG_FUNCTION_ARGS) +{ + float8 arg1 = PG_GETARG_FLOAT8(0); + float8 result; + + /* + * Note: lgamma may not be thread-safe because it may write to a global + * variable signgam, which may not be thread-local. However, this doesn't + * matter to us, since we don't use signgam. + */ + errno = 0; + result = lgamma(arg1); + + /* + * If an ERANGE error occurs, it means there was an overflow or a pole + * error (which happens for zero and negative integer inputs). + * + * On some platforms, lgamma() will not set errno but just return infinity + * to report overflow, but it should never underflow. + */ + if (errno == ERANGE || (isinf(result) && !isinf(arg1))) + float_overflow_error(); + + PG_RETURN_FLOAT8(result); +} + + /* * ========================= |