Repository: risingwavelabs/risingwave
File: src/expr/impl/src/scalar/arithmetic_op.rs (Rust)

Code before:
/// SELECT gamma('3'::float8);
/// ----
/// 2
///
/// query R
/// SELECT gamma('4'::float8);
/// ----
/// 6
///
/// query R
/// SELECT gamma('5'::float8);
/// ----
/// 24
///
/// statement error overflow
/// SELECT gamma('-1'::float8);
///
/// statement error underflow
/// SELECT gamma('-1000.5'::float8);
///
/// statement error overflow
/// SELECT gamma('0'::float8);
///
/// statement error overflow
/// SELECT gamma('1000'::float8);
/// ```
#[function("gamma(float8) -> float8")]
pub fn gamma_f64(input: F64) -> Result<F64> {
    let mut result = input;
    if input.is_nan() {
        return Ok(result);
    } else if input.is_infinite() {
        if input.is_negative() {
            return Err(ExprError::NumericOverflow);
        }
    } else {
        result = input.gamma();
        if result.is_nan() || result.is_infinite() {
            if !result.is_zero() {
                return Err(ExprError::NumericOverflow);
            } else {
                return Err(ExprError::NumericUnderflow);
            }
        } else if result.is_zero() {
            return Err(ExprError::NumericUnderflow);
        }
    }
    Ok(result)
}

/// ```slt

Review comment (suggestion):
The inline SLT-formatted tests suggest these should be proper e2e tests, but no corresponding test file exists in the e2e_test directory. According to the project guidelines, the preferred testing format is SQLLogicTest (SLT) and tests should be located in ./e2e_test folder. Consider creating an e2e test file for the gamma and lgamma functions.

Code after:
mod tests {
    use std::str::FromStr;

    use num_traits::Float;
    use risingwave_common::types::test_utils::IntervalTestExt;
    use risingwave_common::types::{F32, Int256, Int256Ref, Scalar};

    use super::*;

    #[test]
    fn test() {
        assert_eq!(
            general_add::<_, _, Decimal>(Decimal::from_str("1").unwrap(), 1i32).unwrap(),
            Decimal::from_str("2").unwrap()
        );
    }

    #[test]
    fn test_arithmetic() {
        assert_eq!(
            general_add::<Decimal, i32, Decimal>(dec("1.0"), 1).unwrap(),
            dec("2.0")
        );
        assert_eq!(
            general_sub::<Decimal, i32, Decimal>(dec("1.0"), 2).unwrap(),
            dec("-1.0")
        );
        assert_eq!(
            general_mul::<Decimal, i32, Decimal>(dec("1.0"), 2).unwrap(),
            dec("2.0")
        );
        assert_eq!(
            general_div::<Decimal, i32, Decimal>(dec("2.0"), 2).unwrap(),
            dec("1.0")
        );
        assert_eq!(
            general_mod::<Decimal, i32, Decimal>(dec("2.0"), 2).unwrap(),
            dec("0")
        );
        assert_eq!(general_neg::<Decimal>(dec("1.0")).unwrap(), dec("-1.0"));
        assert_eq!(general_add::<i16, i32, i32>(1i16, 1i32).unwrap(), 2i32);
        assert_eq!(general_sub::<i16, i32, i32>(1i16, 1i32).unwrap(), 0i32);
        assert_eq!(general_mul::<i16, i32, i32>(1i16, 1i32).unwrap(), 1i32);
        assert_eq!(general_div::<i16, i32, i32>(1i16, 1i32).unwrap(), 1i32);
        assert_eq!(general_mod::<i16, i32, i32>(1i16, 1i32).unwrap(), 0i32);
        assert_eq!(general_neg::<i16>(1i16).unwrap(), -1i16);

        assert!(
            general_add::<i32, F32, F64>(-1i32, 1f32.into())
                .unwrap()
                .is_zero()