tdf#155628 split upper triangular code into new function and call

This change reduces the cognitive complexity of the
CalculateBSplines function by moving some of the linear
algebra code into a new function and then calling
the function. No changes are made to external code behavior.

Change-Id: I4116d24b30e922a2f3777aa8dcd926ee690b8243
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205231
Reviewed-by: Hossein <hossein@libreoffice.org>
Tested-by: Jenkins
This commit is contained in:
Jason Whitmore
2026-09-26 10:05:54 +02:00
committed by Hossein
parent 2a64f606b5
commit 94f01698f5
+73 -57
View File
@@ -38,6 +38,75 @@ typedef std::pair< double, double > tPointType;
typedef std::vector< tPointType > tPointVecType;
typedef tPointVecType::size_type lcl_tSizeType;
bool lcl_CalculateUpperTriangularForm(
tPointVecType& rPointsIn
, std::vector<std::vector<double>>& rMatN
, std::vector<lcl_tSizeType>& rShift )
{
lcl_tSizeType r = 0; // true row index
lcl_tSizeType c = 0; // true column index
double fDivisor = 1.0; // used for diagonal element
double fEliminate = 1.0; // used for the element, that will become zero
bool bIsSuccessful = true;
const lcl_tSizeType n = rPointsIn.size() - 1;
for (c = 0 ; c <= n && bIsSuccessful; ++c)
{
// search for first non-zero downwards
r = c;
while ( r < n && rMatN[r][c-rShift[r]] == 0 )
{
++r;
}
if (rMatN[r][c-rShift[r]] == 0.0)
{
// Matrix N is singular, although this is mathematically impossible
bIsSuccessful = false;
}
else
{
// exchange total row r with total row c if necessary
if (r != c)
{
std::swap( rMatN[r], rMatN[c] );
std::swap( rPointsIn[r], rPointsIn[c] );
std::swap( rShift[r], rShift[c] );
}
sal_uInt32 p = rMatN[c].size() - 1;
// divide row c, so that element(c,c) becomes 1
fDivisor = rMatN[c][c-rShift[c]]; // not zero, see above
for (sal_uInt32 i = 0; i <= p; ++i)
{
rMatN[c][i] /= fDivisor;
}
rPointsIn[c].first /= fDivisor;
rPointsIn[c].second /= fDivisor;
// eliminate forward, examine row c+1 to n-1 (worst case)
// stop if first non-zero element in row has an higher column as c
// look at nShift for that, elements in nShift are equal or increasing
for ( r = c+1; r < n && rShift[r]<=c ; ++r)
{
fEliminate = rMatN[r][0];
if (fEliminate != 0.0) // else accidentally zero, nothing to do
{
for (sal_uInt32 i = 1; i <= p; ++i)
{
rMatN[r][i-1] = rMatN[r][i] - fEliminate * rMatN[c][i];
}
rMatN[r][p]=0;
rPointsIn[r].first -= fEliminate * rPointsIn[c].first;
rPointsIn[r].second -= fEliminate * rPointsIn[c].second;
++rShift[r];
}
}
}
}
return bIsSuccessful;
}
class lcl_SplineCalculation
{
public:
@@ -719,63 +788,9 @@ void SplineCalculator::CalculateBSplines(
// Get matrix C of control points from the matrix equation aMatN * C = aPointsIn
// aPointsIn is overwritten with C.
// Gaussian elimination is possible without pivoting, see reference
lcl_tSizeType r = 0; // true row index
lcl_tSizeType c = 0; // true column index
double fDivisor = 1.0; // used for diagonal element
double fEliminate = 1.0; // used for the element, that will become zero
bool bIsSuccessful = true;
for (c = 0 ; c <= n && bIsSuccessful; ++c)
{
// search for first non-zero downwards
r = c;
while ( r < n && aMatN[r][c-aShift[r]] == 0 )
{
++r;
}
if (aMatN[r][c-aShift[r]] == 0.0)
{
// Matrix N is singular, although this is mathematically impossible
bIsSuccessful = false;
}
else
{
// exchange total row r with total row c if necessary
if (r != c)
{
std::swap( aMatN[r], aMatN[c] );
std::swap( aPointsIn[r], aPointsIn[c] );
std::swap( aShift[r], aShift[c] );
}
// divide row c, so that element(c,c) becomes 1
fDivisor = aMatN[c][c-aShift[c]]; // not zero, see above
for (sal_uInt32 i = 0; i <= p; ++i)
{
aMatN[c][i] /= fDivisor;
}
aPointsIn[c].first /= fDivisor;
aPointsIn[c].second /= fDivisor;
bool bIsSuccessful = lcl_CalculateUpperTriangularForm(aPointsIn, aMatN, aShift);
// eliminate forward, examine row c+1 to n-1 (worst case)
// stop if first non-zero element in row has an higher column as c
// look at nShift for that, elements in nShift are equal or increasing
for ( r = c+1; r < n && aShift[r]<=c ; ++r)
{
fEliminate = aMatN[r][0];
if (fEliminate != 0.0) // else accidentally zero, nothing to do
{
for (sal_uInt32 i = 1; i <= p; ++i)
{
aMatN[r][i-1] = aMatN[r][i] - fEliminate * aMatN[c][i];
}
aMatN[r][p]=0;
aPointsIn[r].first -= fEliminate * aPointsIn[c].first;
aPointsIn[r].second -= fEliminate * aPointsIn[c].second;
++aShift[r];
}
}
}
}// upper triangle form is reached
if( bIsSuccessful)
{
// eliminate backwards, begin with last column
@@ -785,10 +800,11 @@ void SplineCalculator::CalculateBSplines(
// diagonal are zero and do not influence other rows.
// Full matrix N has semibandwidth < p, therefore element(r,c) is
// zero, if abs(r-cc)>=p. abs(r-cc)=cc-r, because r<cc.
r = cc - 1;
lcl_tSizeType r = cc - 1; // true row index
while ( r !=0 && cc-r < p )
{
fEliminate = aMatN[r][ cc - aShift[r] ];
double fEliminate = aMatN[r][ cc - aShift[r] ]; // used for the element, that will become zero
if ( fEliminate != 0.0) // else element is accidentally zero, no action needed
{
// row r -= fEliminate * row cc only relevant for right side