Skip to content

Commit

Permalink
Change NaN with large number
Browse files Browse the repository at this point in the history
Summary:
Changed NaN with large number to support `-ffast-math` compiler flag.For  `-ffast-math` to work, all floating point numbers should be finite. Reason for not going with `FLT_MAX`, is that, it may cause number overflow during math operations. So thats why I opted for big number smaller than `FLT_MAX`.  Earlier we used NaN, while NaN is involved in comparision the comparision operator behaves differently, it always returns false. Also operators like, fmaxf,fminf etc. have wierd beahviours. This diff takes care of those things as far as possible, and all tests are passing.

Running ./instrumentation_tests/run instrumentation_tests/com/facebook/feed/ctacoalescing:ctacoalescing --class AttachmentCallToActionSelectorBenchmarkTest --benchmark --extra-arg iterations=100 shows the perf gain of 13-15%

Reviewed By: emilsjolander

Differential Revision: D6969537

fbshipit-source-id: bdc09eaf703e0d313ca65c25a4fb44c99203d9bf
  • Loading branch information
priteshrnandgaonkar authored and facebook-github-bot committed Mar 1, 2018
1 parent adab060 commit 68c51c3
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 127 deletions.
24 changes: 23 additions & 1 deletion lib/yoga/src/main/cpp/yoga/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,37 @@ YGFlexDirection YGFlexDirectionCross(
: YGFlexDirectionColumn;
}

float YGFloatMax(const float a, const float b) {
if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
return fmaxf(a, b);
}
return YGFloatIsUndefined(a) ? b : a;
}

float YGFloatMin(const float a, const float b) {
if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
return fminf(a, b);
}

return YGFloatIsUndefined(a) ? b : a;
}

bool YGValueEqual(const YGValue a, const YGValue b) {
if (a.unit != b.unit) {
return false;
}

if (a.unit == YGUnitUndefined ||
(std::isnan(a.value) && std::isnan(b.value))) {
(YGFloatIsUndefined(a.value) && YGFloatIsUndefined(b.value))) {
return true;
}

return fabs(a.value - b.value) < 0.0001f;
}

bool YGFloatsEqual(const float a, const float b) {
if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
return fabs(a - b) < 0.0001f;
}
return YGFloatIsUndefined(a) && YGFloatIsUndefined(b);
}
34 changes: 33 additions & 1 deletion lib/yoga/src/main/cpp/yoga/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,38 @@ struct YGCollectFlexItemsRowValues {

bool YGValueEqual(const YGValue a, const YGValue b);

// This custom float equality function returns true if either absolute
// difference between two floats is less than 0.0001f or both are undefined.
bool YGFloatsEqual(const float a, const float b);

// We need custom max function, since we want that, if one argument is
// YGUndefined then the max funtion should return the other argument as the max
// value. We wouldn't have needed a custom max function if YGUndefined was NAN
// as fmax has the same behaviour, but with NAN we cannot use `-ffast-math`
// compiler flag.
float YGFloatMax(const float a, const float b);

// We need custom min function, since we want that, if one argument is
// YGUndefined then the min funtion should return the other argument as the min
// value. We wouldn't have needed a custom min function if YGUndefined was NAN
// as fmin has the same behaviour, but with NAN we cannot use `-ffast-math`
// compiler flag.
float YGFloatMin(const float a, const float b);

// This custom float comparision function compares the array of float with
// YGFloatsEqual, as the default float comparision operator will not work(Look
// at the comments of YGFloatsEqual function).
template <std::size_t size>
bool YGFloatArrayEqual(
const std::array<float, size>& val1,
const std::array<float, size>& val2) {
bool areEqual = true;
for (std::size_t i = 0; i < size && areEqual; ++i) {
areEqual = YGFloatsEqual(val1[i], val2[i]);
}
return areEqual;
}

YGFlexDirection YGFlexDirectionCross(
const YGFlexDirection flexDirection,
const YGDirection direction);
Expand All @@ -71,7 +103,7 @@ inline float YGResolveValue(const YGValue value, const float parentSize) {
case YGUnitPoint:
return value.value;
case YGUnitPercent:
return value.value * parentSize / 100.0f;
return value.value * parentSize * 0.01;
}
return YGUndefined;
}
Expand Down
9 changes: 6 additions & 3 deletions lib/yoga/src/main/cpp/yoga/YGLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
#include "YGLayout.h"
#include "Utils.h"

const std::array<float, 2> kYGDefaultDimensionValues = {
{YGUndefined, YGUndefined}};
Expand All @@ -31,9 +32,11 @@ YGLayout::YGLayout()
doesLegacyStretchFlagAffectsLayout(false) {}

bool YGLayout::operator==(YGLayout layout) const {
bool isEqual = position == layout.position &&
dimensions == layout.dimensions && margin == layout.margin &&
border == layout.border && padding == layout.padding &&
bool isEqual = YGFloatArrayEqual(position, layout.position) &&
YGFloatArrayEqual(dimensions, layout.dimensions) &&
YGFloatArrayEqual(margin, layout.margin) &&
YGFloatArrayEqual(border, layout.border) &&
YGFloatArrayEqual(padding, layout.padding) &&
direction == layout.direction && hadOverflow == layout.hadOverflow &&
lastParentDirection == layout.lastParentDirection &&
nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex &&
Expand Down
41 changes: 24 additions & 17 deletions lib/yoga/src/main/cpp/yoga/YGNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,56 +624,63 @@ bool YGNode::isNodeFlexible() {
float YGNode::getLeadingBorder(const YGFlexDirection axis) {
if (YGFlexDirectionIsRow(axis) &&
style_.border[YGEdgeStart].unit != YGUnitUndefined &&
!YGFloatIsUndefined(style_.border[YGEdgeStart].value) &&
style_.border[YGEdgeStart].value >= 0.0f) {
return style_.border[YGEdgeStart].value;
}

return fmaxf(
YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value,
0.0f);
float computedEdgeValue =
YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value;
return YGFloatMax(computedEdgeValue, 0.0f);
}

float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) {
if (YGFlexDirectionIsRow(flexDirection) &&
style_.border[YGEdgeEnd].unit != YGUnitUndefined &&
!YGFloatIsUndefined(style_.border[YGEdgeEnd].value) &&
style_.border[YGEdgeEnd].value >= 0.0f) {
return style_.border[YGEdgeEnd].value;
}

return fmaxf(
float computedEdgeValue =
YGComputedEdgeValue(style_.border, trailing[flexDirection], &YGValueZero)
->value,
0.0f);
->value;
return YGFloatMax(computedEdgeValue, 0.0f);
}

float YGNode::getLeadingPadding(
const YGFlexDirection axis,
const float widthSize) {
if (YGFlexDirectionIsRow(axis) &&
style_.padding[YGEdgeStart].unit != YGUnitUndefined &&
YGResolveValue(style_.padding[YGEdgeStart], widthSize) >= 0.0f) {
!YGFloatIsUndefined(
YGResolveValue(style_.padding[YGEdgeStart], widthSize)) &&
YGResolveValue(style_.padding[YGEdgeStart], widthSize) > 0.0f) {
return YGResolveValue(style_.padding[YGEdgeStart], widthSize);
}
return fmaxf(
YGResolveValue(
*YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero),
widthSize),
0.0f);

float resolvedValue = YGResolveValue(
*YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero),
widthSize);
return YGFloatMax(resolvedValue, 0.0f);
}

float YGNode::getTrailingPadding(
const YGFlexDirection axis,
const float widthSize) {
if (YGFlexDirectionIsRow(axis) &&
style_.padding[YGEdgeEnd].unit != YGUnitUndefined &&
!YGFloatIsUndefined(
YGResolveValue(style_.padding[YGEdgeEnd], widthSize)) &&
YGResolveValue(style_.padding[YGEdgeEnd], widthSize) >= 0.0f) {
return YGResolveValue(style_.padding[YGEdgeEnd], widthSize);
}
return fmaxf(
YGResolveValue(
*YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero),
widthSize),
0.0f);

float resolvedValue = YGResolveValue(
*YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero),
widthSize);

return YGFloatMax(resolvedValue, 0.0f);
}

float YGNode::getLeadingPaddingAndBorder(
Expand Down
10 changes: 6 additions & 4 deletions lib/yoga/src/main/cpp/yoga/YGStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,23 @@ bool YGStyle::operator==(const YGStyle& style) {
YGValueArrayEqual(minDimensions, style.minDimensions) &&
YGValueArrayEqual(maxDimensions, style.maxDimensions);

if (!(std::isnan(flex) && std::isnan(style.flex))) {
if (!(YGFloatIsUndefined(flex) && YGFloatIsUndefined(style.flex))) {
areNonFloatValuesEqual = areNonFloatValuesEqual && flex == style.flex;
}

if (!(std::isnan(flexGrow) && std::isnan(style.flexGrow))) {
if (!(YGFloatIsUndefined(flexGrow) && YGFloatIsUndefined(style.flexGrow))) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && flexGrow == style.flexGrow;
}

if (!(std::isnan(flexShrink) && std::isnan(style.flexShrink))) {
if (!(YGFloatIsUndefined(flexShrink) &&
YGFloatIsUndefined(style.flexShrink))) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && flexShrink == style.flexShrink;
}

if (!(std::isnan(aspectRatio) && std::isnan(style.aspectRatio))) {
if (!(YGFloatIsUndefined(aspectRatio) &&
YGFloatIsUndefined(style.aspectRatio))) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && aspectRatio == style.aspectRatio;
}
Expand Down
15 changes: 8 additions & 7 deletions lib/yoga/src/main/cpp/yoga/Yoga-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,20 @@ struct YGCachedMeasurement {
bool isEqual = widthMeasureMode == measurement.widthMeasureMode &&
heightMeasureMode == measurement.heightMeasureMode;

if (!std::isnan(availableWidth) ||
!std::isnan(measurement.availableWidth)) {
if (!YGFloatIsUndefined(availableWidth) ||
!YGFloatIsUndefined(measurement.availableWidth)) {
isEqual = isEqual && availableWidth == measurement.availableWidth;
}
if (!std::isnan(availableHeight) ||
!std::isnan(measurement.availableHeight)) {
if (!YGFloatIsUndefined(availableHeight) ||
!YGFloatIsUndefined(measurement.availableHeight)) {
isEqual = isEqual && availableHeight == measurement.availableHeight;
}
if (!std::isnan(computedWidth) || !std::isnan(measurement.computedWidth)) {
if (!YGFloatIsUndefined(computedWidth) ||
!YGFloatIsUndefined(measurement.computedWidth)) {
isEqual = isEqual && computedWidth == measurement.computedWidth;
}
if (!std::isnan(computedHeight) ||
!std::isnan(measurement.computedHeight)) {
if (!YGFloatIsUndefined(computedHeight) ||
!YGFloatIsUndefined(measurement.computedHeight)) {
isEqual = isEqual && computedHeight == measurement.computedHeight;
}

Expand Down
Loading

0 comments on commit 68c51c3

Please sign in to comment.