@ScalarFunction
    @SqlType(StandardTypes.BIGINT)
    public static long sign(@SqlType(StandardTypes.BIGINT) long num)
    {
        return (long) Math.signum(num);
    }
@Test
    public void testSign()
    {
        DecimalType expectedDecimalReturnType = createDecimalType(1, 0);

        //retains type for NULL values
        assertFunction("sign(CAST(NULL as TINYINT))", TINYINT, null);
        assertFunction("sign(CAST(NULL as SMALLINT))", SMALLINT, null);
        assertFunction("sign(CAST(NULL as INTEGER))", INTEGER, null);
        assertFunction("sign(CAST(NULL as BIGINT))", BIGINT, null);
        assertFunction("sign(CAST(NULL as DOUBLE))", DOUBLE, null);
        assertFunction("sign(CAST(NULL as DECIMAL(2,1)))", expectedDecimalReturnType, null);
        assertFunction("sign(CAST(NULL as DECIMAL(38,0)))", expectedDecimalReturnType, null);

        //tinyint
        for (int intValue : intLefts) {
            Float signum = Math.signum(intValue);
            assertFunction("sign(TINYINT '" + intValue + "')", TINYINT, signum.byteValue());
        }

        //smallint
        for (int intValue : intLefts) {
            Float signum = Math.signum(intValue);
            assertFunction("sign(SMALLINT '" + intValue + "')", SMALLINT, signum.shortValue());
        }

        //integer
        for (int intValue : intLefts) {
            Float signum = Math.signum(intValue);
            assertFunction("sign(INTEGER '" + intValue + "')", INTEGER, signum.intValue());
        }

        //bigint
        for (int intValue : intLefts) {
            Float signum = Math.signum(intValue);
            assertFunction("sign(BIGINT '" + intValue + "')", BIGINT, signum.longValue());
        }

        //double and float
        for (double doubleValue : DOUBLE_VALUES) {
            assertFunction("sign(DOUBLE '" + doubleValue + "')", DOUBLE, Math.signum(doubleValue));
            assertFunction("sign(REAL '" + (float) doubleValue + "')", REAL, Math.signum(((float) doubleValue)));
        }

        //returns NaN for NaN input
        assertFunction("sign(DOUBLE 'NaN')", DOUBLE, Double.NaN);

        //returns proper sign for +/-Infinity input
        assertFunction("sign(DOUBLE '+Infinity')", DOUBLE, 1.0);
        assertFunction("sign(DOUBLE '-Infinity')", DOUBLE, -1.0);

        //short decimal
        assertFunction("sign(DECIMAL '0')", expectedDecimalReturnType, SqlDecimal.of("0"));
        assertFunction("sign(DECIMAL '123')", expectedDecimalReturnType, SqlDecimal.of("1"));
        assertFunction("sign(DECIMAL '-123')", expectedDecimalReturnType, SqlDecimal.of("-1"));
        assertFunction("sign(DECIMAL '123.000000000000000')", expectedDecimalReturnType, SqlDecimal.of("1"));
        assertFunction("sign(DECIMAL '-123.000000000000000')", expectedDecimalReturnType, SqlDecimal.of("-1"));

        //long decimal
        assertFunction("sign(DECIMAL '0.000000000000000000')", expectedDecimalReturnType, SqlDecimal.of("0"));
        assertFunction("sign(DECIMAL '1230.000000000000000')", expectedDecimalReturnType, SqlDecimal.of("1"));
        assertFunction("sign(DECIMAL '-1230.000000000000000')", expectedDecimalReturnType, SqlDecimal.of("-1"));
    }