Use std::hypot for Pythagorean Addition – EasyHack

There are many places in the code that calculating the Pythagorean addition is needed.It is defined as:

a ⊕ b = sqrt(a^2+b^2)

This is hypotenuse, or the length of the longest side of a right-angled triangle, that we know the other 2 sides, a and b. For a more detailed description, see this:

Theoretically, this calculation could be done using sqrt(a * a + b * b), but there are problems with this approach. For large a or b, there is a possibility of overflow, although the result itself is not that big to cause overflow.

To overcome this problem, there are implementations of hypotenuse that do not use power of 2, and use other methods to calculate the result. One of them which is usable in C++ is the std::hypot. To calculate a ⊕ b, you can easily use std::hypot(a,b). For the description of this function, see this page:

As an example, you can see this commit from Mike:

@@ -3943,8 +3943,6 @@ void HwpReader::makePicture(Picture * hbox)
    }
}

- namespace { double DBL(int x) { return x * x; } }
-
void HwpReader::makePictureDRAW(HWPDrawingObject *drawobj, Picture * hbox)
{
    int x = hbox->pgx;
@@ -4047,8 +4045,8 @@ void HwpReader::makePictureDRAW(HWPDrawingObject *drawobj, Picture * hbox)
                    bIsRotate = true;
                }
                if( bIsRotate ){
-                   drawobj->extent.w = static_cast<int>(sqrt(DBL(pt[1].x-pt[0].x) + DBL(pt[1].y-pt[0].y)));
-                   drawobj->extent.h = static_cast<int>(sqrt(DBL(pt[2].x-pt[1].x) + DBL(pt[2].y-pt[1].y)));
+                   drawobj->extent.w = static_cast<int>(std::hypot(pt[1].x-pt[0].x, pt[1].y-pt[0].y));
+                   drawobj->extent.h = static_cast<int>(std::hypot(pt[2].x-pt[1].x, pt[2].y-pt[1].y));
                    padd("draw:transform", sXML_CDATA, trans);
                }
            }

How to find instances

Among the result of this output, you can find some instances:

git grep sqrt

Afterall, there are good candidates among the results. You can look at the results to find the instances of a Pythagorean addition. Then, you can use the std::hypot instead of the manual addition.

This is both a code cleanup that produces a more readable code, and also reduces the instances where the manual calculation can lead to an unwanted overflow.

Update: Pythagorean Addition for Other Languages

This EasyHack was previously about C++ std::hypot, but it would be fine to use the similar method Math.hypot() from Java, or math.hypot() from Python. Therefore, this EasyHack is now suitable for those who interested in improving C++, Java and Python code from LibreOffice.

As an example, you can refer to this change for Java:

Final Notes

EasyHacks are good starting points for the newcomers. This specific improvement is filed as tdf#147906.

If you want to contribute to LibreOffice code by working on this improvement, but you need to know how to get started with LibreOffice development, I suggest you to see our Getting started video tutorial.