LCOV - code coverage report
Current view: top level - sc/source/ui/optdlg - calcoptionsdlg.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 0 388 0.0 %
Date: 2015-06-13 12:38:46 Functions: 0 126 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 <sal/config.h>
      11             : 
      12             : #include <algorithm>
      13             : #include <cmath>
      14             : 
      15             : #include "calcconfig.hxx"
      16             : #include "calcoptionsdlg.hxx"
      17             : #include "docfunc.hxx"
      18             : #include "docsh.hxx"
      19             : #include "interpre.hxx"
      20             : #include "sc.hrc"
      21             : #include "scresid.hxx"
      22             : #include "scopetools.hxx"
      23             : #include "viewdata.hxx"
      24             : 
      25             : #include <com/sun/star/frame/Desktop.hpp>
      26             : #include <com/sun/star/frame/XDesktop2.hpp>
      27             : 
      28             : #include <comphelper/random.hxx>
      29             : #include <svtools/svlbitm.hxx>
      30             : #include <svtools/treelistentry.hxx>
      31             : 
      32             : #if HAVE_FEATURE_OPENCL
      33             : #include "formulagroup.hxx"
      34             : #include "globalnames.hxx"
      35             : #endif
      36             : 
      37             : namespace {
      38             : 
      39           0 : formula::FormulaGrammar::AddressConvention toAddressConvention(sal_Int32 nPos)
      40             : {
      41           0 :     switch (nPos)
      42             :     {
      43             :         case 1:
      44           0 :             return formula::FormulaGrammar::CONV_OOO;
      45             :         case 2:
      46           0 :             return formula::FormulaGrammar::CONV_XL_A1;
      47             :         case 3:
      48           0 :             return formula::FormulaGrammar::CONV_XL_R1C1;
      49             :         case 0:
      50             :         default:
      51             :             ;
      52             :     }
      53             : 
      54           0 :     return formula::FormulaGrammar::CONV_UNSPECIFIED;
      55             : }
      56             : 
      57             : }
      58             : 
      59           0 : ScCalcOptionsDialog::ScCalcOptionsDialog(vcl::Window* pParent, const ScCalcConfig& rConfig)
      60             :     : ModalDialog(pParent, "FormulaCalculationOptions",
      61             :         "modules/scalc/ui/formulacalculationoptions.ui")
      62             :     , maConfig(rConfig)
      63           0 :     , mbSelectedEmptyStringAsZero(rConfig.mbEmptyStringAsZero)
      64             : {
      65           0 :     get(mpTestButton, "test");
      66           0 :     get(mpOpenclInfoList, "opencl_list");
      67           0 :     get(mpBtnAutomaticSelectionTrue, "automatic_select_true");
      68           0 :     get(mpBtnAutomaticSelectionFalse, "automatic_select_false");
      69           0 :     get(mpFtFrequency, "frequency");
      70           0 :     get(mpFtComputeUnits, "compute_units");
      71           0 :     get(mpFtMemory, "memory");
      72             : 
      73           0 :     get(mpConversion,"comboConversion");
      74           0 :     mpConversion->SelectEntryPos(static_cast<sal_Int32>(rConfig.meStringConversion), true);
      75           0 :     mpConversion->SetSelectHdl(LINK(this, ScCalcOptionsDialog, ConversionModifiedHdl));
      76             : 
      77           0 :     get(mpEmptyAsZero,"checkEmptyAsZero");
      78           0 :     mpEmptyAsZero->Check(rConfig.mbEmptyStringAsZero);
      79           0 :     mpEmptyAsZero->SetClickHdl(LINK(this, ScCalcOptionsDialog, AsZeroModifiedHdl));
      80             : 
      81           0 :     get(mpSyntax,"comboSyntaxRef");
      82           0 :     mpSyntax->SelectEntryPos(rConfig.meStringRefAddressSyntax);
      83           0 :     mpSyntax->SetSelectHdl(LINK(this, ScCalcOptionsDialog, SyntaxModifiedHdl));
      84             : 
      85           0 :     get(mpUseOpenCL,"CBUseOpenCL");
      86           0 :     mpUseOpenCL->Check(rConfig.mbOpenCLSubsetOnly);
      87           0 :     mpUseOpenCL->SetClickHdl(LINK(this, ScCalcOptionsDialog, CBUseOpenCLHdl));
      88             : 
      89           0 :     get(mpSpinButton,"spinOpenCLSize");
      90           0 :     mpSpinButton->SetValue(rConfig.mnOpenCLMinimumFormulaGroupSize);
      91           0 :     mpSpinButton->SetModifyHdl(LINK(this, ScCalcOptionsDialog, SpinOpenCLMinSizeHdl));
      92             : 
      93           0 :     get(mpEditField, "entry");
      94           0 :     mpEditField->SetText(ScOpCodeSetToSymbolicString(maConfig.maOpenCLSubsetOpCodes));
      95           0 :     mpEditField->set_height_request(4 * mpEditField->GetTextHeight());
      96             : 
      97           0 :     mpEditField->SetModifyHdl(LINK(this, ScCalcOptionsDialog, EditModifiedHdl));
      98             : 
      99           0 :     mpOpenclInfoList->set_height_request(4* mpOpenclInfoList->GetTextHeight());
     100           0 :     mpOpenclInfoList->SetStyle(mpOpenclInfoList->GetStyle() | WB_CLIPCHILDREN | WB_FORCE_MAKEVISIBLE);
     101           0 :     mpOpenclInfoList->SetHighlightRange();
     102           0 :     mpOpenclInfoList->GetParent()->Hide();
     103           0 :     mpOpenclInfoList->SetSelectHdl(LINK(this, ScCalcOptionsDialog, DeviceSelHdl));
     104             : 
     105           0 :     mpBtnAutomaticSelectionTrue->SetToggleHdl(LINK(this, ScCalcOptionsDialog, BtnAutomaticSelectHdl));
     106             : 
     107           0 :     maSoftware = get<vcl::Window>("software")->GetText();
     108             : 
     109           0 :     mpTestButton->SetClickHdl(LINK(this, ScCalcOptionsDialog, TestClickHdl));
     110           0 : }
     111             : 
     112           0 : ScCalcOptionsDialog::~ScCalcOptionsDialog()
     113             : {
     114           0 :     disposeOnce();
     115           0 : }
     116             : 
     117           0 : void ScCalcOptionsDialog::dispose()
     118             : {
     119           0 :     mpUseOpenCL.clear();
     120           0 :     mpSpinButton.clear();
     121           0 :     mpEditField.clear();
     122           0 :     mpTestButton.clear();
     123           0 :     mpFtFrequency.clear();
     124           0 :     mpFtComputeUnits.clear();
     125           0 :     mpFtMemory.clear();
     126           0 :     mpOpenclInfoList.clear();
     127           0 :     mpBtnAutomaticSelectionTrue.clear();
     128           0 :     mpBtnAutomaticSelectionFalse.clear();
     129           0 :     ModalDialog::dispose();
     130           0 : }
     131             : 
     132           0 : void ScCalcOptionsDialog::OpenCLAutomaticSelectionChanged()
     133             : {
     134           0 :     bool bValue = mpBtnAutomaticSelectionTrue->IsChecked();
     135           0 :     if(bValue)
     136           0 :         mpOpenclInfoList->Disable();
     137             :     else
     138           0 :         mpOpenclInfoList->Enable();
     139             : 
     140           0 :     maConfig.mbOpenCLAutoSelect = bValue;
     141           0 : }
     142             : 
     143           0 : void ScCalcOptionsDialog::SelectedDeviceChanged()
     144             : {
     145             : #if HAVE_FEATURE_OPENCL
     146           0 :     SvTreeListEntry* pEntry = mpOpenclInfoList->GetModel()->GetView(0)->FirstSelected();
     147           0 :     if(!pEntry)
     148           0 :         return;
     149             : 
     150           0 :     OpenCLDeviceInfo* pInfo = static_cast<OpenCLDeviceInfo*>(pEntry->GetUserData());
     151           0 :     if(pInfo)
     152             :     {
     153           0 :         mpFtFrequency->SetText(OUString::number(pInfo->mnFrequency));
     154           0 :         mpFtComputeUnits->SetText(OUString::number(pInfo->mnComputeUnits));
     155           0 :         mpFtMemory->SetText(OUString::number(pInfo->mnMemory/1024/1024));
     156             :     }
     157             :     else
     158             :     {
     159           0 :         mpFtFrequency->SetText(OUString());
     160           0 :         mpFtComputeUnits->SetText(OUString());
     161           0 :         mpFtMemory->SetText(OUString());
     162             :     }
     163             : 
     164           0 :     SvLBoxString* pBoxEntry = dynamic_cast<SvLBoxString*>(pEntry->GetItem(1));
     165           0 :     if (!pBoxEntry)
     166           0 :         return;
     167             : 
     168           0 :     OUString aDevice = pBoxEntry->GetText();
     169             :     // use english string for configuration
     170           0 :     if(aDevice == maSoftware)
     171           0 :         aDevice = OPENCL_SOFTWARE_DEVICE_CONFIG_NAME;
     172             : 
     173           0 :     maConfig.maOpenCLDevice = aDevice;
     174             : #endif
     175             : }
     176             : 
     177           0 : IMPL_LINK(ScCalcOptionsDialog, AsZeroModifiedHdl, CheckBox*, pCheckBox )
     178             : {
     179           0 :     maConfig.mbEmptyStringAsZero = pCheckBox->IsChecked();
     180           0 :     return 0;
     181             : }
     182             : 
     183           0 : IMPL_LINK(ScCalcOptionsDialog, ConversionModifiedHdl, ListBox*, pConv )
     184             : {
     185             : 
     186           0 :   maConfig.meStringConversion = (ScCalcConfig::StringConversion)pConv->GetSelectEntryPos();
     187           0 :     switch (maConfig.meStringConversion)
     188             :     {
     189             :          case ScCalcConfig::StringConversion::ILLEGAL:
     190           0 :                     maConfig.mbEmptyStringAsZero = false;
     191           0 :                     mpEmptyAsZero->Check(false);
     192           0 :                     mpEmptyAsZero->Enable(false);
     193           0 :          break;
     194             :          case ScCalcConfig::StringConversion::ZERO:
     195           0 :                     maConfig.mbEmptyStringAsZero = true;
     196           0 :                     mpEmptyAsZero->Check(true);
     197           0 :                     mpEmptyAsZero->Enable(false);
     198           0 :          break;
     199             :          case ScCalcConfig::StringConversion::UNAMBIGUOUS:
     200             :          case ScCalcConfig::StringConversion::LOCALE:
     201             :                     // Reset to the value the user selected before.
     202           0 :                     maConfig.mbEmptyStringAsZero = mbSelectedEmptyStringAsZero;
     203           0 :                     mpEmptyAsZero->Enable(true);
     204           0 :          break;
     205             :      }
     206           0 :     return 0;
     207             : }
     208             : 
     209           0 : IMPL_LINK(ScCalcOptionsDialog, SyntaxModifiedHdl, ListBox*, pSyntax)
     210             : {
     211           0 :     maConfig.meStringRefAddressSyntax = toAddressConvention(pSyntax->GetSelectEntryPos());
     212           0 :     return 0;
     213             : }
     214             : 
     215           0 : IMPL_LINK(ScCalcOptionsDialog, CBUseOpenCLHdl, CheckBox*, pCheckBox)
     216             : {
     217           0 :     maConfig.mbOpenCLSubsetOnly = pCheckBox->IsChecked();
     218           0 :     return 0;
     219             : }
     220             : 
     221           0 : IMPL_LINK(ScCalcOptionsDialog, SpinOpenCLMinSizeHdl, NumericField*, pSpin)
     222             : {
     223           0 :     maConfig.mnOpenCLMinimumFormulaGroupSize = pSpin->GetValue();
     224           0 :     return 0;
     225             : }
     226             : 
     227           0 : IMPL_LINK_NOARG(ScCalcOptionsDialog, BtnAutomaticSelectHdl)
     228             : {
     229           0 :     OpenCLAutomaticSelectionChanged();
     230           0 :     return 0;
     231             : }
     232             : 
     233           0 : IMPL_LINK_NOARG(ScCalcOptionsDialog, DeviceSelHdl)
     234             : {
     235           0 :     SelectedDeviceChanged();
     236           0 :     return 0;
     237             : }
     238             : 
     239           0 : IMPL_LINK(ScCalcOptionsDialog, EditModifiedHdl, Edit*, pCtrl)
     240             : {
     241           0 :     maConfig.maOpenCLSubsetOpCodes = ScStringToOpCodeSet(pCtrl->GetText());
     242           0 :     return 0;
     243             : }
     244             : 
     245             : namespace {
     246             : 
     247             : struct Area
     248             : {
     249             :     OUString msTitle;
     250             :     int mnRows;
     251             : 
     252           0 :     Area(const OUString& rTitle, int nRows = ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize + 2) :
     253             :         msTitle(rTitle),
     254           0 :         mnRows(nRows)
     255             :     {
     256           0 :     }
     257             : 
     258           0 :     virtual ~Area()
     259           0 :     {
     260           0 :     }
     261             : 
     262             :     virtual void addHeader(ScDocument *pDoc, int nTab) const = 0;
     263             : 
     264             :     virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const = 0;
     265             : 
     266             :     virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const = 0;
     267             : };
     268             : 
     269           0 : struct OpenCLTester
     270             : {
     271             :     int mnTestAreas;
     272             :     ScDocShell* mpDocShell;
     273             :     ScDocument *mpDoc;
     274             :     bool mbOldAutoCalc;
     275             :     ScCalcConfig maOldCalcConfig;
     276             : 
     277           0 :     OpenCLTester() :
     278           0 :         mnTestAreas(0)
     279             :     {
     280           0 :         css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
     281           0 :         css::uno::Reference< css::frame::XDesktop2 > xComponentLoader = css::frame::Desktop::create(xContext);
     282             :         css::uno::Reference< css::lang::XComponent >
     283           0 :             xComponent( xComponentLoader->loadComponentFromURL( "private:factory/scalc",
     284             :                                                                 "_blank", 0,
     285           0 :                                                                 css::uno::Sequence < css::beans::PropertyValue >() ) );
     286           0 :         mpDocShell = dynamic_cast<ScDocShell*>(SfxObjectShell::GetShellFromComponent(xComponent));
     287             : 
     288             :         assert(mpDocShell);
     289             : 
     290           0 :         mpDoc = &mpDocShell->GetDocument();
     291             : 
     292           0 :         mbOldAutoCalc = mpDoc->GetAutoCalc();
     293           0 :         mpDoc->SetAutoCalc(false);
     294           0 :         maOldCalcConfig = ScInterpreter::GetGlobalConfig();
     295           0 :         ScCalcConfig aConfig(maOldCalcConfig);
     296           0 :         aConfig.mnOpenCLMinimumFormulaGroupSize = 20;
     297           0 :         ScInterpreter::SetGlobalConfig(aConfig);
     298             : 
     299           0 :         mpDoc->SetString(ScAddress(0,0,0), "Result:");
     300           0 :     }
     301             : 
     302           0 :     void addTest(const Area &rArea)
     303             :     {
     304           0 :         mnTestAreas++;
     305           0 :         (void) mpDocShell->GetDocFunc().InsertTable(mnTestAreas, rArea.msTitle, false, true);
     306             : 
     307           0 :         rArea.addHeader(mpDoc, mnTestAreas);
     308             : 
     309           0 :         for (int i = 0; i < rArea.mnRows; ++i)
     310           0 :             rArea.addRow(mpDoc, i, mnTestAreas);
     311             : 
     312           0 :         mpDoc->SetString(ScAddress(0,1+mnTestAreas-1,0), rArea.msTitle + ":");
     313           0 :         mpDoc->SetString(ScAddress(1,1+mnTestAreas-1,0), rArea.getSummaryFormula(mpDoc, mnTestAreas));
     314             : 
     315             :         mpDoc->SetString(ScAddress(1,0,0),
     316           0 :                         "=IF(SUM(" +
     317             :                         ScRange(ScAddress(1,1,0),
     318           0 :                                 ScAddress(1,1+mnTestAreas-1,0)).Format(SCA_VALID|SCA_VALID_COL|SCA_VALID_ROW) +
     319           0 :                         ")=0,\"PASS\",\"FAIL\")");
     320           0 :     }
     321             : };
     322             : 
     323             : struct Op : Area
     324             : {
     325             :     OUString msOp;
     326             :     double mnRangeLo;
     327             :     double mnRangeHi;
     328             :     double mnEpsilon;
     329             : 
     330           0 :     Op(const OUString& rTitle,
     331             :        const OUString& rOp,
     332             :        double nRangeLo, double nRangeHi,
     333             :        double nEpsilon) :
     334             :         Area(rTitle),
     335             :         msOp(rOp),
     336             :         mnRangeLo(nRangeLo),
     337             :         mnRangeHi(nRangeHi),
     338           0 :         mnEpsilon(nEpsilon)
     339             :     {
     340           0 :     }
     341             : 
     342           0 :     virtual ~Op()
     343           0 :     {
     344           0 :     }
     345             : };
     346             : 
     347             : struct UnOp : Op
     348             : {
     349             :     double (*mpFun)(double nArg);
     350             :     bool (*mpFilterOut)(double nArg);
     351             : 
     352           0 :     UnOp(const OUString& rTitle,
     353             :          const OUString& rOp,
     354             :          double nRangeLo, double nRangeHi,
     355             :          double nEpsilon,
     356             :          double (*pFun)(double nArg),
     357             :          bool (*pFilterOut)(double nArg) = nullptr) :
     358             :         Op(rTitle, rOp, nRangeLo, nRangeHi, nEpsilon),
     359             :         mpFun(pFun),
     360           0 :         mpFilterOut(pFilterOut)
     361             :     {
     362           0 :     }
     363             : 
     364           0 :     virtual ~UnOp()
     365           0 :     {
     366           0 :     }
     367             : 
     368           0 :     virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     369             :     {
     370           0 :         pDoc->SetString(ScAddress(0,0,nTab), "arg");
     371           0 :         pDoc->SetString(ScAddress(1,0,nTab), msOp + "(arg)");
     372           0 :         pDoc->SetString(ScAddress(2,0,nTab), "expected");
     373           0 :     }
     374             : 
     375           0 :     virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
     376             :     {
     377             :         double nArg;
     378             : 
     379           0 :         do {
     380           0 :             nArg = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
     381           0 :         } while (mpFilterOut != nullptr && mpFilterOut(nArg));
     382             : 
     383           0 :         pDoc->SetValue(ScAddress(0,1+nRow,nTab), nArg);
     384             : 
     385             :         pDoc->SetString(ScAddress(1,1+nRow,nTab),
     386           0 :                         "=" + msOp + "(" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) + ")");
     387             : 
     388           0 :         pDoc->SetValue(ScAddress(2,1+nRow,nTab), mpFun(nArg));
     389             : 
     390           0 :         if (mnEpsilon < 0)
     391             :         {
     392             :             // relative epsilon
     393             :             pDoc->SetString(ScAddress(3,1+nRow,nTab),
     394           0 :                             "=IF(ABS((" + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     395           0 :                             "-" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     396           0 :                             ")/" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     397           0 :                             ")<=" + OUString::number(-mnEpsilon) +
     398           0 :                             ",0,1)");
     399             :         }
     400             :         else
     401             :         {
     402             :             // absolute epsilon
     403             :             pDoc->SetString(ScAddress(3,1+nRow,nTab),
     404           0 :                             "=IF(ABS(" + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     405           0 :                             "-" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     406           0 :                             ")<=" + OUString::number(mnEpsilon) +
     407           0 :                             ",0,1)");
     408             :         }
     409           0 :     }
     410             : 
     411           0 :     virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     412             :     {
     413           0 :         return "=SUM(" +
     414             :             ScRange(ScAddress(3,1,nTab),
     415           0 :                     ScAddress(3,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
     416           0 :             ")";
     417             :     }
     418             : };
     419             : 
     420             : struct BinOp : Op
     421             : {
     422             :     double (*mpFun)(double nLhs, double nRhs);
     423             :     bool (*mpFilterOut)(double nLhs, double nRhs);
     424             : 
     425           0 :     BinOp(const OUString& rTitle,
     426             :           const OUString& rOp,
     427             :           double nRangeLo, double nRangeHi,
     428             :           double nEpsilon,
     429             :           double (*pFun)(double nLhs, double nRhs),
     430             :           bool (*pFilterOut)(double nLhs, double nRhs) = nullptr) :
     431             :         Op(rTitle, rOp, nRangeLo, nRangeHi, nEpsilon),
     432             :         mpFun(pFun),
     433           0 :         mpFilterOut(pFilterOut)
     434             :     {
     435           0 :     }
     436             : 
     437           0 :     virtual ~BinOp()
     438           0 :     {
     439           0 :     }
     440             : 
     441           0 :     virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     442             :     {
     443           0 :         pDoc->SetString(ScAddress(0,0,nTab), "lhs");
     444           0 :         pDoc->SetString(ScAddress(1,0,nTab), "rhs");
     445           0 :         pDoc->SetString(ScAddress(2,0,nTab), "lhs" + msOp + "rhs");
     446           0 :         pDoc->SetString(ScAddress(3,0,nTab), "expected");
     447           0 :     }
     448             : 
     449           0 :     virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
     450             :     {
     451             :         double nLhs, nRhs;
     452             : 
     453           0 :         do {
     454           0 :             nLhs = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
     455           0 :             nRhs = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
     456           0 :         } while (mpFilterOut != nullptr && mpFilterOut(nLhs, nRhs));
     457             : 
     458           0 :         pDoc->SetValue(ScAddress(0,1+nRow,nTab), nLhs);
     459           0 :         pDoc->SetValue(ScAddress(1,1+nRow,nTab), nRhs);
     460             : 
     461             :         pDoc->SetString(ScAddress(2,1+nRow,nTab),
     462           0 :                         "=" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     463           0 :                         msOp + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW));
     464             : 
     465           0 :         pDoc->SetValue(ScAddress(3,1+nRow,nTab), mpFun(nLhs, nRhs));
     466             : 
     467             :         pDoc->SetString(ScAddress(4,1+nRow,nTab),
     468           0 :                         "=IF(ABS(" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     469           0 :                         "-" + ScAddress(3,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     470           0 :                         ")<=" + OUString::number(mnEpsilon) +
     471           0 :                         ",0,1)");
     472           0 :     }
     473             : 
     474           0 :     virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     475             :     {
     476           0 :         return "=SUM(" +
     477             :             ScRange(ScAddress(4,1,nTab),
     478           0 :                     ScAddress(4,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
     479           0 :             ")";
     480             :     }
     481             : };
     482             : 
     483             : struct Round : Area
     484             : {
     485           0 :     Round() :
     486           0 :         Area("Round")
     487             :     {
     488           0 :     }
     489             : 
     490           0 :     virtual ~Round()
     491           0 :     {
     492           0 :     }
     493             : 
     494           0 :     virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     495             :     {
     496           0 :         pDoc->SetString(ScAddress(0,0,nTab), "x");
     497           0 :         pDoc->SetString(ScAddress(1,0,nTab), "n");
     498           0 :         pDoc->SetString(ScAddress(2,0,nTab), "ROUND(x,n)");
     499           0 :         pDoc->SetString(ScAddress(3,0,nTab), "expected");
     500           0 :     }
     501             : 
     502           0 :     virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
     503             :     {
     504           0 :         const double nX(comphelper::rng::uniform_real_distribution(0, 100));
     505           0 :         const int nN(comphelper::rng::uniform_int_distribution(1, 10));
     506             : 
     507           0 :         pDoc->SetValue(ScAddress(0,1+nRow,nTab), nX);
     508           0 :         pDoc->SetValue(ScAddress(1,1+nRow,nTab), nN);
     509             : 
     510             :         pDoc->SetString(ScAddress(2,1+nRow,nTab),
     511           0 :                         "=ROUND(" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     512           0 :                         "," + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     513           0 :                         ")");
     514             : 
     515           0 :         pDoc->SetValue(ScAddress(3,1+nRow,nTab), ::rtl::math::round(nX, (short) nN, rtl_math_RoundingMode_Corrected));
     516             : 
     517             :         pDoc->SetString(ScAddress(4,1+nRow,nTab),
     518           0 :                         "=IF(ABS(" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     519           0 :                         "-" + ScAddress(3,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     520             :                         ")<=3e-10"
     521           0 :                         ",0,1)");
     522           0 :     }
     523             : 
     524           0 :     virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     525             :     {
     526           0 :         return "=SUM(" +
     527             :             ScRange(ScAddress(4,1,nTab),
     528           0 :                     ScAddress(4,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
     529           0 :             ")";
     530             :     }
     531             : 
     532             : };
     533             : 
     534             : struct Normdist : Area
     535             : {
     536           0 :     Normdist() :
     537           0 :         Area("Normdist")
     538             :     {
     539           0 :     }
     540             : 
     541           0 :     virtual ~Normdist()
     542           0 :     {
     543           0 :     }
     544             : 
     545           0 :     virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     546             :     {
     547           0 :         pDoc->SetString(ScAddress(0,0,nTab), "num");
     548           0 :         pDoc->SetString(ScAddress(1,0,nTab), "avg");
     549           0 :         pDoc->SetString(ScAddress(2,0,nTab), "stdev");
     550           0 :         pDoc->SetString(ScAddress(3,0,nTab), "type");
     551           0 :         pDoc->SetString(ScAddress(4,0,nTab), "NORMDIST(num,avg,stdev,type)");
     552           0 :         pDoc->SetString(ScAddress(5,0,nTab), "expected");
     553           0 :     }
     554             : 
     555           0 :     virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
     556             :     {
     557           0 :         const double nNum(comphelper::rng::uniform_real_distribution(0, 100));
     558           0 :         const double nAvg(comphelper::rng::uniform_real_distribution(0, 100));
     559           0 :         const double nStDev(comphelper::rng::uniform_real_distribution(1, 10));
     560           0 :         const int nType(comphelper::rng::uniform_int_distribution(0, 1));
     561             : 
     562           0 :         pDoc->SetValue(ScAddress(0,1+nRow,nTab), nNum);
     563           0 :         pDoc->SetValue(ScAddress(1,1+nRow,nTab), nAvg);
     564           0 :         pDoc->SetValue(ScAddress(2,1+nRow,nTab), nStDev);
     565           0 :         pDoc->SetValue(ScAddress(3,1+nRow,nTab), nType);
     566             : 
     567             :         pDoc->SetString(ScAddress(4,1+nRow,nTab),
     568           0 :                         "=NORMDIST(" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     569           0 :                         "," + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     570           0 :                         "," + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     571           0 :                         "," + ScAddress(3,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     572           0 :                         ")");
     573             : 
     574           0 :         if (nType == 1)
     575           0 :             pDoc->SetValue(ScAddress(5,1+nRow,nTab), ScInterpreter::integralPhi((nNum-nAvg)/nStDev));
     576             :         else
     577           0 :             pDoc->SetValue(ScAddress(5,1+nRow,nTab), ScInterpreter::phi((nNum-nAvg)/nStDev)/nStDev);
     578             : 
     579             :         pDoc->SetString(ScAddress(6,1+nRow,nTab),
     580           0 :                         "=IF(ABS(" + ScAddress(4,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     581           0 :                         "-" + ScAddress(5,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     582             :                         ")<=3e-10"
     583           0 :                         ",0,1)");
     584           0 :     }
     585             : 
     586           0 :     virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     587             :     {
     588           0 :         return "=SUM(" +
     589             :             ScRange(ScAddress(6,1,nTab),
     590           0 :                     ScAddress(6,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
     591           0 :             ")";
     592             :     }
     593             : 
     594             : };
     595             : 
     596             : struct Reduction : Op
     597             : {
     598             :     double mnAccumInitial;
     599             :     double (*mpFun)(double nAccum, double nArg, const Reduction& rReduction);
     600             :     bool (*mpFilterOut)(double nArg);
     601             : 
     602           0 :     Reduction(const OUString& rTitle,
     603             :               const OUString& rOp,
     604             :               double nAccumInitial,
     605             :               double nRangeLo, double nRangeHi,
     606             :               double nEpsilon,
     607             :               double (*pFun)(double nAccum, double nArg, const Reduction& rReduction),
     608             :               bool (*pFilterOut)(double nArg) = nullptr) :
     609             :         Op(rTitle, rOp, nRangeLo, nRangeHi, nEpsilon),
     610             :         mnAccumInitial(nAccumInitial),
     611             :         mpFun(pFun),
     612           0 :         mpFilterOut(pFilterOut)
     613             :     {
     614           0 :     }
     615             : 
     616           0 :     virtual ~Reduction()
     617           0 :     {
     618           0 :     }
     619             : 
     620           0 :     virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     621             :     {
     622           0 :         pDoc->SetString(ScAddress(0,0,nTab), "x");
     623           0 :         pDoc->SetString(ScAddress(1,0,nTab), msOp);
     624           0 :         pDoc->SetString(ScAddress(2,0,nTab), "expected");
     625           0 :     }
     626             : 
     627           0 :     virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
     628             :     {
     629             :         double nArg;
     630             : 
     631           0 :         do {
     632           0 :             nArg = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
     633           0 :         } while (mpFilterOut != nullptr && mpFilterOut(nArg));
     634             : 
     635           0 :         pDoc->SetValue(ScAddress(0,1+nRow,nTab), nArg);
     636             : 
     637           0 :         if (nRow >= mnRows/2-1)
     638             :         {
     639           0 :             pDoc->SetString(ScAddress(1,1+nRow-mnRows/2+1,nTab),
     640           0 :                             "=" + msOp + "(" +
     641           0 :                             ScRange(ScAddress(0,1+nRow-mnRows/2+1,nTab),
     642           0 :                                     ScAddress(0,1+nRow,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW) +
     643           0 :                             ")");
     644             : 
     645           0 :             double nAccum(mnAccumInitial);
     646           0 :             for (int i = 0; i < mnRows/2; i++)
     647           0 :                 nAccum = mpFun(nAccum, pDoc->GetValue(ScAddress(0,1+nRow-mnRows/2+i+1,nTab)), *this);
     648             : 
     649           0 :             pDoc->SetValue(ScAddress(2,1+nRow-mnRows/2+1,nTab), nAccum);
     650             : 
     651           0 :             if (mnEpsilon != 0)
     652           0 :                 pDoc->SetString(ScAddress(3,1+nRow-mnRows/2+1,nTab),
     653           0 :                                 "=IF(ABS(" + ScAddress(1,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     654           0 :                                 "-" + ScAddress(2,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     655           0 :                                 ")<=" + OUString::number(mnEpsilon) +
     656           0 :                                 ",0,1)");
     657             :             else
     658           0 :                 pDoc->SetString(ScAddress(3,1+nRow-mnRows/2+1,nTab),
     659           0 :                                 "=IF(" + ScAddress(1,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     660           0 :                                 "=" + ScAddress(2,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
     661           0 :                                 ",0,1)");
     662             :         }
     663           0 :     }
     664             : 
     665           0 :     virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
     666             :     {
     667           0 :         return "=SUM(" +
     668             :             ScRange(ScAddress(3,1+0,nTab),
     669           0 :                     ScAddress(3,1+mnRows-mnRows/2-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
     670           0 :             ")";
     671             :     }
     672             : };
     673             : 
     674             : }
     675             : 
     676           0 : IMPL_STATIC_LINK(
     677             :     ScCalcOptionsDialog, TestClickHdl, PushButton*, pButton)
     678             : {
     679           0 :     pButton->Disable();
     680             : 
     681             :     // Automatically test the current implementation of OpenCL. If it
     682             :     // seems good, whitelist it. If it seems bad, blacklist it.
     683             : 
     684           0 :     std::unique_ptr<OpenCLTester> xTestDocument(new OpenCLTester());
     685             : 
     686             :     xTestDocument->addTest(BinOp("Plus", "+", -1000, 1000, 3e-10,
     687           0 :                                  [] (double nLhs, double nRhs)
     688             :                                  {
     689             :                                      return nLhs + nRhs;
     690           0 :                                  }));
     691             : 
     692             :     xTestDocument->addTest(BinOp("Minus", "-", -1000, 1000, 3e-10,
     693           0 :                                  [] (double nLhs, double nRhs)
     694             :                                  {
     695             :                                      return nLhs - nRhs;
     696           0 :                                  }));
     697             : 
     698             :     xTestDocument->addTest(BinOp("Times", "*", -1000, 1000, 3e-10,
     699           0 :                                  [] (double nLhs, double nRhs)
     700             :                                  {
     701             :                                      return nLhs * nRhs;
     702           0 :                                  }));
     703             : 
     704             :     xTestDocument->addTest(BinOp("Divided", "/", -1000, 1000, 3e-10,
     705           0 :                                  [] (double nLhs, double nRhs)
     706             :                                  {
     707             :                                      return nLhs / nRhs;
     708           0 :                                  },
     709           0 :                                  [] (double, double nRhs)
     710             :                                  {
     711             :                                      return (nRhs == 0);
     712           0 :                                  }));
     713             : 
     714             :     xTestDocument->addTest(UnOp("Sin", "SIN", -10, 10, 3e-10,
     715           0 :                                 [] (double nArg)
     716             :                                 {
     717             :                                     return sin(nArg);
     718           0 :                                 }));
     719             : 
     720             :     xTestDocument->addTest(UnOp("Cos", "COS", -10, 10, 3e-10,
     721           0 :                                 [] (double nArg)
     722             :                                 {
     723             :                                     return cos(nArg);
     724           0 :                                 }));
     725             : 
     726             :     xTestDocument->addTest(UnOp("Tan", "TAN", 0, 10, -3e-10,
     727           0 :                                 [] (double nArg)
     728             :                                 {
     729             :                                     return tan(nArg);
     730           0 :                                 },
     731           0 :                                 [] (double nArg)
     732             :                                 {
     733           0 :                                     return (std::fmod(nArg, M_PI) == M_PI/2);
     734           0 :                                 }));
     735             : 
     736             :     xTestDocument->addTest(UnOp("Atan", "ATAN", -10, 10, 3e-10,
     737           0 :                                 [] (double nArg)
     738             :                                 {
     739             :                                     return atan(nArg);
     740           0 :                                 }));
     741             : 
     742             :     xTestDocument->addTest(UnOp("Sqrt", "SQRT", 0, 1000, 3e-10,
     743           0 :                                 [] (double nArg)
     744             :                                 {
     745             :                                     return sqrt(nArg);
     746           0 :                                 }));
     747             : 
     748             :     xTestDocument->addTest(UnOp("Exp", "EXP", 0, 10, 3e-10,
     749           0 :                                 [] (double nArg)
     750             :                                 {
     751             :                                     return exp(nArg);
     752           0 :                                 }));
     753             : 
     754             :     xTestDocument->addTest(UnOp("Ln", "LN", 0, 1000, 3e-10,
     755           0 :                                 [] (double nArg)
     756             :                                 {
     757             :                                     return log(nArg);
     758           0 :                                 },
     759           0 :                                 [] (double nArg)
     760             :                                 {
     761             :                                     return (nArg == 0);
     762           0 :                                 }));
     763             : 
     764             :     xTestDocument->addTest(UnOp("NormSInv", "NORMSINV", 0, 1, 3e-10,
     765           0 :                                 [] (double nArg)
     766             :                                 {
     767             :                                     return ScInterpreter::gaussinv(nArg);
     768           0 :                                 }));
     769             : 
     770           0 :     xTestDocument->addTest(Round());
     771             : 
     772           0 :     xTestDocument->addTest(Normdist());
     773             : 
     774             :     xTestDocument->addTest(Reduction("Sum", "SUM", 0, -1000, 1000, 3e-10,
     775           0 :                                      [] (double nAccum, double nArg, const Reduction&)
     776             :                                      {
     777             :                                          return (nAccum + nArg);
     778           0 :                                      }));
     779             : 
     780             :     xTestDocument->addTest(Reduction("Average", "AVERAGE", 0, -1000, 1000, 3e-10,
     781           0 :                                      [] (double nAccum, double nArg, const Reduction& rReduction)
     782             :                                      {
     783           0 :                                          return (nAccum + nArg/(rReduction.mnRows/2));
     784           0 :                                      }));
     785             : 
     786             :     xTestDocument->addTest(Reduction("Product", "PRODUCT", 1, 0.1, 2.5, 3e-10,
     787           0 :                                      [] (double nAccum, double nArg, const Reduction&)
     788             :                                      {
     789             :                                          return (nAccum * nArg);
     790           0 :                                      }));
     791             : 
     792             :     xTestDocument->addTest(Reduction("Min", "MIN", DBL_MAX, -1000, 1000, 0,
     793           0 :                                      [] (double nAccum, double nArg, const Reduction&)
     794             :                                      {
     795           0 :                                          return std::min(nAccum, nArg);
     796           0 :                                      }));
     797             : 
     798             :     xTestDocument->addTest(Reduction("Max", "MAX", -DBL_MAX, -1000, 1000, 0,
     799           0 :                                      [] (double nAccum, double nArg, const Reduction&)
     800             :                                      {
     801           0 :                                          return std::max(nAccum, nArg);
     802           0 :                                      }));
     803             : 
     804           0 :     xTestDocument->mpDoc->CalcAll();
     805           0 :     ScInterpreter::SetGlobalConfig(xTestDocument->maOldCalcConfig);
     806             : 
     807           0 :     return 0;
     808           0 : }
     809             : 
     810             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11