LCOV - code coverage report
Current view: top level - sc/source/core/tool - formulagroup.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 73 266 27.4 %
Date: 2015-06-13 12:38:46 Functions: 17 32 53.1 %
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             : 
      10             : #include <config_features.h>
      11             : 
      12             : #include "formulagroup.hxx"
      13             : #include "formulagroupcl.hxx"
      14             : #include "document.hxx"
      15             : #include "formulacell.hxx"
      16             : #include "tokenarray.hxx"
      17             : #include "compiler.hxx"
      18             : #include "interpre.hxx"
      19             : #include "scmatrix.hxx"
      20             : #include "globalnames.hxx"
      21             : 
      22             : #include <formula/vectortoken.hxx>
      23             : #include <officecfg/Office/Common.hxx>
      24             : #if HAVE_FEATURE_OPENCL
      25             : #include <opencl/platforminfo.hxx>
      26             : #endif
      27             : #include <rtl/bootstrap.hxx>
      28             : 
      29             : #include <cstdio>
      30             : #include <unordered_map>
      31             : #include <vector>
      32             : 
      33             : #if HAVE_FEATURE_OPENCL
      34             : #include <opencl/openclwrapper.hxx>
      35             : #endif
      36             : 
      37             : namespace sc {
      38             : 
      39          67 : FormulaGroupEntry::FormulaGroupEntry( ScFormulaCell** pCells, size_t nRow, size_t nLength ) :
      40          67 :     mpCells(pCells), mnRow(nRow), mnLength(nLength), mbShared(true) {}
      41             : 
      42         225 : FormulaGroupEntry::FormulaGroupEntry( ScFormulaCell* pCell, size_t nRow ) :
      43         225 :     mpCell(pCell), mnRow(nRow), mnLength(0), mbShared(false) {}
      44             : 
      45          51 : size_t FormulaGroupContext::ColKey::Hash::operator ()( const FormulaGroupContext::ColKey& rKey ) const
      46             : {
      47          51 :     return rKey.mnTab * MAXCOLCOUNT + rKey.mnCol;
      48             : }
      49             : 
      50          51 : FormulaGroupContext::ColKey::ColKey( SCTAB nTab, SCCOL nCol ) : mnTab(nTab), mnCol(nCol) {}
      51             : 
      52          14 : bool FormulaGroupContext::ColKey::operator== ( const ColKey& r ) const
      53             : {
      54          14 :     return mnTab == r.mnTab && mnCol == r.mnCol;
      55             : }
      56             : 
      57           0 : bool FormulaGroupContext::ColKey::operator!= ( const ColKey& r ) const
      58             : {
      59           0 :     return !operator==(r);
      60             : }
      61             : 
      62          17 : FormulaGroupContext::ColArray::ColArray( NumArrayType* pNumArray, StrArrayType* pStrArray ) :
      63          17 :     mpNumArray(pNumArray), mpStrArray(pStrArray), mnSize(0)
      64             : {
      65          17 :     if (mpNumArray)
      66          13 :         mnSize = mpNumArray->size();
      67           4 :     else if (mpStrArray)
      68           4 :         mnSize = mpStrArray->size();
      69          17 : }
      70             : 
      71          22 : FormulaGroupContext::ColArray* FormulaGroupContext::getCachedColArray( SCTAB nTab, SCCOL nCol, size_t nSize )
      72             : {
      73          22 :     ColArraysType::iterator itColArray = maColArrays.find(ColKey(nTab, nCol));
      74          22 :     if (itColArray == maColArrays.end())
      75             :         // Not cached for this column.
      76          13 :         return NULL;
      77             : 
      78           9 :     ColArray& rCached = itColArray->second;
      79           9 :     if (nSize > rCached.mnSize)
      80             :         // Cached data array is not long enough for the requested range.
      81           5 :         return NULL;
      82             : 
      83           4 :     return &rCached;
      84             : }
      85             : 
      86          17 : FormulaGroupContext::ColArray* FormulaGroupContext::setCachedColArray(
      87             :     SCTAB nTab, SCCOL nCol, NumArrayType* pNumArray, StrArrayType* pStrArray )
      88             : {
      89          17 :     ColArraysType::iterator it = maColArrays.find(ColKey(nTab, nCol));
      90          17 :     if (it == maColArrays.end())
      91             :     {
      92             :         std::pair<ColArraysType::iterator,bool> r =
      93             :             maColArrays.insert(
      94          12 :                 ColArraysType::value_type(ColKey(nTab, nCol), ColArray(pNumArray, pStrArray)));
      95             : 
      96          12 :         if (!r.second)
      97             :             // Somehow the insertion failed.
      98           0 :             return NULL;
      99             : 
     100          12 :         return &r.first->second;
     101             :     }
     102             : 
     103             :     // Prior array exists for this column. Overwrite it.
     104           5 :     ColArray& rArray = it->second;
     105           5 :     rArray = ColArray(pNumArray, pStrArray);
     106           5 :     return &rArray;
     107             : }
     108             : 
     109           6 : void FormulaGroupContext::ensureStrArray( ColArray& rColArray, size_t nArrayLen )
     110             : {
     111           6 :     if (rColArray.mpStrArray)
     112           7 :         return;
     113             : 
     114             :     maStrArrays.push_back(
     115           5 :         new sc::FormulaGroupContext::StrArrayType(nArrayLen, NULL));
     116           5 :     rColArray.mpStrArray = &maStrArrays.back();
     117             : }
     118             : 
     119          14 : void FormulaGroupContext::ensureNumArray( ColArray& rColArray, size_t nArrayLen )
     120             : {
     121          14 :     if (rColArray.mpNumArray)
     122          27 :         return;
     123             : 
     124             :     double fNan;
     125           1 :     rtl::math::setNan(&fNan);
     126             : 
     127             :     maNumArrays.push_back(
     128           1 :         new sc::FormulaGroupContext::NumArrayType(nArrayLen, fNan));
     129           1 :     rColArray.mpNumArray = &maNumArrays.back();
     130             : }
     131             : 
     132           8 : FormulaGroupContext::FormulaGroupContext()
     133             : {
     134           8 : }
     135             : 
     136           8 : FormulaGroupContext::~FormulaGroupContext()
     137             : {
     138           8 : }
     139             : 
     140             : namespace {
     141             : 
     142             : /**
     143             :  * Input double array consists of segments of NaN's and normal values.
     144             :  * Insert only the normal values into the matrix while skipping the NaN's.
     145             :  */
     146           0 : void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen )
     147             : {
     148           0 :     const double* pNum = pNums;
     149           0 :     const double* pNumEnd = pNum + nLen;
     150           0 :     const double* pNumHead = NULL;
     151           0 :     for (; pNum != pNumEnd; ++pNum)
     152             :     {
     153           0 :         if (!rtl::math::isNan(*pNum))
     154             :         {
     155           0 :             if (!pNumHead)
     156             :                 // Store the first non-NaN position.
     157           0 :                 pNumHead = pNum;
     158             : 
     159           0 :             continue;
     160             :         }
     161             : 
     162           0 :         if (pNumHead)
     163             :         {
     164             :             // Flush this non-NaN segment to the matrix.
     165           0 :             rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums);
     166           0 :             pNumHead = NULL;
     167             :         }
     168             :     }
     169             : 
     170           0 :     if (pNumHead)
     171             :     {
     172             :         // Flush last non-NaN segment to the matrix.
     173           0 :         rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums);
     174             :     }
     175           0 : }
     176             : 
     177           0 : void flushStrSegment(
     178             :     ScMatrix& rMat, size_t nCol, rtl_uString** pHead, rtl_uString** pCur, rtl_uString** pTop )
     179             : {
     180           0 :     size_t nOffset = pHead - pTop;
     181           0 :     std::vector<svl::SharedString> aStrs;
     182           0 :     aStrs.reserve(pCur - pHead);
     183           0 :     for (; pHead != pCur; ++pHead)
     184           0 :         aStrs.push_back(svl::SharedString(*pHead, *pHead));
     185             : 
     186           0 :     rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset);
     187           0 : }
     188             : 
     189           0 : void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen )
     190             : {
     191           0 :     rtl_uString** p = pStrs;
     192           0 :     rtl_uString** pEnd = p + nLen;
     193           0 :     rtl_uString** pHead = NULL;
     194           0 :     for (; p != pEnd; ++p)
     195             :     {
     196           0 :         if (*p)
     197             :         {
     198           0 :             if (!pHead)
     199             :                 // Store the first non-empty string position.
     200           0 :                 pHead = p;
     201             : 
     202           0 :             continue;
     203             :         }
     204             : 
     205           0 :         if (pHead)
     206             :         {
     207             :             // Flush this non-empty segment to the matrix.
     208           0 :             flushStrSegment(rMat, nCol, pHead, p, pStrs);
     209           0 :             pHead = NULL;
     210             :         }
     211             :     }
     212             : 
     213           0 :     if (pHead)
     214             :     {
     215             :         // Flush last non-empty segment to the matrix.
     216           0 :         flushStrSegment(rMat, nCol, pHead, p, pStrs);
     217             :     }
     218           0 : }
     219             : 
     220           0 : void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, rtl_uString** pStrs, size_t nLen )
     221             : {
     222           0 :     if (!pStrs)
     223             :     {
     224           0 :         fillMatrix(rMat, nCol, pNums, nLen);
     225           0 :         return;
     226             :     }
     227             : 
     228           0 :     const double* pNum = pNums;
     229           0 :     const double* pNumHead = NULL;
     230           0 :     rtl_uString** pStr = pStrs;
     231           0 :     rtl_uString** pStrEnd = pStr + nLen;
     232           0 :     rtl_uString** pStrHead = NULL;
     233             : 
     234           0 :     for (; pStr != pStrEnd; ++pStr, ++pNum)
     235             :     {
     236           0 :         if (*pStr)
     237             :         {
     238             :             // String cell exists.
     239             : 
     240           0 :             if (pNumHead)
     241             :             {
     242             :                 // Flush this numeric segment to the matrix.
     243           0 :                 rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums);
     244           0 :                 pNumHead = NULL;
     245             :             }
     246             : 
     247           0 :             if (!pStrHead)
     248             :                 // Store the first non-empty string position.
     249           0 :                 pStrHead = pStr;
     250             : 
     251           0 :             continue;
     252             :         }
     253             : 
     254             :         // No string cell. Check the numeric cell value.
     255             : 
     256           0 :         if (pStrHead)
     257             :         {
     258             :             // Flush this non-empty string segment to the matrix.
     259           0 :             flushStrSegment(rMat, nCol, pStrHead, pStr, pStrs);
     260           0 :             pStrHead = NULL;
     261             :         }
     262             : 
     263           0 :         if (!rtl::math::isNan(*pNum))
     264             :         {
     265             :             // Numeric cell exists.
     266           0 :             if (!pNumHead)
     267             :                 // Store the first non-NaN position.
     268           0 :                 pNumHead = pNum;
     269             : 
     270           0 :             continue;
     271             :         }
     272             : 
     273             :         // Empty cell. No action required.
     274             :     }
     275             : 
     276           0 :     if (pStrHead)
     277             :     {
     278             :         // Flush the last non-empty segment to the matrix.
     279           0 :         flushStrSegment(rMat, nCol, pStrHead, pStr, pStrs);
     280             :     }
     281           0 :     else if (pNumHead)
     282             :     {
     283             :         // Flush the last numeric segment to the matrix.
     284           0 :         rMat.PutDouble(pNumHead, pNum - pNumHead, nCol, pNumHead - pNums);
     285             :     }
     286             : }
     287             : 
     288             : }
     289             : 
     290           0 : CompiledFormula::CompiledFormula() {}
     291             : 
     292           0 : CompiledFormula::~CompiledFormula() {}
     293             : 
     294           0 : FormulaGroupInterpreterSoftware::FormulaGroupInterpreterSoftware() : FormulaGroupInterpreter()
     295             : {
     296           0 : }
     297             : 
     298           0 : ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
     299             : {
     300           0 :     return ScMatrixRef();
     301             : }
     302             : 
     303           0 : CompiledFormula* FormulaGroupInterpreterSoftware::createCompiledFormula(
     304             :     ScFormulaCellGroup& /*rGroup*/, ScTokenArray& /*rCode*/ )
     305             : {
     306           0 :     return NULL;
     307             : }
     308             : 
     309           0 : bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
     310             :                                                 ScFormulaCellGroupRef& xGroup,
     311             :                                                 ScTokenArray& rCode)
     312             : {
     313             :     typedef std::unordered_map<const formula::FormulaToken*, formula::FormulaTokenRef> CachedTokensType;
     314             : 
     315             :     // Decompose the group into individual cells and calculate them individually.
     316             : 
     317             :     // The caller must ensure that the top position is the start position of
     318             :     // the group.
     319             : 
     320           0 :     ScAddress aTmpPos = rTopPos;
     321           0 :     std::vector<formula::FormulaTokenRef> aResults;
     322           0 :     aResults.reserve(xGroup->mnLength);
     323           0 :     CachedTokensType aCachedTokens;
     324             : 
     325             :     double fNan;
     326           0 :     rtl::math::setNan(&fNan);
     327             : 
     328           0 :     for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow())
     329             :     {
     330           0 :         ScTokenArray aCode2;
     331           0 :         for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
     332             :         {
     333           0 :             CachedTokensType::iterator it = aCachedTokens.find(p);
     334           0 :             if (it != aCachedTokens.end())
     335             :             {
     336             :                 // This token is cached. Use the cached one.
     337           0 :                 aCode2.AddToken(*it->second);
     338           0 :                 continue;
     339             :             }
     340             : 
     341           0 :             switch (p->GetType())
     342             :             {
     343             :                 case formula::svSingleVectorRef:
     344             :                 {
     345           0 :                     const formula::SingleVectorRefToken* p2 = static_cast<const formula::SingleVectorRefToken*>(p);
     346           0 :                     const formula::VectorRefArray& rArray = p2->GetArray();
     347             : 
     348           0 :                     rtl_uString* pStr = NULL;
     349           0 :                     double fVal = fNan;
     350           0 :                     if (static_cast<size_t>(i) < p2->GetArrayLength())
     351             :                     {
     352           0 :                         if (rArray.mpStringArray)
     353             :                             // See if the cell is of string type.
     354           0 :                             pStr = rArray.mpStringArray[i];
     355             : 
     356           0 :                         if (!pStr && rArray.mpNumericArray)
     357           0 :                             fVal = rArray.mpNumericArray[i];
     358             :                     }
     359             : 
     360           0 :                     if (pStr)
     361             :                     {
     362             :                         // This is a string cell.
     363           0 :                         svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
     364           0 :                         aCode2.AddString(rPool.intern(OUString(pStr)));
     365             :                     }
     366           0 :                     else if (rtl::math::isNan(fVal))
     367             :                         // Value of NaN represents an empty cell.
     368           0 :                         aCode2.AddToken(ScEmptyCellToken(false, false));
     369             :                     else
     370             :                         // Numeric cell.
     371           0 :                         aCode2.AddDouble(fVal);
     372             :                 }
     373           0 :                 break;
     374             :                 case formula::svDoubleVectorRef:
     375             :                 {
     376           0 :                     const formula::DoubleVectorRefToken* p2 = static_cast<const formula::DoubleVectorRefToken*>(p);
     377           0 :                     const std::vector<formula::VectorRefArray>& rArrays = p2->GetArrays();
     378           0 :                     size_t nColSize = rArrays.size();
     379           0 :                     size_t nRowStart = p2->IsStartFixed() ? 0 : i;
     380           0 :                     size_t nRowEnd = p2->GetRefRowSize() - 1;
     381           0 :                     if (!p2->IsEndFixed())
     382           0 :                         nRowEnd += i;
     383           0 :                     size_t nRowSize = nRowEnd - nRowStart + 1;
     384           0 :                     ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize));
     385             : 
     386           0 :                     size_t nDataRowEnd = p2->GetArrayLength() - 1;
     387           0 :                     if (nRowStart > nDataRowEnd)
     388             :                         // Referenced rows are all empty.
     389           0 :                         nRowSize = 0;
     390           0 :                     else if (nRowEnd > nDataRowEnd)
     391             :                         // Data array is shorter than the row size of the reference. Truncate it to the data.
     392           0 :                         nRowSize -= nRowEnd - nDataRowEnd;
     393             : 
     394           0 :                     for (size_t nCol = 0; nCol < nColSize; ++nCol)
     395             :                     {
     396           0 :                         const formula::VectorRefArray& rArray = rArrays[nCol];
     397           0 :                         if (rArray.mpStringArray)
     398             :                         {
     399           0 :                             if (rArray.mpNumericArray)
     400             :                             {
     401             :                                 // Mixture of string and numeric values.
     402           0 :                                 const double* pNums = rArray.mpNumericArray;
     403           0 :                                 pNums += nRowStart;
     404           0 :                                 rtl_uString** pStrs = rArray.mpStringArray;
     405           0 :                                 pStrs += nRowStart;
     406           0 :                                 fillMatrix(*pMat, nCol, pNums, pStrs, nRowSize);
     407             :                             }
     408             :                             else
     409             :                             {
     410             :                                 // String cells only.
     411           0 :                                 rtl_uString** pStrs = rArray.mpStringArray;
     412           0 :                                 pStrs += nRowStart;
     413           0 :                                 fillMatrix(*pMat, nCol, pStrs, nRowSize);
     414             :                             }
     415             :                         }
     416           0 :                         else if (rArray.mpNumericArray)
     417             :                         {
     418             :                             // Numeric cells only.
     419           0 :                             const double* pNums = rArray.mpNumericArray;
     420           0 :                             pNums += nRowStart;
     421           0 :                             fillMatrix(*pMat, nCol, pNums, nRowSize);
     422             :                         }
     423             :                     }
     424             : 
     425           0 :                     if (p2->IsStartFixed() && p2->IsEndFixed())
     426             :                     {
     427             :                         // Cached the converted token for absolute range referene.
     428             :                         ScComplexRefData aRef;
     429           0 :                         ScRange aRefRange = rTopPos;
     430           0 :                         aRefRange.aEnd.SetRow(rTopPos.Row() + nRowEnd);
     431           0 :                         aRef.InitRange(aRefRange);
     432           0 :                         formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
     433           0 :                         aCachedTokens.insert(CachedTokensType::value_type(p, xTok));
     434           0 :                         aCode2.AddToken(*xTok);
     435             :                     }
     436             :                     else
     437             :                     {
     438           0 :                         ScMatrixToken aTok(pMat);
     439           0 :                         aCode2.AddToken(aTok);
     440           0 :                     }
     441             :                 }
     442           0 :                 break;
     443             :                 default:
     444           0 :                     aCode2.AddToken(*p);
     445             :             }
     446             :         }
     447             : 
     448           0 :         ScFormulaCell* pDest = rDoc.GetFormulaCell(aTmpPos);
     449           0 :         if (!pDest)
     450           0 :             return false;
     451             : 
     452           0 :         ScCompiler aComp(&rDoc, aTmpPos, aCode2);
     453           0 :         aComp.CompileTokenArray();
     454           0 :         ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2);
     455           0 :         aInterpreter.Interpret();
     456           0 :         aResults.push_back(aInterpreter.GetResultToken());
     457           0 :     } // for loop end (xGroup->mnLength)
     458             : 
     459           0 :     if (!aResults.empty())
     460           0 :         rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
     461             : 
     462           0 :     return true;
     463             : }
     464             : 
     465             : FormulaGroupInterpreter *FormulaGroupInterpreter::msInstance = NULL;
     466             : 
     467           0 : void FormulaGroupInterpreter::MergeCalcConfig(const ScDocument& rDoc)
     468             : {
     469           0 :     maCalcConfig = ScInterpreter::GetGlobalConfig();
     470           0 :     maCalcConfig.MergeDocumentSpecific(rDoc.GetCalcConfig());
     471           0 : }
     472             : 
     473             : /// load and/or configure the correct formula group interpreter
     474           1 : FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic()
     475             : {
     476           1 :     if ( !msInstance )
     477             :     {
     478             : #if HAVE_FEATURE_OPENCL
     479           1 :         const ScCalcConfig& rConfig = ScInterpreter::GetGlobalConfig();
     480           1 :         if (officecfg::Office::Common::Misc::UseOpenCL::get())
     481           1 :             switchOpenCLDevice(rConfig.maOpenCLDevice, rConfig.mbOpenCLAutoSelect, false);
     482             : #endif
     483           1 :         static bool bAllowSoftwareInterpreter = (getenv("SC_ALLOW_BROKEN_SOFTWARE_INTERPRETER") != NULL);
     484             : 
     485           1 :         if ( !msInstance && bAllowSoftwareInterpreter ) // software fallback
     486             :         {
     487             :             SAL_INFO("sc.formulagroup", "Create S/W interpreter");
     488           0 :             msInstance = new sc::FormulaGroupInterpreterSoftware();
     489             :         }
     490             :     }
     491             : 
     492           1 :     return msInstance;
     493             : }
     494             : 
     495             : #if HAVE_FEATURE_OPENCL
     496           0 : void FormulaGroupInterpreter::fillOpenCLInfo(std::vector<OpenCLPlatformInfo>& rPlatforms)
     497             : {
     498             :     const std::vector<OpenCLPlatformInfo>& rPlatformsFromWrapper =
     499           0 :         ::opencl::fillOpenCLInfo();
     500             : 
     501           0 :     rPlatforms.assign(rPlatformsFromWrapper.begin(), rPlatformsFromWrapper.end());
     502           0 : }
     503             : 
     504         224 : bool FormulaGroupInterpreter::switchOpenCLDevice(const OUString& rDeviceId, bool bAutoSelect, bool bForceEvaluation)
     505             : {
     506         224 :     bool bOpenCLEnabled = officecfg::Office::Common::Misc::UseOpenCL::get();
     507         224 :     static bool bAllowSoftwareInterpreter = (getenv("SC_ALLOW_BROKEN_SOFTWARE_INTERPRETER") != NULL);
     508         224 :     if (!bOpenCLEnabled || (bAllowSoftwareInterpreter && rDeviceId == OPENCL_SOFTWARE_DEVICE_CONFIG_NAME))
     509             :     {
     510           0 :         if(msInstance)
     511             :         {
     512             :             // if we already have a software interpreter don't delete it
     513           0 :             if(dynamic_cast<sc::FormulaGroupInterpreterSoftware*>(msInstance))
     514           0 :                 return true;
     515             : 
     516           0 :             delete msInstance;
     517             :         }
     518             : 
     519           0 :         msInstance = new sc::FormulaGroupInterpreterSoftware();
     520           0 :         return true;
     521             :     }
     522         224 :     bool bSuccess = ::opencl::switchOpenCLDevice(&rDeviceId, bAutoSelect, bForceEvaluation);
     523         224 :     if(!bSuccess)
     524         224 :         return false;
     525             : 
     526           0 :     delete msInstance;
     527           0 :     msInstance = NULL;
     528             : 
     529           0 :     if ( officecfg::Office::Common::Misc::UseOpenCL::get() )
     530             :     {
     531           0 :         msInstance = new sc::opencl::FormulaGroupInterpreterOpenCL();
     532           0 :         return msInstance != NULL;
     533             :     }
     534             : 
     535           0 :     return false;
     536             : }
     537             : 
     538           0 : void FormulaGroupInterpreter::getOpenCLDeviceInfo(sal_Int32& rDeviceId, sal_Int32& rPlatformId)
     539             : {
     540           0 :     rDeviceId = -1;
     541           0 :     rPlatformId = -1;
     542           0 :     bool bOpenCLEnabled = officecfg::Office::Common::Misc::UseOpenCL::get();
     543           0 :     if(!bOpenCLEnabled)
     544           0 :         return;
     545             : 
     546           0 :     size_t aDeviceId = static_cast<size_t>(-1);
     547           0 :     size_t aPlatformId = static_cast<size_t>(-1);
     548             : 
     549           0 :     ::opencl::getOpenCLDeviceInfo(aDeviceId, aPlatformId);
     550           0 :     rDeviceId = aDeviceId;
     551           0 :     rPlatformId = aPlatformId;
     552             : }
     553             : 
     554         223 : void FormulaGroupInterpreter::enableOpenCL_UnitTestsOnly()
     555             : {
     556         223 :     std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
     557         223 :     officecfg::Office::Common::Misc::UseOpenCL::set(true, batch);
     558         223 :     batch->commit();
     559             : 
     560         446 :     ScCalcConfig aConfig = ScInterpreter::GetGlobalConfig();
     561             : 
     562         223 :     aConfig.mbOpenCLSubsetOnly = false;
     563         223 :     aConfig.mnOpenCLMinimumFormulaGroupSize = 2;
     564             : 
     565         446 :     ScInterpreter::SetGlobalConfig(aConfig);
     566         223 : }
     567             : 
     568             : #endif
     569             : 
     570         156 : } // namespace sc
     571             : 
     572             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11