RESOLVED FIXED 130947
[iOS] Fix remaining misuses of abs() and fabsf()
https://bugs.webkit.org/show_bug.cgi?id=130947
Summary [iOS] Fix remaining misuses of abs() and fabsf()
David Kilzer (:ddkilzer)
Reported 2014-03-30 13:57:30 PDT
Compiling WebKit for iOS with trunk clang shows a few more misuses of abs() and fabsf(): WebCore/platform/ios/wak/WKView.mm:251:30: error: using integer absolute value function 'abs' when argument is of floating point type [-Werror,-Wabsolute-value] || (abs(origMarginsTotal) == 1)) { ^ WebCore/platform/ios/wak/WKView.mm:251:30: note: use function 'fabs' instead || (abs(origMarginsTotal) == 1)) { ^~~ fabs WebCore/platform/ios/ScrollAnimatorIOS.mm:125:45: error: using floating point absolute value function 'fabsf' when argument is of integer type [-Werror,-Wabsolute-value] float dragAngle = atanf(fabsf(deltaFromStart.height()) / fabsf(deltaFromStart.width())); ^ WebCore/platform/ios/ScrollAnimatorIOS.mm:125:45: note: use function 'abs' instead float dragAngle = atanf(fabsf(deltaFromStart.height()) / fabsf(deltaFromStart.width())); ^~~~~ abs WebCore/platform/ios/ScrollAnimatorIOS.mm:125:78: error: using floating point absolute value function 'fabsf' when argument is of integer type [-Werror,-Wabsolute-value] float dragAngle = atanf(fabsf(deltaFromStart.height()) / fabsf(deltaFromStart.width())); ^ WebCore/platform/ios/ScrollAnimatorIOS.mm:125:78: note: use function 'abs' instead float dragAngle = atanf(fabsf(deltaFromStart.height()) / fabsf(deltaFromStart.width())); ^~~~~ abs WebCore/platform/ios/ScrollAnimatorIOS.mm:143:114: error: using floating point absolute value function 'fabsf' when argument is of integer type [-Werror,-Wabsolute-value] handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollLeft : ScrollRight, ScrollByPixel, fabsf(delta)); ^ WebCore/platform/ios/ScrollAnimatorIOS.mm:143:114: note: use function 'abs' instead handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollLeft : ScrollRight, ScrollByPixel, fabsf(delta)); ^~~~~ abs WebCore/platform/ios/ScrollAnimatorIOS.mm:149:111: error: using floating point absolute value function 'fabsf' when argument is of integer type [-Werror,-Wabsolute-value] handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollUp : ScrollDown, ScrollByPixel, fabsf(delta)); ^ WebCore/platform/ios/ScrollAnimatorIOS.mm:149:111: note: use function 'abs' instead handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollUp : ScrollDown, ScrollByPixel, fabsf(delta)); ^~~~~ abs
Attachments
Patch v1 (22.12 KB, patch)
2014-03-30 14:09 PDT, David Kilzer (:ddkilzer)
no flags
Archive of layout-test-results from webkit-ews-08 for mac-mountainlion (487.60 KB, application/zip)
2014-03-30 17:12 PDT, Build Bot
no flags
Patch v2 (19.26 KB, patch)
2014-09-16 17:22 PDT, David Kilzer (:ddkilzer)
no flags
Patch (4.02 KB, patch)
2014-10-06 17:49 PDT, Andy Estes
simon.fraser: review+
David Kilzer (:ddkilzer)
Comment 1 2014-03-30 14:09:38 PDT
Created attachment 228131 [details] Patch v1
David Kilzer (:ddkilzer)
Comment 2 2014-03-30 14:11:26 PDT
(In reply to comment #1) > Created an attachment (id=228131) [details] > Patch v1 Obviously, if this lands with narrowPrecisionTo<>() methods, I would replace functions in Source/WebCore/platform/FloatConversion.h with NumericConversion.h.
Brent Fulgham
Comment 3 2014-03-30 16:19:35 PDT
Comment on attachment 228131 [details] Patch v1 View in context: https://bugs.webkit.org/attachment.cgi?id=228131&action=review A couple of minor questions, but looks good overall. R=me. > Source/WTF/wtf/MathExtras.h:395 > +template<> inline double abs(const double& value) { return ::fabs(value); } Doesn't the existing STL math library (<cmath>, or maybe <cfloat>) provide template methods for these already? > Source/WTF/wtf/NumericConversion.h:165 > +inline float narrowPrecisionTo(const float& value) { return value; } Is there any advantage to range checks like you did for double->int here? IIRC, floats have about an order of magnitude smaller range of values they can hold (aside from the obvious precision differences). > Source/WTF/wtf/NumericConversion.h:168 > +inline float narrowPrecisionTo(const double& value) { return static_cast<float>(value); } Obviously I meant the previous comment for this line!
Build Bot
Comment 4 2014-03-30 17:11:56 PDT
Comment on attachment 228131 [details] Patch v1 Attachment 228131 [details] did not pass mac-ews (mac): Output: http://webkit-queues.appspot.com/results/4882791653179392 New failing tests: compositing/columns/composited-rl-paginated-repaint.html
Build Bot
Comment 5 2014-03-30 17:12:02 PDT
Created attachment 228134 [details] Archive of layout-test-results from webkit-ews-08 for mac-mountainlion The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: webkit-ews-08 Port: mac-mountainlion Platform: Mac OS X 10.8.5
David Kilzer (:ddkilzer)
Comment 6 2014-03-30 17:41:41 PDT
Comment on attachment 228131 [details] Patch v1 Ahh, std::abs() is overloaded to work as expected for floating point types from <cmath>. I'll use that instead of defining my own macros.
David Kilzer (:ddkilzer)
Comment 7 2014-03-30 18:02:14 PDT
(In reply to comment #3) > (From update of attachment 228131 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=228131&action=review > > A couple of minor questions, but looks good overall. R=me. Thanks! I want Darin to weigh on this as well because he mentioned he's interested in this topic on Friday. > > Source/WTF/wtf/MathExtras.h:395 > > +template<> inline double abs(const double& value) { return ::fabs(value); } > > Doesn't the existing STL math library (<cmath>, or maybe <cfloat>) provide template methods for these already? Yes! std::abs() provides overloaded arguments for floating point types, so I'll use that instead. > Source/WTF/wtf/NumericConversion.h:168 > +inline float narrowPrecisionTo(const double& value) { return static_cast<float>(value); } > > Is there any advantage to range checks like you did for double->int here? IIRC, floats have about an order of magnitude smaller range of values they can hold (aside from the obvious precision differences). I suppose it depends on where you care about the loss of precision happening. In larger numbers, the loss of precision occurs to the left of the decimal place. In smaller numbers, it's to the right of the decimal place. I'm not sure what a good rule of thumb here is, though, so I did the same thing that Source/WebCore/platform/FloatPrecision.h does now.
Darin Adler
Comment 8 2014-03-31 09:07:46 PDT
Comment on attachment 228131 [details] Patch v1 View in context: https://bugs.webkit.org/attachment.cgi?id=228131&action=review > Source/WTF/wtf/NumericConversion.h:36 > +T narrowPrecisionTo(const U& value); I don’t think we need const U& here. Just U should be fine. I see no advantage to const int&, etc. > Source/WTF/wtf/NumericConversion.h:39 > +T to(const U& value); Ditto. > Source/WTF/wtf/NumericConversion.h:96 > +template<> > +inline int narrowPrecisionTo(const float& value) > +{ > + ASSERT(!isinf(value)); > + ASSERT(!isnan(value)); > + ASSERT(static_cast<double>(value) >= static_cast<double>(std::numeric_limits<int>::min())); > + ASSERT(static_cast<double>(value) <= static_cast<double>(std::numeric_limits<int>::max())); > + return static_cast<int>(value); > +} I don’t like the name here. This doesn’t narrow precision, it truncates to an integer, which doesn’t seem like the same thing. Further, besides truncation, there are other operations one could do to convert a float to an int, such as rounding. > Source/WTF/wtf/NumericConversion.h:99 > +inline int narrowPrecisionTo(const double& value) Ditto. > Source/WTF/wtf/NumericConversion.h:115 > + ASSERT(static_cast<double>(result) == static_cast<double>(value)); How important is this assertion? It seems fine to convert an int to a float in cases where we lose a small of amount precision, in most cases. Asserting we lost no precision seems overzealous. The name to<int> doesn’t justify this strictness to me. If we really need such functions, I think they should have different names. > Source/WTF/wtf/NumericConversion.h:123 > + ASSERT(static_cast<long>(result) == value); Ditto. > Source/WTF/wtf/NumericConversion.h:131 > + ASSERT(static_cast<long long>(result) == value); Ditto. > Source/WTF/wtf/NumericConversion.h:141 > + ASSERT(static_cast<double>(result) == static_cast<double>(value)); Ditto. > Source/WTF/wtf/NumericConversion.h:149 > + ASSERT(static_cast<unsigned long>(result) == value); Ditto. > Source/WTF/wtf/NumericConversion.h:157 > + ASSERT(static_cast<unsigned long long>(result) == value); Ditto. > Source/WTF/wtf/NumericConversion.h:180 > + ASSERT(static_cast<long>(result) == value); Same comment for double. > Source/WTF/wtf/NumericConversion.h:188 > + ASSERT(static_cast<long long>(result) == value); Ditto. > Source/WTF/wtf/NumericConversion.h:201 > + ASSERT(static_cast<unsigned long>(result) == value); Ditto. > Source/WTF/wtf/NumericConversion.h:209 > + ASSERT(static_cast<unsigned long long>(result) == value); Ditto. > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:126 > + float dragAngle = atanf(to<float>(abs(deltaFromStart.height())) / to<float>(abs(deltaFromStart.width()))); Does not seem like we want to do range checking here. We don’t care if the height or width is so large it doesn’t fit with full precision into a float. Approximation is fine. > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:144 > + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollLeft : ScrollRight, ScrollByPixel, to<float>(abs(delta))); Does not seem like we want to do range checking here. Do we really need to check if the delta is so large that it won’t fit with full precision into a float? > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:150 > + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollUp : ScrollDown, ScrollByPixel, to<float>(abs(delta))); Ditto. > Source/WebCore/platform/ios/wak/WKView.mm:253 > + || (narrowPrecisionTo<int>(abs<CGFloat>(origMarginsTotal)) == 1)) { I don’t understand why abs<CGFloat> is needed here. Wouldn’t std::abs do the right thing without specifying an explicit type? Any why are we truncating to integer here. Is that really what we want rather than, say, rounding?
Csaba Osztrogonác
Comment 9 2014-06-04 03:25:18 PDT
Comment on attachment 228131 [details] Patch v1 Cleared Brent Fulgham's review+ from obsolete attachment 228131 [details] so that this bug does not appear in http://webkit.org/pending-commit.
David Kilzer (:ddkilzer)
Comment 10 2014-09-15 13:32:41 PDT
Comment on attachment 228131 [details] Patch v1 View in context: https://bugs.webkit.org/attachment.cgi?id=228131&action=review >> Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:126 >> + float dragAngle = atanf(to<float>(abs(deltaFromStart.height())) / to<float>(abs(deltaFromStart.width()))); > > Does not seem like we want to do range checking here. We don’t care if the height or width is so large it doesn’t fit with full precision into a float. Approximation is fine. Range checks will be removed from to<float>() in the next patch. After talking with Simon, we do want to perform floating point arithmetic here, so as a result I'm not going to change the above line in the next patch. >> Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:144 >> + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollLeft : ScrollRight, ScrollByPixel, to<float>(abs(delta))); > > Does not seem like we want to do range checking here. Do we really need to check if the delta is so large that it won’t fit with full precision into a float? Range checks will be removed from to<float>() in the next patch. After talking with Simon, we do want to perform floating point arithmetic here, so as a result I'm not going to change the above line in the next patch. >> Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:150 >> + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollUp : ScrollDown, ScrollByPixel, to<float>(abs(delta))); > > Ditto. Ditto. >> Source/WebCore/platform/ios/wak/WKView.mm:253 >> + || (narrowPrecisionTo<int>(abs<CGFloat>(origMarginsTotal)) == 1)) { > > I don’t understand why abs<CGFloat> is needed here. Wouldn’t std::abs do the right thing without specifying an explicit type? > > Any why are we truncating to integer here. Is that really what we want rather than, say, rounding? I will switch to std::abs in the next patch. In looking at the code with Simon, we suspect that back when this code was written (in August 2005), the height values would always be integral (even though they were stored as floating point values). We also briefly searched to see if this code is even still used, but we couldn't definitely rule it out, so I'd prefer to keep the original behavior here for this patch.
David Kilzer (:ddkilzer)
Comment 11 2014-09-16 17:22:20 PDT
Created attachment 238225 [details] Patch v2
WebKit Commit Bot
Comment 12 2014-09-16 17:23:33 PDT
Attachment 238225 [details] did not pass style-queue: ERROR: Source/WebCore/platform/ios/wak/WKView.mm:252: Weird number of spaces at line-start. Are you using a 4-space indent? [whitespace/indent] [3] Total errors found: 1 in 9 files If any of these errors are false positives, please file a bug against check-webkit-style.
David Kilzer (:ddkilzer)
Comment 13 2014-09-16 17:26:17 PDT
(In reply to comment #11) > Created an attachment (id=238225) [details] > Patch v2 Changes since Patch v1: - Replaced "const U&" with "U". - Renamed narrowPrecisionTo<>() to truncateTo<>(). - Removed ASSERT()s where Darin thought they were unnecessary. - Removed abs<CGFloat>() and used std::abs() instead in WKView.mm. (Did not change code otherwise. Risk/reward didn't see correct for this legacy code, and it's out of scope for this change.)
Darin Adler
Comment 14 2014-09-18 09:54:53 PDT
Comment on attachment 238225 [details] Patch v2 View in context: https://bugs.webkit.org/attachment.cgi?id=238225&action=review > Source/WTF/ChangeLog:10 > + - to<T>(U) converts type U to type T with runtime bounds checks > + in Debug builds for integral types. Since by runtime bounds checks you mean assertions, I am a little puzzled. We would only assert something that’s guaranteed. Since there are no uses of to<int> it’s hard for me to argue one way or another whether there is a guarantee, but this doesn’t sound great to me. > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:132 > + float dragAngle = atanf(to<float>(abs(deltaFromStart.height())) / to<float>(abs(deltaFromStart.width()))); I don’t see any benefit to using to<float> here instead of static_cast<float>. Is there a benefit I am missing? > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:150 > + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollLeft : ScrollRight, ScrollByPixel, to<float>(abs(delta))); Ditto. > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:156 > + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollUp : ScrollDown, ScrollByPixel, to<float>(abs(delta))); Ditto. > Source/WebCore/platform/ios/wak/WKView.mm:252 > else if (origMarginsTotal == 0.0f > - || (abs(origMarginsTotal) == 1)) { > + || (truncateTo<int>(std::abs(origMarginsTotal)) == 1)) { I don’t think that truncating is what we want to do here. Lets instead write out the code in a way that makes it obvious what it actually does. Here's what the code does: if (origMarginsTotal == 0 || (origMarginsTotal > -2 && origMarginsTotal <= -1) || (origMarginsTotal >= 1 && origMarginsTotal < 2)) I think this rule is wrong, and rewriting it to use std::abs and truncateTo just makes it seem like it makes sense, but obscures what is actually happening. Writing the way the way I suggest above to make it clear what it really does might make someone consider fixing it. One step in the right direction would be to get rid of the strange special case for the range (0,1). Like this: if (origMarginsTotal > -2 && origMarginsTotal < 2) That seems like it might be a helpful change, although it is a change in behavior.
David Kilzer (:ddkilzer)
Comment 15 2014-10-03 11:12:47 PDT
(In reply to comment #14) > (From update of attachment 238225 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=238225&action=review > > > Source/WTF/ChangeLog:10 > > + - to<T>(U) converts type U to type T with runtime bounds checks > > + in Debug builds for integral types. > > Since by runtime bounds checks you mean assertions, I am a little puzzled. We would only assert something that’s guaranteed. Since there are no uses of to<int> it’s hard for me to argue one way or another whether there is a guarantee, but this doesn’t sound great to me. I can't tell whether your objection is with this comment in the ChangeLog, or the actual to<int> methods. The goal of the assertion checks for to<int> methods is to catch bugs in debug builds were integer truncation is happening unexpectedly. I guess if that's a non-goal, then we don't need the to<int> methods. > > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:132 > > + float dragAngle = atanf(to<float>(abs(deltaFromStart.height())) / to<float>(abs(deltaFromStart.width()))); > > I don’t see any benefit to using to<float> here instead of static_cast<float>. Is there a benefit I am missing? static_cast<float> is a rather large hammer that will change any base numeric type to a float. The to<float> methods are more explicit and can be tailored to behave differently (in Debug builds) for different arguments. (I guess most of the assertions I had in earlier patches were ripped out, so maybe this doesn't matter anymore.) > > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:150 > > + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollLeft : ScrollRight, ScrollByPixel, to<float>(abs(delta))); > > Ditto. > > > Source/WebCore/platform/ios/ScrollAnimatorIOS.mm:156 > > + handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollUp : ScrollDown, ScrollByPixel, to<float>(abs(delta))); > > Ditto. > > > Source/WebCore/platform/ios/wak/WKView.mm:252 > > else if (origMarginsTotal == 0.0f > > - || (abs(origMarginsTotal) == 1)) { > > + || (truncateTo<int>(std::abs(origMarginsTotal)) == 1)) { > > I don’t think that truncating is what we want to do here. Lets instead write out the code in a way that makes it obvious what it actually does. Here's what the code does: > > if (origMarginsTotal == 0 || (origMarginsTotal > -2 && origMarginsTotal <= -1) || (origMarginsTotal >= 1 && origMarginsTotal < 2)) > > I think this rule is wrong, and rewriting it to use std::abs and truncateTo just makes it seem like it makes sense, but obscures what is actually happening. Writing the way the way I suggest above to make it clear what it really does might make someone consider fixing it. One step in the right direction would be to get rid of the strange special case for the range (0,1). Like this: > > if (origMarginsTotal > -2 && origMarginsTotal < 2) > > That seems like it might be a helpful change, although it is a change in behavior. Okay.
Andy Estes
Comment 16 2014-10-06 17:47:03 PDT
In the interest of moving forward quickly, I'm going to post a patch that fixes these warnings with regular casts and let Dave continue with the NumericConversion.h work as a follow-up.
Andy Estes
Comment 17 2014-10-06 17:49:32 PDT
Andy Estes
Comment 18 2014-10-06 20:33:21 PDT
Note You need to log in before you can comment on or make changes to this bug.