tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / include / basegfx / matrix / hommatrixtemplate.hxx
blob4f1300f533189a5eac30611e5321dbbbdff31ac8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #pragma once
22 #include <sal/types.h>
23 #include <basegfx/numeric/ftools.hxx>
24 #include <cmath>
26 namespace basegfx::internal
29 inline constexpr double implGetDefaultValue(sal_uInt16 nRow, sal_uInt16 nColumn)
31 if(nRow == nColumn)
32 return 1.0;
33 return 0.0;
36 template < sal_uInt16 RowSize > class ImplMatLine
38 double mfValue[RowSize];
40 public:
41 ImplMatLine() = default;
43 explicit ImplMatLine(sal_uInt16 nRow)
45 for(sal_uInt16 a(0); a < RowSize; a++)
47 mfValue[a] = implGetDefaultValue(nRow, a);
51 double get(sal_uInt16 nColumn) const
53 return mfValue[nColumn];
56 void set(sal_uInt16 nColumn, const double& rValue)
58 mfValue[nColumn] = rValue;
62 template < sal_uInt16 RowSize > class ImplHomMatrixTemplate
64 ImplMatLine< RowSize > maLine[RowSize];
66 public:
67 // Is last line used?
68 bool isLastLineDefault() const
70 for(sal_uInt16 a(0); a < RowSize; a++)
72 const double fDefault(implGetDefaultValue((RowSize - 1), a));
73 const double fLineValue(maLine[RowSize-1].get(a));
75 if(fDefault != fLineValue)
77 return false;
80 return true;
83 ImplHomMatrixTemplate()
85 // complete initialization with identity matrix, all lines
86 // were initialized with a trailing 1 followed by 0's.
87 for(sal_uInt16 a(0); a < RowSize; a++)
89 for(sal_uInt16 b(0); b < RowSize; b++)
90 maLine[a].set(b, implGetDefaultValue(a, b) );
94 ImplHomMatrixTemplate(const ImplHomMatrixTemplate& rToBeCopied)
96 operator=(rToBeCopied);
99 ImplHomMatrixTemplate& operator=(const ImplHomMatrixTemplate& rToBeCopied)
101 if (this != &rToBeCopied)
103 // complete initialization using copy
104 for(sal_uInt16 a(0); a < RowSize; a++)
106 maLine[a] = rToBeCopied.maLine[a];
109 return *this;
112 static sal_uInt16 getEdgeLength() { return RowSize; }
114 double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
116 return maLine[nRow].get(nColumn);
119 void set(sal_uInt16 nRow, sal_uInt16 nColumn, const double& rValue)
121 maLine[nRow].set(nColumn, rValue);
124 // Left-upper decomposition
125 bool ludcmp(sal_uInt16 nIndex[], sal_Int16& nParity)
127 double fBig, fSum, fDum;
128 double fStorage[RowSize];
129 sal_uInt16 a, b, c;
131 // #i30874# Initialize nAMax (compiler warns)
132 sal_uInt16 nAMax = 0;
134 nParity = 1;
136 // Calc the max of each line. If a line is empty,
137 // stop immediately since matrix is not invertible then.
138 for(a = 0; a < RowSize; a++)
140 fBig = 0.0;
142 for(b = 0; b < RowSize; b++)
144 double fTemp(fabs(get(a, b)));
146 if(::basegfx::fTools::more(fTemp, fBig))
148 fBig = fTemp;
152 if(::basegfx::fTools::equalZero(fBig))
154 return false;
157 fStorage[a] = 1.0 / fBig;
160 // start normalizing
161 for(b = 0; b < RowSize; b++)
163 for(a = 0; a < b; a++)
165 fSum = get(a, b);
167 for(c = 0; c < a; c++)
169 fSum -= get(a, c) * get(c, b);
172 set(a, b, fSum);
175 fBig = 0.0;
177 for(a = b; a < RowSize; a++)
179 fSum = get(a, b);
181 for(c = 0; c < b; c++)
183 fSum -= get(a, c) * get(c, b);
186 set(a, b, fSum);
187 fDum = fStorage[a] * fabs(fSum);
189 if(::basegfx::fTools::moreOrEqual(fDum, fBig))
191 fBig = fDum;
192 nAMax = a;
196 if(b != nAMax)
198 for(c = 0; c < RowSize; c++)
200 fDum = get(nAMax, c);
201 set(nAMax, c, get(b, c));
202 set(b, c, fDum);
205 nParity = -nParity;
206 fStorage[nAMax] = fStorage[b];
209 nIndex[b] = nAMax;
211 // here the failure of precision occurs
212 const double fValBB(fabs(get(b, b)));
214 if(::basegfx::fTools::equalZero(fValBB))
216 return false;
219 if(b != (RowSize - 1))
221 fDum = 1.0 / get(b, b);
223 for(a = b + 1; a < RowSize; a++)
225 set(a, b, get(a, b) * fDum);
230 return true;
233 void lubksb(const sal_uInt16 nIndex[], double fRow[]) const
235 sal_uInt16 b, ip;
236 sal_Int16 a, a2 = -1;
237 double fSum;
239 for(a = 0; a < RowSize; a++)
241 ip = nIndex[a];
242 fSum = fRow[ip];
243 fRow[ip] = fRow[a];
245 if(a2 >= 0)
247 for(b = a2; b < a; b++)
249 fSum -= get(a, b) * fRow[b];
252 else if(!::basegfx::fTools::equalZero(fSum))
254 a2 = a;
257 fRow[a] = fSum;
260 for(a = (RowSize - 1); a >= 0; a--)
262 fSum = fRow[a];
264 for(b = a + 1; b < RowSize; b++)
266 fSum -= get(a, b) * fRow[b];
269 const double fValueAA(get(a, a));
271 if(!::basegfx::fTools::equalZero(fValueAA))
273 fRow[a] = fSum / get(a, a);
278 bool isIdentity() const
280 for(sal_uInt16 a(0); a < RowSize; a++)
282 for(sal_uInt16 b(0); b < RowSize; b++)
284 const double fDefault(implGetDefaultValue(a, b));
285 const double fValueAB(get(a, b));
287 if(!::basegfx::fTools::equal(fDefault, fValueAB))
289 return false;
294 return true;
297 bool isInvertible() const
299 ImplHomMatrixTemplate aWork(*this);
300 sal_uInt16 nIndex[RowSize];
301 sal_Int16 nParity;
303 return aWork.ludcmp(nIndex, nParity);
306 void doInvert(const ImplHomMatrixTemplate& rWork, const sal_uInt16 nIndex[])
308 double fArray[RowSize];
310 for(sal_uInt16 a(0); a < RowSize; a++)
312 // prepare line
313 sal_uInt16 b;
314 for( b = 0; b < RowSize; b++)
316 fArray[b] = implGetDefaultValue(a, b);
319 // expand line
320 rWork.lubksb(nIndex, fArray);
322 // copy line transposed to this matrix
323 for( b = 0; b < RowSize; b++)
325 set(b, a, fArray[b]);
330 double doDeterminant() const
332 ImplHomMatrixTemplate aWork(*this);
333 sal_uInt16 nIndex[RowSize];
334 sal_Int16 nParity;
335 double fRetval(0.0);
337 if(aWork.ludcmp(nIndex, nParity))
339 fRetval = static_cast<double>(nParity);
340 for(sal_uInt16 a(0); a < RowSize; a++)
342 fRetval *= aWork.get(a, a);
346 return fRetval;
349 void doAddMatrix(const ImplHomMatrixTemplate& rMat)
351 for(sal_uInt16 a(0); a < RowSize; a++)
353 for(sal_uInt16 b(0); b < RowSize; b++)
355 set(a, b, get(a, b) + rMat.get(a, b));
360 void doSubMatrix(const ImplHomMatrixTemplate& rMat)
362 for(sal_uInt16 a(0); a < RowSize; a++)
364 for(sal_uInt16 b(0); b < RowSize; b++)
366 set(a, b, get(a, b) - rMat.get(a, b));
371 void doMulMatrix(const double& rfValue)
373 for(sal_uInt16 a(0); a < RowSize; a++)
375 for(sal_uInt16 b(0); b < RowSize; b++)
377 set(a, b, get(a, b) * rfValue);
382 void doMulMatrix(const ImplHomMatrixTemplate& rMat)
384 // create a copy as source for the original values
385 const ImplHomMatrixTemplate aCopy(*this);
387 // TODO: maybe optimize cases where last line is [0 0 1].
389 double fValue(0.0);
391 for(sal_uInt16 a(0); a < RowSize; ++a)
393 for(sal_uInt16 b(0); b < RowSize; ++b)
395 fValue = 0.0;
397 for(sal_uInt16 c(0); c < RowSize; ++c)
398 fValue += aCopy.get(c, b) * rMat.get(a, c);
400 set(a, b, fValue);
405 bool isEqual(const ImplHomMatrixTemplate& rMat) const
407 for(sal_uInt16 a(0); a < RowSize; a++)
409 for(sal_uInt16 b(0); b < RowSize; b++)
411 const double fValueA(get(a, b));
412 const double fValueB(rMat.get(a, b));
414 if(!::basegfx::fTools::equal(fValueA, fValueB))
416 return false;
421 return true;
425 } // namespace basegfx::internal
427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */