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

Generated by: LCOV version 1.10