-
Notifications
You must be signed in to change notification settings - Fork 252
feat: Add support for abs
#2689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| // https://github.com/apache/datafusion-comet/issues/666 | ||
| ignore("abs") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I implemented new tests using the fuzz data generator
|
@hsiang-c could you review? |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2689 +/- ##
============================================
+ Coverage 56.12% 59.32% +3.20%
- Complexity 976 1448 +472
============================================
Files 119 147 +28
Lines 11743 13816 +2073
Branches 2251 2370 +119
============================================
+ Hits 6591 8197 +1606
- Misses 4012 4393 +381
- Partials 1140 1226 +86 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| | ScalarValue::UInt32(_) | ||
| | ScalarValue::UInt64(_) => Ok(args[0].clone()), | ||
| ScalarValue::Int8(a) => match a { | ||
| None => Ok(args[0].clone()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks!
| #[test] | ||
| fn test_abs_i8_scalar() { | ||
| with_fail_on_error(|fail_on_error| { | ||
| let args = ColumnarValue::Scalar(ScalarValue::Int8(Some(i8::MIN))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need a scalar test for the None case.
| case _: NumericType => | ||
| Compatible() | ||
| case _ => | ||
| // Spark supports NumericType, DayTimeIntervalType, and YearMonthIntervalType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| StructField("c1", DataTypes.ShortType, nullable = true), | ||
| StructField("c2", DataTypes.IntegerType, nullable = true), | ||
| StructField("c3", DataTypes.LongType, nullable = true), | ||
| StructField("c4", DataTypes.FloatType, nullable = true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are NaNs included in the test data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the fuzz generator generates edge cases like NaN, Infinity, -0.0 (optionally).
hsiang-c
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks Andy.
| f.dataType == DataTypes.FloatType || f.dataType == DataTypes.DoubleType)) { | ||
| val col = field.name | ||
| checkSparkAnswerAndOperator( | ||
| s"SELECT $col, abs($col) FROM tbl WHERE signum($col) < 0 ORDER BY $col") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the value of $col is -0.0 (a negative zero) then signum($col) would return 0.
Just checking whether this is the intended behavior because the test is about negative zero specifically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @martin-g. I updated the test. Results:
+----+-------+
|c4 |abs(c4)|
+----+-------+
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
|-0.0|0.0 |
+----+-------+
| Ok(()) | ||
| } | ||
| Err(e) => { | ||
| if fail_on_error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that it would overflow for unsigned integers ?
IMO it should always panic here, i.e. leave only the else clause body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated, thanks
|
|
||
| fn with_fail_on_error<F: Fn(bool) -> Result<()>>(test_fn: F) { | ||
| for fail_on_error in [true, false] { | ||
| let _ = test_fn(fail_on_error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would ignore the returned Result.
| let _ = test_fn(fail_on_error); | |
| let _ = test_fn(fail_on_error)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. I couldn't add ? but added .expect
| false | ||
| }; | ||
|
|
||
| match &args[0] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no check that the function is called with at least one argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
| }, | ||
| }, | ||
| ScalarValue::Int16(a) => match a { | ||
| None => Ok(args[0].clone()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: The code for handling Int16/32/64 is very similar to Int8.
It could be extracted to a declarative macro.
| #[test] | ||
| fn test_abs_f32_array() { | ||
| with_fail_on_error(|fail_on_error| { | ||
| let input = Float32Array::from(vec![Some(-1f32), Some(f32::MIN), Some(f32::MAX), None]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we also have NaN, Infinities?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
Co-authored-by: Oleks V <comphead@users.noreply.github.com>
Co-authored-by: Oleks V <comphead@users.noreply.github.com>
Co-authored-by: Oleks V <comphead@users.noreply.github.com>
| } | ||
|
|
||
| #[test] | ||
| fn test_abs_f32_array() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have this edge case
scala> spark.sql("select abs(-0.0), abs(0.0)").show(false)
+--------+--------+
|abs(0.0)|abs(0.0)|
+--------+--------+
|0.0 |0.0 |
+--------+--------+
Because Rust
fn main() {
println!("{}", -0f32.abs());
}
-0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added. We also have specific Spark test for negative zero case.
comphead
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @andygrove and @hsiang-c for supporting abs
Which issue does this PR close?
Closes #666
Rationale for this change
This PR is based on #2595
What changes are included in this PR?
The differences since #2595 are:
DayTimeIntervalTypeandYearMonthIntervalTypeHow are these changes tested?