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

Generated by: LCOV version 1.10