LCOV - code coverage report
Current view: top level - basegfx/source/inc - hommatrixtemplate.hxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 178 206 86.4 %
Date: 2014-11-03 Functions: 38 45 84.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #ifndef INCLUDED_BASEGFX_SOURCE_INC_HOMMATRIXTEMPLATE_HXX
      21             : #define INCLUDED_BASEGFX_SOURCE_INC_HOMMATRIXTEMPLATE_HXX
      22             : 
      23             : #include <sal/types.h>
      24             : #include <basegfx/numeric/ftools.hxx>
      25             : #include <math.h>
      26             : #include <string.h>
      27             : 
      28             : namespace basegfx
      29             : {
      30             :     namespace internal
      31             :     {
      32             : 
      33    36430525 :         inline double implGetDefaultValue(sal_uInt16 nRow, sal_uInt16 nColumn)
      34             :         {
      35    36430525 :             if(nRow == nColumn)
      36    12263573 :                 return 1.0;
      37    24166952 :             return 0.0;
      38             :         }
      39             : 
      40             :         template < unsigned int _RowSize > class ImplMatLine
      41             :         {
      42             :             enum { RowSize = _RowSize };
      43             : 
      44             :             double                                          mfValue[RowSize];
      45             : 
      46             :         public:
      47     6236446 :             ImplMatLine()
      48             :             {
      49     6236446 :             }
      50             : 
      51       16459 :             explicit ImplMatLine(sal_uInt16 nRow, ImplMatLine< RowSize >* pToBeCopied = 0L)
      52             :             {
      53       16459 :                 if(pToBeCopied)
      54             :                 {
      55        8005 :                     memcpy(&mfValue, pToBeCopied, sizeof(double) * RowSize);
      56             :                 }
      57             :                 else
      58             :                 {
      59       42244 :                     for(sal_uInt16 a(0); a < RowSize; a++)
      60             :                     {
      61       33790 :                         mfValue[a] = implGetDefaultValue(nRow, a);
      62             :                     }
      63             :                 }
      64       16459 :             }
      65             : 
      66   132644261 :             double get(sal_uInt16 nColumn) const
      67             :             {
      68   132644261 :                 return mfValue[nColumn];
      69             :             }
      70             : 
      71    16169131 :             void set(sal_uInt16 nColumn, const double& rValue)
      72             :             {
      73    16169131 :                 mfValue[nColumn] = rValue;
      74    16169131 :             }
      75             :         };
      76             : 
      77             :         template < unsigned int _RowSize > class ImplHomMatrixTemplate
      78             :         {
      79             :             enum { RowSize = _RowSize };
      80             : 
      81             :             ImplMatLine< RowSize >                          maLine[RowSize - 1];
      82             :             ImplMatLine< RowSize >*                         mpLine;
      83             : 
      84             :         public:
      85             :             // Is last line used?
      86    10286080 :             bool isLastLineDefault() const
      87             :             {
      88    10286080 :                 if(!mpLine)
      89    10263020 :                     return true;
      90             : 
      91       25956 :                 for(sal_uInt16 a(0); a < RowSize; a++)
      92             :                 {
      93       25956 :                     const double fDefault(implGetDefaultValue((RowSize - 1), a));
      94       25956 :                     const double fLineValue(mpLine->get(a));
      95             : 
      96       25956 :                     if(!::basegfx::fTools::equal(fDefault, fLineValue))
      97             :                     {
      98       23060 :                         return false;
      99             :                     }
     100             :                 }
     101             : 
     102             :                 // reset last line, it equals default
     103           0 :                 delete const_cast<ImplHomMatrixTemplate< RowSize >*>(this)->mpLine;
     104           0 :                 const_cast<ImplHomMatrixTemplate< RowSize >*>(this)->mpLine = 0L;
     105             : 
     106           0 :                 return true;
     107             :             }
     108             : 
     109      478290 :             ImplHomMatrixTemplate()
     110      478290 :                 :   mpLine(0L)
     111             :             {
     112             :                 // complete initialization with identity matrix, all lines
     113             :                 // were initialized with a trailing 1 followed by 0's.
     114     1574752 :                 for(sal_uInt16 a(0); a < RowSize-1; a++)
     115             :                 {
     116     4805494 :                     for(sal_uInt16 b(0); b < RowSize; b++)
     117     3709032 :                         maLine[a].set(b, implGetDefaultValue(a, b) );
     118             :                 }
     119      478290 :             }
     120             : 
     121     2233825 :             ImplHomMatrixTemplate(const ImplHomMatrixTemplate& rToBeCopied)
     122     2233825 :                 :   mpLine(0L)
     123             :             {
     124             :                 // complete initialization using copy
     125     7373809 :                 for(sal_uInt16 a(0); a < (RowSize - 1); a++)
     126             :                 {
     127     5139984 :                     memcpy(&maLine[a], &rToBeCopied.maLine[a], sizeof(ImplMatLine< RowSize >));
     128             :                 }
     129             : 
     130     2233825 :                 if(rToBeCopied.mpLine)
     131             :                 {
     132        8005 :                     mpLine = new ImplMatLine< RowSize >((RowSize - 1), rToBeCopied.mpLine);
     133             :                 }
     134     2233825 :             }
     135             : 
     136     2710344 :             ~ImplHomMatrixTemplate()
     137             :             {
     138     2710344 :                 if(mpLine)
     139             :                 {
     140       16459 :                     delete mpLine;
     141             :                 }
     142     2710344 :             }
     143             : 
     144       73436 :             sal_uInt16 getEdgeLength() const { return RowSize; }
     145             : 
     146   156028726 :             double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
     147             :             {
     148   156028726 :                 if(nRow < (RowSize - 1))
     149             :                 {
     150   132301468 :                     return maLine[nRow].get(nColumn);
     151             :                 }
     152             : 
     153    23727258 :                 if(mpLine)
     154             :                 {
     155      290020 :                     return mpLine->get(nColumn);
     156             :                 }
     157             : 
     158    23437238 :                 return implGetDefaultValue((RowSize - 1), nColumn);
     159             :             }
     160             : 
     161    16453559 :             void set(sal_uInt16 nRow, sal_uInt16 nColumn, const double& rValue)
     162             :             {
     163    16453559 :                 if(nRow < (RowSize - 1))
     164             :                 {
     165    12406636 :                     maLine[nRow].set(nColumn, rValue);
     166             :                 }
     167     4046923 :                 else if(mpLine)
     168             :                 {
     169       45009 :                     mpLine->set(nColumn, rValue);
     170             :                 }
     171             :                 else
     172             :                 {
     173     4001914 :                     const double fDefault(implGetDefaultValue((RowSize - 1), nColumn));
     174             : 
     175     4001914 :                     if(!::basegfx::fTools::equal(fDefault, rValue))
     176             :                     {
     177        8454 :                         mpLine = new ImplMatLine< RowSize >((RowSize - 1), 0L);
     178        8454 :                         mpLine->set(nColumn, rValue);
     179             :                     }
     180             :                 }
     181    16453559 :             }
     182             : 
     183     1017854 :             void testLastLine()
     184             :             {
     185     1017854 :                 if(mpLine)
     186             :                 {
     187       10583 :                     bool bNecessary(false);
     188             : 
     189       37400 :                     for(sal_uInt16 a(0);!bNecessary && a < RowSize; a++)
     190             :                     {
     191       26817 :                         const double fDefault(implGetDefaultValue((RowSize - 1), a));
     192       26817 :                         const double fLineValue(mpLine->get(a));
     193             : 
     194       26817 :                         if(!::basegfx::fTools::equal(fDefault, fLineValue))
     195             :                         {
     196       10583 :                             bNecessary = true;
     197             :                         }
     198             :                     }
     199             : 
     200       10583 :                     if(!bNecessary)
     201             :                     {
     202           0 :                         delete mpLine;
     203           0 :                         mpLine = 0L;
     204             :                     }
     205             :                 }
     206     1017854 :             }
     207             : 
     208             :             // Left-upper decompositon
     209       76107 :             bool ludcmp(sal_uInt16 nIndex[], sal_Int16& nParity)
     210             :             {
     211             :                 double fBig, fSum, fDum;
     212             :                 double fStorage[RowSize];
     213             :                 sal_uInt16 a, b, c;
     214             : 
     215             :                 // #i30874# Initialize nAMax (compiler warns)
     216       76107 :                 sal_uInt16 nAMax = 0;
     217             : 
     218       76107 :                 nParity = 1;
     219             : 
     220             :                 // Calc the max of each line. If a line is empty,
     221             :                 // stop immediately since matrix is not invertible then.
     222      326503 :                 for(a = 0; a < RowSize; a++)
     223             :                 {
     224      250396 :                     fBig = 0.0;
     225             : 
     226     1089884 :                     for(b = 0; b < RowSize; b++)
     227             :                     {
     228      839488 :                         double fTemp(fabs(get(a, b)));
     229             : 
     230      839488 :                         if(::basegfx::fTools::more(fTemp, fBig))
     231             :                         {
     232      325379 :                             fBig = fTemp;
     233             :                         }
     234             :                     }
     235             : 
     236      250396 :                     if(::basegfx::fTools::equalZero(fBig))
     237             :                     {
     238           0 :                         return false;
     239             :                     }
     240             : 
     241      250396 :                     fStorage[a] = 1.0 / fBig;
     242             :                 }
     243             : 
     244             :                 // start normalizing
     245      326503 :                 for(b = 0; b < RowSize; b++)
     246             :                 {
     247      544942 :                     for(a = 0; a < b; a++)
     248             :                     {
     249      294546 :                         fSum = get(a, b);
     250             : 
     251      436878 :                         for(c = 0; c < a; c++)
     252             :                         {
     253      142332 :                             fSum -= get(a, c) * get(c, b);
     254             :                         }
     255             : 
     256      294546 :                         set(a, b, fSum);
     257             :                     }
     258             : 
     259      250396 :                     fBig = 0.0;
     260             : 
     261      795338 :                     for(a = b; a < RowSize; a++)
     262             :                     {
     263      544942 :                         fSum = get(a, b);
     264             : 
     265      981820 :                         for(c = 0; c < b; c++)
     266             :                         {
     267      436878 :                             fSum -= get(a, c) * get(c, b);
     268             :                         }
     269             : 
     270      544942 :                         set(a, b, fSum);
     271      544942 :                         fDum = fStorage[a] * fabs(fSum);
     272             : 
     273      544942 :                         if(::basegfx::fTools::moreOrEqual(fDum, fBig))
     274             :                         {
     275      258996 :                             fBig = fDum;
     276      258996 :                             nAMax = a;
     277             :                         }
     278             :                     }
     279             : 
     280      250396 :                     if(b != nAMax)
     281             :                     {
     282       40686 :                         for(c = 0; c < RowSize; c++)
     283             :                         {
     284       32086 :                             fDum = get(nAMax, c);
     285       32086 :                             set(nAMax, c, get(b, c));
     286       32086 :                             set(b, c, fDum);
     287             :                         }
     288             : 
     289        8600 :                         nParity = -nParity;
     290        8600 :                         fStorage[nAMax] = fStorage[b];
     291             :                     }
     292             : 
     293      250396 :                     nIndex[b] = nAMax;
     294             : 
     295             :                     // here the failure of precision occurs
     296      250396 :                     const double fValBB(fabs(get(b, b)));
     297             : 
     298      250396 :                     if(::basegfx::fTools::equalZero(fValBB))
     299             :                     {
     300           0 :                         return false;
     301             :                     }
     302             : 
     303      250396 :                     if(b != (RowSize - 1))
     304             :                     {
     305      174289 :                         fDum = 1.0 / get(b, b);
     306             : 
     307      468835 :                         for(a = b + 1; a < RowSize; a++)
     308             :                         {
     309      294546 :                             set(a, b, get(a, b) * fDum);
     310             :                         }
     311             :                     }
     312             :                 }
     313             : 
     314       76107 :                 return true;
     315             :             }
     316             : 
     317      239712 :             void lubksb(const sal_uInt16 nIndex[], double fRow[]) const
     318             :             {
     319             :                 sal_uInt16 b, ip;
     320      239712 :                 sal_Int16 a, a2 = -1;
     321             :                 double fSum;
     322             : 
     323     1036464 :                 for(a = 0; a < RowSize; a++)
     324             :                 {
     325      796752 :                     ip = nIndex[a];
     326      796752 :                     fSum = fRow[ip];
     327      796752 :                     fRow[ip] = fRow[a];
     328             : 
     329      796752 :                     if(a2 >= 0)
     330             :                     {
     331      688688 :                         for(b = a2; b < a; b++)
     332             :                         {
     333      410168 :                             fSum -= get(a, b) * fRow[b];
     334             :                         }
     335             :                     }
     336      518232 :                     else if(!::basegfx::fTools::equalZero(fSum))
     337             :                     {
     338      239712 :                         a2 = a;
     339             :                     }
     340             : 
     341      796752 :                     fRow[a] = fSum;
     342             :                 }
     343             : 
     344     1036464 :                 for(a = (RowSize - 1); a >= 0; a--)
     345             :                 {
     346      796752 :                     fSum = fRow[a];
     347             : 
     348     1748736 :                     for(b = a + 1; b < RowSize; b++)
     349             :                     {
     350      951984 :                         fSum -= get(a, b) * fRow[b];
     351             :                     }
     352             : 
     353      796752 :                     const double fValueAA(get(a, a));
     354             : 
     355      796752 :                     if(!::basegfx::fTools::equalZero(fValueAA))
     356             :                     {
     357      796752 :                         fRow[a] = fSum / get(a, a);
     358             :                     }
     359             :                 }
     360      239712 :             }
     361             : 
     362     2465092 :             bool isIdentity() const
     363             :             {
     364             :                 // last line needs no testing if not existing
     365             :                 const sal_uInt16 nMaxLine(
     366     2465092 :                     sal::static_int_cast<sal_uInt16>(mpLine ? RowSize : (RowSize - 1)) );
     367             : 
     368     2772887 :                 for(sal_uInt16 a(0); a < nMaxLine; a++)
     369             :                 {
     370     4706821 :                     for(sal_uInt16 b(0); b < RowSize; b++)
     371             :                     {
     372     4399026 :                         const double fDefault(implGetDefaultValue(a, b));
     373     4399026 :                         const double fValueAB(get(a, b));
     374             : 
     375     4399026 :                         if(!::basegfx::fTools::equal(fDefault, fValueAB))
     376             :                         {
     377     2435908 :                             return false;
     378             :                         }
     379             :                     }
     380             :                 }
     381             : 
     382       29184 :                 return true;
     383             :             }
     384             : 
     385           0 :             bool isInvertible() const
     386             :             {
     387           0 :                 ImplHomMatrixTemplate aWork(*this);
     388             :                 sal_uInt16 nIndex[RowSize];
     389             :                 sal_Int16 nParity;
     390             : 
     391           0 :                 return aWork.ludcmp(nIndex, nParity);
     392             :             }
     393             : 
     394             :             bool isNormalized() const
     395             :             {
     396             :                 if(!mpLine)
     397             :                     return true;
     398             : 
     399             :                 const double fHomValue(get((RowSize - 1), (RowSize - 1)));
     400             : 
     401             :                 if(::basegfx::fTools::equalZero(fHomValue))
     402             :                 {
     403             :                     return true;
     404             :                 }
     405             : 
     406             :                 const double fOne(1.0);
     407             : 
     408             :                 if(::basegfx::fTools::equal(fOne, fHomValue))
     409             :                 {
     410             :                     return true;
     411             :                 }
     412             : 
     413             :                 return false;
     414             :             }
     415             : 
     416       73436 :             void doInvert(const ImplHomMatrixTemplate& rWork, const sal_uInt16 nIndex[])
     417             :             {
     418             :                 double fArray[RowSize];
     419             : 
     420      313148 :                 for(sal_uInt16 a(0); a < RowSize; a++)
     421             :                 {
     422             :                     // prepare line
     423             :             sal_uInt16 b;
     424     1036464 :                     for( b = 0; b < RowSize; b++)
     425             :                     {
     426      796752 :                         fArray[b] = implGetDefaultValue(a, b);
     427             :                     }
     428             : 
     429             :                     // expand line
     430      239712 :                     rWork.lubksb(nIndex, fArray);
     431             : 
     432             :                     // copy line transposed to this matrix
     433     1036464 :                     for( b = 0; b < RowSize; b++)
     434             :                     {
     435      796752 :                         set(b, a, fArray[b]);
     436             :                     }
     437             :                 }
     438             : 
     439             :                 // evtl. get rid of last matrix line
     440       73436 :                 testLastLine();
     441       73436 :             }
     442             : 
     443             :             void doNormalize()
     444             :             {
     445             :                 if(mpLine)
     446             :                 {
     447             :                     const double fHomValue(get((RowSize - 1), (RowSize - 1)));
     448             : 
     449             :                     for(sal_uInt16 a(0); a < RowSize; a++)
     450             :                     {
     451             :                         for(sal_uInt16 b(0); b < RowSize; b++)
     452             :                         {
     453             :                             set(a, b, get(a, b) / fHomValue);
     454             :                         }
     455             :                     }
     456             : 
     457             :                     // evtl. get rid of last matrix line
     458             :                     testLastLine();
     459             :                 }
     460             :             }
     461             : 
     462        2671 :             double doDeterminant() const
     463             :             {
     464        2671 :                 ImplHomMatrixTemplate aWork(*this);
     465             :                 sal_uInt16 nIndex[RowSize];
     466             :                 sal_Int16 nParity;
     467        2671 :                 double fRetval(0.0);
     468             : 
     469        2671 :                 if(aWork.ludcmp(nIndex, nParity))
     470             :                 {
     471        2671 :                     fRetval = (double)nParity;
     472             : 
     473             :                     // last line needs no multiply if not existing; default value would be 1.
     474             :                     const sal_uInt16 nMaxLine(
     475        2671 :                         sal::static_int_cast<sal_uInt16>(aWork.mpLine ? RowSize : (RowSize - 1)) );
     476             : 
     477       10684 :                     for(sal_uInt16 a(0); a < nMaxLine; a++)
     478             :                     {
     479        8013 :                         fRetval *= aWork.get(a, a);
     480             :                     }
     481             :                 }
     482             : 
     483        2671 :                 return fRetval;
     484             :             }
     485             : 
     486             :             double doTrace() const
     487             :             {
     488             :                 double fTrace = (mpLine) ? 0.0 : 1.0;
     489             :                 const sal_uInt16 nMaxLine(
     490             :                     sal::static_int_cast<sal_uInt16>(mpLine ? RowSize : (RowSize - 1)) );
     491             : 
     492             :                 for(sal_uInt16 a(0); a < nMaxLine; a++)
     493             :                 {
     494             :                     fTrace += get(a, a);
     495             :                 }
     496             : 
     497             :                 return fTrace;
     498             :             }
     499             : 
     500             :             void doTranspose()
     501             :             {
     502             :                 for(sal_uInt16 a(0); a < (RowSize - 1); a++)
     503             :                 {
     504             :                     for(sal_uInt16 b(a + 1); b < RowSize; b++)
     505             :                     {
     506             :                         const double fTemp(get(a, b));
     507             :                         set(a, b, get(b, a));
     508             :                         set(b, a, fTemp);
     509             :                     }
     510             :                 }
     511             : 
     512             :                 testLastLine();
     513             :             }
     514             : 
     515           0 :             void doAddMatrix(const ImplHomMatrixTemplate& rMat)
     516             :             {
     517           0 :                 for(sal_uInt16 a(0); a < RowSize; a++)
     518             :                 {
     519           0 :                     for(sal_uInt16 b(0); b < RowSize; b++)
     520             :                     {
     521           0 :                         set(a, b, get(a, b) + rMat.get(a, b));
     522             :                     }
     523             :                 }
     524             : 
     525           0 :                 testLastLine();
     526           0 :             }
     527             : 
     528           0 :             void doSubMatrix(const ImplHomMatrixTemplate& rMat)
     529             :             {
     530           0 :                 for(sal_uInt16 a(0); a < RowSize; a++)
     531             :                 {
     532           0 :                     for(sal_uInt16 b(0); b < RowSize; b++)
     533             :                     {
     534           0 :                         set(a, b, get(a, b) - rMat.get(a, b));
     535             :                     }
     536             :                 }
     537             : 
     538           0 :                 testLastLine();
     539           0 :             }
     540             : 
     541           0 :             void doMulMatrix(const double& rfValue)
     542             :             {
     543           0 :                 for(sal_uInt16 a(0); a < RowSize; a++)
     544             :                 {
     545           0 :                     for(sal_uInt16 b(0); b < RowSize; b++)
     546             :                     {
     547           0 :                         set(a, b, get(a, b) * rfValue);
     548             :                     }
     549             :                 }
     550             : 
     551           0 :                 testLastLine();
     552           0 :             }
     553             : 
     554      944418 :             void doMulMatrix(const ImplHomMatrixTemplate& rMat)
     555             :             {
     556             :                 // create a copy as source for the original values
     557      944418 :                 const ImplHomMatrixTemplate aCopy(*this);
     558             : 
     559             :                 // TODO: maybe optimize cases where last line is [0 0 1].
     560             : 
     561      944418 :                 double fValue(0.0);
     562             : 
     563     4112032 :                 for(sal_uInt16 a(0); a < RowSize; ++a)
     564             :                 {
     565    14007896 :                     for(sal_uInt16 b(0); b < RowSize; ++b)
     566             :                     {
     567    10840282 :                         fValue = 0.0;
     568             : 
     569    48710888 :                         for(sal_uInt16 c(0); c < RowSize; ++c)
     570    37870606 :                             fValue += aCopy.get(c, b) * rMat.get(a, c);
     571             : 
     572    10840282 :                         set(a, b, fValue);
     573             :                     }
     574             :                 }
     575             : 
     576      944418 :                 testLastLine();
     577      944418 :             }
     578             : 
     579       47195 :             bool isEqual(const ImplHomMatrixTemplate& rMat) const
     580             :             {
     581             :                 const sal_uInt16 nMaxLine(
     582       47195 :                     sal::static_int_cast<sal_uInt16>((mpLine || rMat.mpLine) ? RowSize : (RowSize - 1)) );
     583             : 
     584      123421 :                 for(sal_uInt16 a(0); a < nMaxLine; a++)
     585             :                 {
     586      351690 :                     for(sal_uInt16 b(0); b < RowSize; b++)
     587             :                     {
     588      275464 :                         const double fValueA(get(a, b));
     589      275464 :                         const double fValueB(rMat.get(a, b));
     590             : 
     591      275464 :                         if(!::basegfx::fTools::equal(fValueA, fValueB))
     592             :                         {
     593       12996 :                             return false;
     594             :                         }
     595             :                     }
     596             :                 }
     597             : 
     598       34199 :                 return true;
     599             :             }
     600             :         };
     601             : 
     602             :     } // namespace internal
     603             : } // namespace basegfx
     604             : 
     605             : #endif // INCLUDED_BASEGFX_SOURCE_INC_HOMMATRIXTEMPLATE_HXX
     606             : 
     607             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10