@@ -2786,6 +2786,93 @@ derfc(PG_FUNCTION_ARGS)
27862786}
27872787
27882788
2789+ /* ========== GAMMA FUNCTIONS ========== */
2790+
2791+
2792+ /*
2793+ * dgamma - returns the gamma function of arg1
2794+ */
2795+ Datum
2796+ dgamma (PG_FUNCTION_ARGS )
2797+ {
2798+ float8 arg1 = PG_GETARG_FLOAT8 (0 );
2799+ float8 result ;
2800+
2801+ /*
2802+ * Handle NaN and Inf cases explicitly. This simplifies the overflow
2803+ * checks on platforms that do not set errno.
2804+ */
2805+ if (isnan (arg1 ))
2806+ result = arg1 ;
2807+ else if (isinf (arg1 ))
2808+ {
2809+ /* Per POSIX, an input of -Inf causes a domain error */
2810+ if (arg1 < 0 )
2811+ {
2812+ float_overflow_error ();
2813+ result = get_float8_nan (); /* keep compiler quiet */
2814+ }
2815+ else
2816+ result = arg1 ;
2817+ }
2818+ else
2819+ {
2820+ /*
2821+ * Note: the POSIX/C99 gamma function is called "tgamma", not "gamma".
2822+ *
2823+ * On some platforms, tgamma() will not set errno but just return Inf,
2824+ * NaN, or zero to report overflow/underflow; therefore, test those
2825+ * cases explicitly (note that, like the exponential function, the
2826+ * gamma function has no zeros).
2827+ */
2828+ errno = 0 ;
2829+ result = tgamma (arg1 );
2830+
2831+ if (errno != 0 || isinf (result ) || isnan (result ))
2832+ {
2833+ if (result != 0.0 )
2834+ float_overflow_error ();
2835+ else
2836+ float_underflow_error ();
2837+ }
2838+ else if (result == 0.0 )
2839+ float_underflow_error ();
2840+ }
2841+
2842+ PG_RETURN_FLOAT8 (result );
2843+ }
2844+
2845+
2846+ /*
2847+ * dlgamma - natural logarithm of absolute value of gamma of arg1
2848+ */
2849+ Datum
2850+ dlgamma (PG_FUNCTION_ARGS )
2851+ {
2852+ float8 arg1 = PG_GETARG_FLOAT8 (0 );
2853+ float8 result ;
2854+
2855+ /*
2856+ * Note: lgamma may not be thread-safe because it may write to a global
2857+ * variable signgam, which may not be thread-local. However, this doesn't
2858+ * matter to us, since we don't use signgam.
2859+ */
2860+ errno = 0 ;
2861+ result = lgamma (arg1 );
2862+
2863+ /*
2864+ * If an ERANGE error occurs, it means there is an overflow.
2865+ *
2866+ * On some platforms, lgamma() will not set errno but just return infinity
2867+ * to report overflow, but it should never underflow.
2868+ */
2869+ if (errno == ERANGE || (isinf (result ) && !isinf (arg1 )))
2870+ float_overflow_error ();
2871+
2872+ PG_RETURN_FLOAT8 (result );
2873+ }
2874+
2875+
27892876
27902877/*
27912878 * =========================
0 commit comments