diff options
author | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2023-06-10 18:13:50 +0200 |
---|---|---|
committer | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2023-06-13 12:59:33 +0200 |
commit | cbb215aa20783523555185c83875ea5d5b94535b (patch) | |
tree | 68d31593174fe0c52557312d0fa9e0b5827a6890 /drawinglayer/source | |
parent | 3e3d6aeec92a7252d92243e2de34b424cf5f7cdf (diff) |
tdf#143877 Fix failing tests caused by floating point precision
Due to different imlementation of floating-point unit (FPU),
on different CPU platforms, the floating point numbers could
could be different.
https://stackoverflow.com/questions/64036879/differing-floating-point-calculation-results-between-x86-64-and-armv8-2-a
https://mcuoneclipse.com/2019/03/29/be-aware-floating-point-operations-on-arm-cortex-m4f/
With this path I have changed the tested images,
to use floating point numbers which are easily represented
by floating numbers (multiplied/divided by 2), like:
- change tension to values: 0.125, 0.25, 0.5, 1.0, 1.5 ...
- change position of curve to of control points to 256.0, 384.0 512.0
Previous values was hard to represent by floating numbers,
for example tension:
- 0.4 has been written as 0.399999976158142
- 0.1 has been written as 0.099999994039535
More information:
https://observablehq.com/@benaubin/floating-point
Additionally the precision of numbers were
increased to double.
Change-Id: I5725c1f2f474d0c00821edaa9bb2102cb172093f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152838
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Tested-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Diffstat (limited to 'drawinglayer/source')
-rw-r--r-- | drawinglayer/source/tools/emfppath.cxx | 42 |
1 files changed, 19 insertions, 23 deletions
diff --git a/drawinglayer/source/tools/emfppath.cxx b/drawinglayer/source/tools/emfppath.cxx index bd5b2d357b0f..e7c4a5512c76 100644 --- a/drawinglayer/source/tools/emfppath.cxx +++ b/drawinglayer/source/tools/emfppath.cxx @@ -34,7 +34,12 @@ namespace namespace emfplushelper { - typedef float matrix [4][4]; + typedef double matrix [4][4]; + + constexpr sal_uInt32 nDetails = 8; + constexpr double alpha[nDetails] + = { 1. / nDetails, 2. / nDetails, 3. / nDetails, 4. / nDetails, + 5. / nDetails, 6. / nDetails, 7. / nDetails, 8. / nDetails }; // see 2.2.2.21 EmfPlusInteger7 // 2.2.2.22 EmfPlusInteger15 @@ -232,21 +237,20 @@ namespace emfplushelper m[0][2] = tension - 2.; m[1][0] = 2. * tension; m[1][1] = tension - 3.; - m[1][2] = 3. - 2 * tension; + m[1][2] = 3. - 2. * tension; m[3][1] = 1.; m[0][3] = m[2][2] = tension; m[0][0] = m[1][3] = m[2][0] = -tension; m[2][1] = m[2][3] = m[3][0] = m[3][2] = m[3][3] = 0.; } - static float calculateSplineCoefficients(float p0, float p1, float p2, float p3, float alpha, matrix m) + static double calculateSplineCoefficients(float p0, float p1, float p2, float p3, sal_uInt32 step, matrix m) { - float a, b, c, d; - a = m[0][0] * p0 + m[0][1] * p1 + m[0][2] * p2 + m[0][3] * p3; - b = m[1][0] * p0 + m[1][1] * p1 + m[1][2] * p2 + m[1][3] * p3; - c = m[2][0] * p0 + m[2][2] * p2; - d = p1; - return (d + alpha * (c + alpha * (b + alpha * a))); + double a = m[0][0] * p0 + m[0][1] * p1 + m[0][2] * p2 + m[0][3] * p3; + double b = m[1][0] * p0 + m[1][1] * p1 + m[1][2] * p2 + m[1][3] * p3; + double c = m[2][0] * p0 + m[2][2] * p2; + double d = p1; + return (d + alpha[step] * (c + alpha[step] * (b + alpha[step] * a))); } ::basegfx::B2DPolyPolygon& EMFPPath::GetCardinalSpline(EmfPlusHelperData const& rR, float fTension, @@ -254,11 +258,7 @@ namespace emfplushelper { ::basegfx::B2DPolygon polygon; matrix mat; - float x, y; - constexpr sal_uInt32 nDetails = 8; - constexpr float alpha[nDetails] - = { 1. / nDetails, 2. / nDetails, 3. / nDetails, 4. / nDetails, - 5. / nDetails, 6. / nDetails, 7. / nDetails, 8. / nDetails }; + double x, y; if (aNumSegments >= nPoints) aNumSegments = nPoints - 1; GetCardinalMatrix(fTension, mat); @@ -274,9 +274,9 @@ namespace emfplushelper for (sal_uInt32 s = 0; s < nDetails; s++) { x = calculateSplineCoefficients(xPoints[i - 3], xPoints[i - 2], xPoints[i - 1], - xPoints[i], alpha[s], mat); + xPoints[i], s, mat); y = calculateSplineCoefficients(yPoints[i - 3], yPoints[i - 2], yPoints[i - 1], - yPoints[i], alpha[s], mat); + yPoints[i], s, mat); polygon.append(rR.Map(x, y)); } } @@ -289,11 +289,7 @@ namespace emfplushelper { ::basegfx::B2DPolygon polygon; matrix mat; - float x, y; - constexpr sal_uInt32 nDetails = 8; - constexpr float alpha[nDetails] - = { 1. / nDetails, 2. / nDetails, 3. / nDetails, 4. / nDetails, - 5. / nDetails, 6. / nDetails, 7. / nDetails, 8. / nDetails }; + double x, y; GetCardinalMatrix(fTension, mat); // add three first points at the end xPoints.push_back(xPoints[0]); @@ -308,9 +304,9 @@ namespace emfplushelper for (sal_uInt32 s = 0; s < nDetails; s++) { x = calculateSplineCoefficients(xPoints[i - 3], xPoints[i - 2], xPoints[i - 1], - xPoints[i], alpha[s], mat); + xPoints[i], s, mat); y = calculateSplineCoefficients(yPoints[i - 3], yPoints[i - 2], yPoints[i - 1], - yPoints[i], alpha[s], mat); + yPoints[i], s, mat); polygon.append(rR.Map(x, y)); } } |