fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / optdlg / calcoptionsdlg.cxx
bloba4f7e065273209ab764d655fb2c22ca096a71f11
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <sal/config.h>
12 #include <algorithm>
13 #include <cmath>
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"
25 #include <com/sun/star/frame/Desktop.hpp>
26 #include <com/sun/star/frame/XDesktop2.hpp>
28 #include <comphelper/random.hxx>
29 #include <svtools/svlbitm.hxx>
30 #include <svtools/treelistentry.hxx>
32 #if HAVE_FEATURE_OPENCL
33 #include "formulagroup.hxx"
34 #include "globalnames.hxx"
35 #endif
37 namespace {
39 formula::FormulaGrammar::AddressConvention toAddressConvention(sal_Int32 nPos)
41 switch (nPos)
43 case 1:
44 return formula::FormulaGrammar::CONV_OOO;
45 case 2:
46 return formula::FormulaGrammar::CONV_XL_A1;
47 case 3:
48 return formula::FormulaGrammar::CONV_XL_R1C1;
49 case 4:
50 return formula::FormulaGrammar::CONV_A1_XL_A1;
51 case 0:
52 default:
56 return formula::FormulaGrammar::CONV_UNSPECIFIED;
59 sal_Int32 toSelectedItem( formula::FormulaGrammar::AddressConvention eConv )
61 switch (eConv)
63 case formula::FormulaGrammar::CONV_OOO:
64 return 1;
65 case formula::FormulaGrammar::CONV_XL_A1:
66 return 2;
67 case formula::FormulaGrammar::CONV_XL_R1C1:
68 return 3;
69 case formula::FormulaGrammar::CONV_A1_XL_A1:
70 return 4;
71 default:
74 return 0;
79 ScCalcOptionsDialog::ScCalcOptionsDialog(vcl::Window* pParent, const ScCalcConfig& rConfig)
80 : ModalDialog(pParent, "FormulaCalculationOptions",
81 "modules/scalc/ui/formulacalculationoptions.ui")
82 , maConfig(rConfig)
83 , mbSelectedEmptyStringAsZero(rConfig.mbEmptyStringAsZero)
85 get(mpTestButton, "test");
86 get(mpOpenclInfoList, "opencl_list");
87 get(mpBtnAutomaticSelectionTrue, "automatic_select_true");
88 get(mpBtnAutomaticSelectionFalse, "automatic_select_false");
89 get(mpFtFrequency, "frequency");
90 get(mpFtComputeUnits, "compute_units");
91 get(mpFtMemory, "memory");
93 get(mpConversion,"comboConversion");
94 mpConversion->SelectEntryPos(static_cast<sal_Int32>(rConfig.meStringConversion), true);
95 mpConversion->SetSelectHdl(LINK(this, ScCalcOptionsDialog, ConversionModifiedHdl));
97 get(mpEmptyAsZero,"checkEmptyAsZero");
98 mpEmptyAsZero->Check(rConfig.mbEmptyStringAsZero);
99 mpEmptyAsZero->SetClickHdl(LINK(this, ScCalcOptionsDialog, AsZeroModifiedHdl));
100 CoupleEmptyAsZeroToStringConversion();
102 get(mpSyntax,"comboSyntaxRef");
103 mpSyntax->SelectEntryPos( toSelectedItem(rConfig.meStringRefAddressSyntax) );
104 mpSyntax->SetSelectHdl(LINK(this, ScCalcOptionsDialog, SyntaxModifiedHdl));
106 get(mpUseOpenCL,"CBUseOpenCL");
107 mpUseOpenCL->Check(rConfig.mbOpenCLSubsetOnly);
108 mpUseOpenCL->SetClickHdl(LINK(this, ScCalcOptionsDialog, CBUseOpenCLHdl));
110 get(mpSpinButton,"spinOpenCLSize");
111 mpSpinButton->SetValue(rConfig.mnOpenCLMinimumFormulaGroupSize);
112 mpSpinButton->SetModifyHdl(LINK(this, ScCalcOptionsDialog, SpinOpenCLMinSizeHdl));
114 get(mpEditField, "entry");
115 mpEditField->SetText(ScOpCodeSetToSymbolicString(maConfig.maOpenCLSubsetOpCodes));
116 mpEditField->set_height_request(4 * mpEditField->GetTextHeight());
118 mpEditField->SetModifyHdl(LINK(this, ScCalcOptionsDialog, EditModifiedHdl));
120 mpOpenclInfoList->set_height_request(4* mpOpenclInfoList->GetTextHeight());
121 mpOpenclInfoList->SetStyle(mpOpenclInfoList->GetStyle() | WB_CLIPCHILDREN | WB_FORCE_MAKEVISIBLE);
122 mpOpenclInfoList->SetHighlightRange();
123 mpOpenclInfoList->GetParent()->Hide();
124 mpOpenclInfoList->SetSelectHdl(LINK(this, ScCalcOptionsDialog, DeviceSelHdl));
126 mpBtnAutomaticSelectionTrue->SetToggleHdl(LINK(this, ScCalcOptionsDialog, BtnAutomaticSelectHdl));
128 maSoftware = get<vcl::Window>("software")->GetText();
130 mpTestButton->SetClickHdl(LINK(this, ScCalcOptionsDialog, TestClickHdl));
133 ScCalcOptionsDialog::~ScCalcOptionsDialog()
135 disposeOnce();
138 void ScCalcOptionsDialog::dispose()
140 mpUseOpenCL.clear();
141 mpSpinButton.clear();
142 mpEditField.clear();
143 mpTestButton.clear();
144 mpFtFrequency.clear();
145 mpFtComputeUnits.clear();
146 mpFtMemory.clear();
147 mpOpenclInfoList.clear();
148 mpBtnAutomaticSelectionTrue.clear();
149 mpBtnAutomaticSelectionFalse.clear();
150 ModalDialog::dispose();
153 void ScCalcOptionsDialog::OpenCLAutomaticSelectionChanged()
155 bool bValue = mpBtnAutomaticSelectionTrue->IsChecked();
156 if(bValue)
157 mpOpenclInfoList->Disable();
158 else
159 mpOpenclInfoList->Enable();
161 maConfig.mbOpenCLAutoSelect = bValue;
164 void ScCalcOptionsDialog::SelectedDeviceChanged()
166 #if HAVE_FEATURE_OPENCL
167 SvTreeListEntry* pEntry = mpOpenclInfoList->GetModel()->GetView(0)->FirstSelected();
168 if(!pEntry)
169 return;
171 OpenCLDeviceInfo* pInfo = static_cast<OpenCLDeviceInfo*>(pEntry->GetUserData());
172 if(pInfo)
174 mpFtFrequency->SetText(OUString::number(pInfo->mnFrequency));
175 mpFtComputeUnits->SetText(OUString::number(pInfo->mnComputeUnits));
176 mpFtMemory->SetText(OUString::number(pInfo->mnMemory/1024/1024));
178 else
180 mpFtFrequency->SetText(OUString());
181 mpFtComputeUnits->SetText(OUString());
182 mpFtMemory->SetText(OUString());
185 SvLBoxString* pBoxEntry = dynamic_cast<SvLBoxString*>(pEntry->GetItem(1));
186 if (!pBoxEntry)
187 return;
189 OUString aDevice = pBoxEntry->GetText();
190 // use english string for configuration
191 if(aDevice == maSoftware)
192 aDevice = OPENCL_SOFTWARE_DEVICE_CONFIG_NAME;
194 maConfig.maOpenCLDevice = aDevice;
195 #endif
198 void ScCalcOptionsDialog::CoupleEmptyAsZeroToStringConversion()
200 switch (maConfig.meStringConversion)
202 case ScCalcConfig::StringConversion::ILLEGAL:
203 maConfig.mbEmptyStringAsZero = false;
204 mpEmptyAsZero->Check(false);
205 mpEmptyAsZero->Enable(false);
206 break;
207 case ScCalcConfig::StringConversion::ZERO:
208 maConfig.mbEmptyStringAsZero = true;
209 mpEmptyAsZero->Check();
210 mpEmptyAsZero->Enable(false);
211 break;
212 case ScCalcConfig::StringConversion::UNAMBIGUOUS:
213 case ScCalcConfig::StringConversion::LOCALE:
214 // Reset to the value the user selected before.
215 maConfig.mbEmptyStringAsZero = mbSelectedEmptyStringAsZero;
216 mpEmptyAsZero->Enable(true);
217 mpEmptyAsZero->Check( mbSelectedEmptyStringAsZero);
218 break;
222 IMPL_LINK(ScCalcOptionsDialog, AsZeroModifiedHdl, CheckBox*, pCheckBox )
224 maConfig.mbEmptyStringAsZero = mbSelectedEmptyStringAsZero = pCheckBox->IsChecked();
225 return 0;
228 IMPL_LINK(ScCalcOptionsDialog, ConversionModifiedHdl, ListBox*, pConv )
231 maConfig.meStringConversion = (ScCalcConfig::StringConversion)pConv->GetSelectEntryPos();
232 CoupleEmptyAsZeroToStringConversion();
233 return 0;
236 IMPL_LINK(ScCalcOptionsDialog, SyntaxModifiedHdl, ListBox*, pSyntax)
238 maConfig.SetStringRefSyntax(toAddressConvention(pSyntax->GetSelectEntryPos()));
239 return 0;
242 IMPL_LINK(ScCalcOptionsDialog, CBUseOpenCLHdl, CheckBox*, pCheckBox)
244 maConfig.mbOpenCLSubsetOnly = pCheckBox->IsChecked();
245 return 0;
248 IMPL_LINK(ScCalcOptionsDialog, SpinOpenCLMinSizeHdl, NumericField*, pSpin)
250 maConfig.mnOpenCLMinimumFormulaGroupSize = pSpin->GetValue();
251 return 0;
254 IMPL_LINK_NOARG(ScCalcOptionsDialog, BtnAutomaticSelectHdl)
256 OpenCLAutomaticSelectionChanged();
257 return 0;
260 IMPL_LINK_NOARG(ScCalcOptionsDialog, DeviceSelHdl)
262 SelectedDeviceChanged();
263 return 0;
266 IMPL_LINK(ScCalcOptionsDialog, EditModifiedHdl, Edit*, pCtrl)
268 maConfig.maOpenCLSubsetOpCodes = ScStringToOpCodeSet(pCtrl->GetText());
269 return 0;
272 namespace {
274 struct Area
276 OUString msTitle;
277 int mnRows;
279 Area(const OUString& rTitle, int nRows = ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize + 2) :
280 msTitle(rTitle),
281 mnRows(nRows)
285 virtual ~Area()
289 virtual void addHeader(ScDocument *pDoc, int nTab) const = 0;
291 virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const = 0;
293 virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const = 0;
296 struct OpenCLTester
298 int mnTestAreas;
299 ScDocShell* mpDocShell;
300 ScDocument *mpDoc;
301 bool mbOldAutoCalc;
302 ScCalcConfig maOldCalcConfig;
304 OpenCLTester() :
305 mnTestAreas(0)
307 css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
308 css::uno::Reference< css::frame::XDesktop2 > xComponentLoader = css::frame::Desktop::create(xContext);
309 css::uno::Reference< css::lang::XComponent >
310 xComponent( xComponentLoader->loadComponentFromURL( "private:factory/scalc",
311 "_blank", 0,
312 css::uno::Sequence < css::beans::PropertyValue >() ) );
313 mpDocShell = dynamic_cast<ScDocShell*>(SfxObjectShell::GetShellFromComponent(xComponent));
315 assert(mpDocShell);
317 mpDoc = &mpDocShell->GetDocument();
319 mbOldAutoCalc = mpDoc->GetAutoCalc();
320 mpDoc->SetAutoCalc(false);
321 maOldCalcConfig = ScInterpreter::GetGlobalConfig();
322 ScCalcConfig aConfig(maOldCalcConfig);
323 aConfig.mnOpenCLMinimumFormulaGroupSize = 20;
324 ScInterpreter::SetGlobalConfig(aConfig);
326 mpDoc->SetString(ScAddress(0,0,0), "Result:");
329 void addTest(const Area &rArea)
331 mnTestAreas++;
332 (void) mpDocShell->GetDocFunc().InsertTable(mnTestAreas, rArea.msTitle, false, true);
334 rArea.addHeader(mpDoc, mnTestAreas);
336 for (int i = 0; i < rArea.mnRows; ++i)
337 rArea.addRow(mpDoc, i, mnTestAreas);
339 mpDoc->SetString(ScAddress(0,1+mnTestAreas-1,0), rArea.msTitle + ":");
340 mpDoc->SetString(ScAddress(1,1+mnTestAreas-1,0), rArea.getSummaryFormula(mpDoc, mnTestAreas));
342 mpDoc->SetString(ScAddress(1,0,0),
343 "=IF(SUM(" +
344 ScRange(ScAddress(1,1,0),
345 ScAddress(1,1+mnTestAreas-1,0)).Format(SCA_VALID|SCA_VALID_COL|SCA_VALID_ROW) +
346 ")=0,\"PASS\",\"FAIL\")");
350 struct Op : Area
352 OUString msOp;
353 double mnRangeLo;
354 double mnRangeHi;
355 double mnEpsilon;
357 Op(const OUString& rTitle,
358 const OUString& rOp,
359 double nRangeLo, double nRangeHi,
360 double nEpsilon) :
361 Area(rTitle),
362 msOp(rOp),
363 mnRangeLo(nRangeLo),
364 mnRangeHi(nRangeHi),
365 mnEpsilon(nEpsilon)
369 virtual ~Op()
374 struct UnOp : Op
376 double (*mpFun)(double nArg);
377 bool (*mpFilterOut)(double nArg);
379 UnOp(const OUString& rTitle,
380 const OUString& rOp,
381 double nRangeLo, double nRangeHi,
382 double nEpsilon,
383 double (*pFun)(double nArg),
384 bool (*pFilterOut)(double nArg) = nullptr) :
385 Op(rTitle, rOp, nRangeLo, nRangeHi, nEpsilon),
386 mpFun(pFun),
387 mpFilterOut(pFilterOut)
391 virtual ~UnOp()
395 virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
397 pDoc->SetString(ScAddress(0,0,nTab), "arg");
398 pDoc->SetString(ScAddress(1,0,nTab), msOp + "(arg)");
399 pDoc->SetString(ScAddress(2,0,nTab), "expected");
402 virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
404 double nArg;
406 do {
407 nArg = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
408 } while (mpFilterOut != nullptr && mpFilterOut(nArg));
410 pDoc->SetValue(ScAddress(0,1+nRow,nTab), nArg);
412 pDoc->SetString(ScAddress(1,1+nRow,nTab),
413 "=" + msOp + "(" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) + ")");
415 pDoc->SetValue(ScAddress(2,1+nRow,nTab), mpFun(nArg));
417 if (mnEpsilon < 0)
419 // relative epsilon
420 pDoc->SetString(ScAddress(3,1+nRow,nTab),
421 "=IF(ABS((" + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
422 "-" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
423 ")/" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
424 ")<=" + OUString::number(-mnEpsilon) +
425 ",0,1)");
427 else
429 // absolute epsilon
430 pDoc->SetString(ScAddress(3,1+nRow,nTab),
431 "=IF(ABS(" + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
432 "-" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
433 ")<=" + OUString::number(mnEpsilon) +
434 ",0,1)");
438 virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
440 return "=SUM(" +
441 ScRange(ScAddress(3,1,nTab),
442 ScAddress(3,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
443 ")";
447 struct BinOp : Op
449 double (*mpFun)(double nLhs, double nRhs);
450 bool (*mpFilterOut)(double nLhs, double nRhs);
452 BinOp(const OUString& rTitle,
453 const OUString& rOp,
454 double nRangeLo, double nRangeHi,
455 double nEpsilon,
456 double (*pFun)(double nLhs, double nRhs),
457 bool (*pFilterOut)(double nLhs, double nRhs) = nullptr) :
458 Op(rTitle, rOp, nRangeLo, nRangeHi, nEpsilon),
459 mpFun(pFun),
460 mpFilterOut(pFilterOut)
464 virtual ~BinOp()
468 virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
470 pDoc->SetString(ScAddress(0,0,nTab), "lhs");
471 pDoc->SetString(ScAddress(1,0,nTab), "rhs");
472 pDoc->SetString(ScAddress(2,0,nTab), "lhs" + msOp + "rhs");
473 pDoc->SetString(ScAddress(3,0,nTab), "expected");
476 virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
478 double nLhs, nRhs;
480 do {
481 nLhs = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
482 nRhs = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
483 } while (mpFilterOut != nullptr && mpFilterOut(nLhs, nRhs));
485 pDoc->SetValue(ScAddress(0,1+nRow,nTab), nLhs);
486 pDoc->SetValue(ScAddress(1,1+nRow,nTab), nRhs);
488 pDoc->SetString(ScAddress(2,1+nRow,nTab),
489 "=" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
490 msOp + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW));
492 pDoc->SetValue(ScAddress(3,1+nRow,nTab), mpFun(nLhs, nRhs));
494 pDoc->SetString(ScAddress(4,1+nRow,nTab),
495 "=IF(ABS(" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
496 "-" + ScAddress(3,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
497 ")<=" + OUString::number(mnEpsilon) +
498 ",0,1)");
501 virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
503 return "=SUM(" +
504 ScRange(ScAddress(4,1,nTab),
505 ScAddress(4,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
506 ")";
510 struct Round : Area
512 Round() :
513 Area("Round")
517 virtual ~Round()
521 virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
523 pDoc->SetString(ScAddress(0,0,nTab), "x");
524 pDoc->SetString(ScAddress(1,0,nTab), "n");
525 pDoc->SetString(ScAddress(2,0,nTab), "ROUND(x,n)");
526 pDoc->SetString(ScAddress(3,0,nTab), "expected");
529 virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
531 const double nX(comphelper::rng::uniform_real_distribution(0, 100));
532 const int nN(comphelper::rng::uniform_int_distribution(1, 10));
534 pDoc->SetValue(ScAddress(0,1+nRow,nTab), nX);
535 pDoc->SetValue(ScAddress(1,1+nRow,nTab), nN);
537 pDoc->SetString(ScAddress(2,1+nRow,nTab),
538 "=ROUND(" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
539 "," + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
540 ")");
542 pDoc->SetValue(ScAddress(3,1+nRow,nTab), ::rtl::math::round(nX, (short) nN, rtl_math_RoundingMode_Corrected));
544 pDoc->SetString(ScAddress(4,1+nRow,nTab),
545 "=IF(ABS(" + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
546 "-" + ScAddress(3,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
547 ")<=3e-10"
548 ",0,1)");
551 virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
553 return "=SUM(" +
554 ScRange(ScAddress(4,1,nTab),
555 ScAddress(4,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
556 ")";
561 struct Normdist : Area
563 Normdist() :
564 Area("Normdist")
568 virtual ~Normdist()
572 virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
574 pDoc->SetString(ScAddress(0,0,nTab), "num");
575 pDoc->SetString(ScAddress(1,0,nTab), "avg");
576 pDoc->SetString(ScAddress(2,0,nTab), "stdev");
577 pDoc->SetString(ScAddress(3,0,nTab), "type");
578 pDoc->SetString(ScAddress(4,0,nTab), "NORMDIST(num,avg,stdev,type)");
579 pDoc->SetString(ScAddress(5,0,nTab), "expected");
582 virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
584 const double nNum(comphelper::rng::uniform_real_distribution(0, 100));
585 const double nAvg(comphelper::rng::uniform_real_distribution(0, 100));
586 const double nStDev(comphelper::rng::uniform_real_distribution(1, 10));
587 const int nType(comphelper::rng::uniform_int_distribution(0, 1));
589 pDoc->SetValue(ScAddress(0,1+nRow,nTab), nNum);
590 pDoc->SetValue(ScAddress(1,1+nRow,nTab), nAvg);
591 pDoc->SetValue(ScAddress(2,1+nRow,nTab), nStDev);
592 pDoc->SetValue(ScAddress(3,1+nRow,nTab), nType);
594 pDoc->SetString(ScAddress(4,1+nRow,nTab),
595 "=NORMDIST(" + ScAddress(0,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
596 "," + ScAddress(1,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
597 "," + ScAddress(2,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
598 "," + ScAddress(3,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
599 ")");
601 if (nType == 1)
602 pDoc->SetValue(ScAddress(5,1+nRow,nTab), ScInterpreter::integralPhi((nNum-nAvg)/nStDev));
603 else
604 pDoc->SetValue(ScAddress(5,1+nRow,nTab), ScInterpreter::phi((nNum-nAvg)/nStDev)/nStDev);
606 pDoc->SetString(ScAddress(6,1+nRow,nTab),
607 "=IF(ABS(" + ScAddress(4,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
608 "-" + ScAddress(5,1+nRow,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
609 ")<=3e-10"
610 ",0,1)");
613 virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
615 return "=SUM(" +
616 ScRange(ScAddress(6,1,nTab),
617 ScAddress(6,1+mnRows-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
618 ")";
623 struct Reduction : Op
625 double mnAccumInitial;
626 double (*mpFun)(double nAccum, double nArg, const Reduction& rReduction);
627 bool (*mpFilterOut)(double nArg);
629 Reduction(const OUString& rTitle,
630 const OUString& rOp,
631 double nAccumInitial,
632 double nRangeLo, double nRangeHi,
633 double nEpsilon,
634 double (*pFun)(double nAccum, double nArg, const Reduction& rReduction),
635 bool (*pFilterOut)(double nArg) = nullptr) :
636 Op(rTitle, rOp, nRangeLo, nRangeHi, nEpsilon),
637 mnAccumInitial(nAccumInitial),
638 mpFun(pFun),
639 mpFilterOut(pFilterOut)
643 virtual ~Reduction()
647 virtual void addHeader(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
649 pDoc->SetString(ScAddress(0,0,nTab), "x");
650 pDoc->SetString(ScAddress(1,0,nTab), msOp);
651 pDoc->SetString(ScAddress(2,0,nTab), "expected");
654 virtual void addRow(ScDocument *pDoc, int nRow, int nTab) const SAL_OVERRIDE
656 double nArg;
658 do {
659 nArg = comphelper::rng::uniform_real_distribution(mnRangeLo, mnRangeHi);
660 } while (mpFilterOut != nullptr && mpFilterOut(nArg));
662 pDoc->SetValue(ScAddress(0,1+nRow,nTab), nArg);
664 if (nRow >= mnRows/2-1)
666 pDoc->SetString(ScAddress(1,1+nRow-mnRows/2+1,nTab),
667 "=" + msOp + "(" +
668 ScRange(ScAddress(0,1+nRow-mnRows/2+1,nTab),
669 ScAddress(0,1+nRow,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW) +
670 ")");
672 double nAccum(mnAccumInitial);
673 for (int i = 0; i < mnRows/2; i++)
674 nAccum = mpFun(nAccum, pDoc->GetValue(ScAddress(0,1+nRow-mnRows/2+i+1,nTab)), *this);
676 pDoc->SetValue(ScAddress(2,1+nRow-mnRows/2+1,nTab), nAccum);
678 if (mnEpsilon != 0)
679 pDoc->SetString(ScAddress(3,1+nRow-mnRows/2+1,nTab),
680 "=IF(ABS(" + ScAddress(1,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
681 "-" + ScAddress(2,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
682 ")<=" + OUString::number(mnEpsilon) +
683 ",0,1)");
684 else
685 pDoc->SetString(ScAddress(3,1+nRow-mnRows/2+1,nTab),
686 "=IF(" + ScAddress(1,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
687 "=" + ScAddress(2,1+nRow-mnRows/2+1,nTab).Format(SCA_VALID_COL|SCA_VALID_ROW) +
688 ",0,1)");
692 virtual OUString getSummaryFormula(ScDocument *pDoc, int nTab) const SAL_OVERRIDE
694 return "=SUM(" +
695 ScRange(ScAddress(3,1+0,nTab),
696 ScAddress(3,1+mnRows-mnRows/2-1,nTab)).Format(SCA_VALID|SCA_TAB_3D|SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB, pDoc) +
697 ")";
703 IMPL_STATIC_LINK(
704 ScCalcOptionsDialog, TestClickHdl, PushButton*, pButton)
706 pButton->Disable();
708 // Automatically test the current implementation of OpenCL. If it
709 // seems good, whitelist it. If it seems bad, blacklist it.
711 std::unique_ptr<OpenCLTester> xTestDocument(new OpenCLTester());
713 xTestDocument->addTest(BinOp("Plus", "+", -1000, 1000, 3e-10,
714 [] (double nLhs, double nRhs)
716 return nLhs + nRhs;
717 }));
719 xTestDocument->addTest(BinOp("Minus", "-", -1000, 1000, 3e-10,
720 [] (double nLhs, double nRhs)
722 return nLhs - nRhs;
723 }));
725 xTestDocument->addTest(BinOp("Times", "*", -1000, 1000, 3e-10,
726 [] (double nLhs, double nRhs)
728 return nLhs * nRhs;
729 }));
731 xTestDocument->addTest(BinOp("Divided", "/", -1000, 1000, 3e-10,
732 [] (double nLhs, double nRhs)
734 return nLhs / nRhs;
736 [] (double, double nRhs)
738 return (nRhs == 0);
739 }));
741 xTestDocument->addTest(UnOp("Sin", "SIN", -10, 10, 3e-10,
742 [] (double nArg)
744 return sin(nArg);
745 }));
747 xTestDocument->addTest(UnOp("Cos", "COS", -10, 10, 3e-10,
748 [] (double nArg)
750 return cos(nArg);
751 }));
753 xTestDocument->addTest(UnOp("Tan", "TAN", 0, 10, -3e-10,
754 [] (double nArg)
756 return tan(nArg);
758 [] (double nArg)
760 return (std::fmod(nArg, M_PI) == M_PI/2);
761 }));
763 xTestDocument->addTest(UnOp("Atan", "ATAN", -10, 10, 3e-10,
764 [] (double nArg)
766 return atan(nArg);
767 }));
769 xTestDocument->addTest(UnOp("Sqrt", "SQRT", 0, 1000, 3e-10,
770 [] (double nArg)
772 return sqrt(nArg);
773 }));
775 xTestDocument->addTest(UnOp("Exp", "EXP", 0, 10, 3e-10,
776 [] (double nArg)
778 return exp(nArg);
779 }));
781 xTestDocument->addTest(UnOp("Ln", "LN", 0, 1000, 3e-10,
782 [] (double nArg)
784 return log(nArg);
786 [] (double nArg)
788 return (nArg == 0);
789 }));
791 xTestDocument->addTest(UnOp("NormSInv", "NORMSINV", 0, 1, 3e-10,
792 [] (double nArg)
794 return ScInterpreter::gaussinv(nArg);
795 }));
797 xTestDocument->addTest(Round());
799 xTestDocument->addTest(Normdist());
801 xTestDocument->addTest(Reduction("Sum", "SUM", 0, -1000, 1000, 3e-10,
802 [] (double nAccum, double nArg, const Reduction&)
804 return (nAccum + nArg);
805 }));
807 xTestDocument->addTest(Reduction("Average", "AVERAGE", 0, -1000, 1000, 3e-10,
808 [] (double nAccum, double nArg, const Reduction& rReduction)
810 return (nAccum + nArg/(rReduction.mnRows/2));
811 }));
813 xTestDocument->addTest(Reduction("Product", "PRODUCT", 1, 0.1, 2.5, 3e-10,
814 [] (double nAccum, double nArg, const Reduction&)
816 return (nAccum * nArg);
817 }));
819 xTestDocument->addTest(Reduction("Min", "MIN", DBL_MAX, -1000, 1000, 0,
820 [] (double nAccum, double nArg, const Reduction&)
822 return std::min(nAccum, nArg);
823 }));
825 xTestDocument->addTest(Reduction("Max", "MAX", -DBL_MAX, -1000, 1000, 0,
826 [] (double nAccum, double nArg, const Reduction&)
828 return std::max(nAccum, nArg);
829 }));
831 xTestDocument->mpDoc->CalcAll();
832 ScInterpreter::SetGlobalConfig(xTestDocument->maOldCalcConfig);
834 return 0;
837 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */