class ArithmeticOperatorsFactory {

    private static final BinaryOperator<Double> ADD_DOUBLE_FUNCTION = Double::sum;
    private static final BinaryOperator<Integer> ADD_INTEGER_FUNCTION = Integer::sum;
    private static final BinaryOperator<Long> ADD_LONG_FUNCTION = Long::sum;
    private static final BinaryOperator<Float> ADD_FLOAT_FUNCTION = Float::sum;

    private static final BinaryOperator<Double> SUB_DOUBLE_FUNCTION = (arg0, arg1) -> arg0 - arg1;
    private static final BinaryOperator<Integer> SUB_INTEGER_FUNCTION = (arg0, arg1) -> arg0 - arg1;
    private static final BinaryOperator<Long> SUB_LONG_FUNCTION = (arg0, arg1) -> arg0 - arg1;
    private static final BinaryOperator<Float> SUB_FLOAT_FUNCTION = (arg0, arg1) -> arg0 - arg1;

    static BiFunction getAddFunction(DataType<?> fstArgDataType, DataType<?> sndArgDataType) {
        switch (fstArgDataType.id()) {
            case LongType.ID:
            case TimestampType.ID_WITH_TZ:
            case TimestampType.ID_WITHOUT_TZ:
                if (IntervalType.ID == sndArgDataType.id()) {
                    var signature = IntervalTimestampArithmeticScalar.signatureFor(
                        fstArgDataType,
                        ArithmeticFunctions.Names.ADD
                    );
                    return new IntervalTimestampArithmeticScalar(
                        "+",
                        signature,
                        BoundSignature.sameAsUnbound(signature)
                    );
                }
                return ADD_LONG_FUNCTION;
            case DoubleType.ID:
                return ADD_DOUBLE_FUNCTION;
            case FloatType.ID:
                return ADD_FLOAT_FUNCTION;
            case ByteType.ID:
            case ShortType.ID:
            case IntegerType.ID:
                return ADD_INTEGER_FUNCTION;
            default:
                throw new UnsupportedOperationException(
                    "Cannot create add function for data type " + fstArgDataType.getName());
        }
    }

    static BiFunction getSubtractFunction(DataType<?> fstArgDataType, DataType<?> sndArgDataType) {<FILL_FUNCTION_BODY>}
}

        switch (fstArgDataType.id()) {
            case LongType.ID:
            case TimestampType.ID_WITH_TZ:
            case TimestampType.ID_WITHOUT_TZ:
                if (IntervalType.ID == sndArgDataType.id()) {
                    var signature = IntervalTimestampArithmeticScalar.signatureFor(
                        fstArgDataType,
                        ArithmeticFunctions.Names.SUBTRACT
                    );
                    return new IntervalTimestampArithmeticScalar(
                        "-",
                        signature,
                        BoundSignature.sameAsUnbound(signature)
                    );
                }
                return SUB_LONG_FUNCTION;
            case DoubleType.ID:
                return SUB_DOUBLE_FUNCTION;
            case FloatType.ID:
                return SUB_FLOAT_FUNCTION;
            case ByteType.ID:
            case ShortType.ID:
            case IntegerType.ID:
                return SUB_INTEGER_FUNCTION;
            default:
                throw new UnsupportedOperationException(
                    "Cannot create subtract function for data type " + fstArgDataType.getName());
        }
    
<no_super_class>