1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <sal/config.h>
15 #include "calcconfig.hxx"
16 #include "calcoptionsdlg.hxx"
17 #include "docfunc.hxx"
19 #include "interpre.hxx"
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"
39 formula::FormulaGrammar::AddressConvention
toAddressConvention(sal_Int32 nPos
)
44 return formula::FormulaGrammar::CONV_OOO
;
46 return formula::FormulaGrammar::CONV_XL_A1
;
48 return formula::FormulaGrammar::CONV_XL_R1C1
;
50 return formula::FormulaGrammar::CONV_A1_XL_A1
;
56 return formula::FormulaGrammar::CONV_UNSPECIFIED
;
59 sal_Int32
toSelectedItem( formula::FormulaGrammar::AddressConvention eConv
)
63 case formula::FormulaGrammar::CONV_OOO
:
65 case formula::FormulaGrammar::CONV_XL_A1
:
67 case formula::FormulaGrammar::CONV_XL_R1C1
:
69 case formula::FormulaGrammar::CONV_A1_XL_A1
:
79 ScCalcOptionsDialog::ScCalcOptionsDialog(vcl::Window
* pParent
, const ScCalcConfig
& rConfig
)
80 : ModalDialog(pParent
, "FormulaCalculationOptions",
81 "modules/scalc/ui/formulacalculationoptions.ui")
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()
138 void ScCalcOptionsDialog::dispose()
141 mpSpinButton
.clear();
143 mpTestButton
.clear();
144 mpFtFrequency
.clear();
145 mpFtComputeUnits
.clear();
147 mpOpenclInfoList
.clear();
148 mpBtnAutomaticSelectionTrue
.clear();
149 mpBtnAutomaticSelectionFalse
.clear();
150 ModalDialog::dispose();
153 void ScCalcOptionsDialog::OpenCLAutomaticSelectionChanged()
155 bool bValue
= mpBtnAutomaticSelectionTrue
->IsChecked();
157 mpOpenclInfoList
->Disable();
159 mpOpenclInfoList
->Enable();
161 maConfig
.mbOpenCLAutoSelect
= bValue
;
164 void ScCalcOptionsDialog::SelectedDeviceChanged()
166 #if HAVE_FEATURE_OPENCL
167 SvTreeListEntry
* pEntry
= mpOpenclInfoList
->GetModel()->GetView(0)->FirstSelected();
171 OpenCLDeviceInfo
* pInfo
= static_cast<OpenCLDeviceInfo
*>(pEntry
->GetUserData());
174 mpFtFrequency
->SetText(OUString::number(pInfo
->mnFrequency
));
175 mpFtComputeUnits
->SetText(OUString::number(pInfo
->mnComputeUnits
));
176 mpFtMemory
->SetText(OUString::number(pInfo
->mnMemory
/1024/1024));
180 mpFtFrequency
->SetText(OUString());
181 mpFtComputeUnits
->SetText(OUString());
182 mpFtMemory
->SetText(OUString());
185 SvLBoxString
* pBoxEntry
= dynamic_cast<SvLBoxString
*>(pEntry
->GetItem(1));
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
;
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);
207 case ScCalcConfig::StringConversion::ZERO
:
208 maConfig
.mbEmptyStringAsZero
= true;
209 mpEmptyAsZero
->Check();
210 mpEmptyAsZero
->Enable(false);
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
);
222 IMPL_LINK(ScCalcOptionsDialog
, AsZeroModifiedHdl
, CheckBox
*, pCheckBox
)
224 maConfig
.mbEmptyStringAsZero
= mbSelectedEmptyStringAsZero
= pCheckBox
->IsChecked();
228 IMPL_LINK(ScCalcOptionsDialog
, ConversionModifiedHdl
, ListBox
*, pConv
)
231 maConfig
.meStringConversion
= (ScCalcConfig::StringConversion
)pConv
->GetSelectEntryPos();
232 CoupleEmptyAsZeroToStringConversion();
236 IMPL_LINK(ScCalcOptionsDialog
, SyntaxModifiedHdl
, ListBox
*, pSyntax
)
238 maConfig
.SetStringRefSyntax(toAddressConvention(pSyntax
->GetSelectEntryPos()));
242 IMPL_LINK(ScCalcOptionsDialog
, CBUseOpenCLHdl
, CheckBox
*, pCheckBox
)
244 maConfig
.mbOpenCLSubsetOnly
= pCheckBox
->IsChecked();
248 IMPL_LINK(ScCalcOptionsDialog
, SpinOpenCLMinSizeHdl
, NumericField
*, pSpin
)
250 maConfig
.mnOpenCLMinimumFormulaGroupSize
= pSpin
->GetValue();
254 IMPL_LINK_NOARG(ScCalcOptionsDialog
, BtnAutomaticSelectHdl
)
256 OpenCLAutomaticSelectionChanged();
260 IMPL_LINK_NOARG(ScCalcOptionsDialog
, DeviceSelHdl
)
262 SelectedDeviceChanged();
266 IMPL_LINK(ScCalcOptionsDialog
, EditModifiedHdl
, Edit
*, pCtrl
)
268 maConfig
.maOpenCLSubsetOpCodes
= ScStringToOpCodeSet(pCtrl
->GetText());
279 Area(const OUString
& rTitle
, int nRows
= ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize
+ 2) :
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;
299 ScDocShell
* mpDocShell
;
302 ScCalcConfig maOldCalcConfig
;
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",
312 css::uno::Sequence
< css::beans::PropertyValue
>() ) );
313 mpDocShell
= dynamic_cast<ScDocShell
*>(SfxObjectShell::GetShellFromComponent(xComponent
));
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
)
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),
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\")");
357 Op(const OUString
& rTitle
,
359 double nRangeLo
, double nRangeHi
,
376 double (*mpFun
)(double nArg
);
377 bool (*mpFilterOut
)(double nArg
);
379 UnOp(const OUString
& rTitle
,
381 double nRangeLo
, double nRangeHi
,
383 double (*pFun
)(double nArg
),
384 bool (*pFilterOut
)(double nArg
) = nullptr) :
385 Op(rTitle
, rOp
, nRangeLo
, nRangeHi
, nEpsilon
),
387 mpFilterOut(pFilterOut
)
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
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
));
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
) +
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
) +
438 virtual OUString
getSummaryFormula(ScDocument
*pDoc
, int nTab
) const SAL_OVERRIDE
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
) +
449 double (*mpFun
)(double nLhs
, double nRhs
);
450 bool (*mpFilterOut
)(double nLhs
, double nRhs
);
452 BinOp(const OUString
& rTitle
,
454 double nRangeLo
, double nRangeHi
,
456 double (*pFun
)(double nLhs
, double nRhs
),
457 bool (*pFilterOut
)(double nLhs
, double nRhs
) = nullptr) :
458 Op(rTitle
, rOp
, nRangeLo
, nRangeHi
, nEpsilon
),
460 mpFilterOut(pFilterOut
)
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
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
) +
501 virtual OUString
getSummaryFormula(ScDocument
*pDoc
, int nTab
) const SAL_OVERRIDE
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
) +
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
) +
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
) +
551 virtual OUString
getSummaryFormula(ScDocument
*pDoc
, int nTab
) const SAL_OVERRIDE
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
) +
561 struct Normdist
: Area
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
) +
602 pDoc
->SetValue(ScAddress(5,1+nRow
,nTab
), ScInterpreter::integralPhi((nNum
-nAvg
)/nStDev
));
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
) +
613 virtual OUString
getSummaryFormula(ScDocument
*pDoc
, int nTab
) const SAL_OVERRIDE
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
) +
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
,
631 double nAccumInitial
,
632 double nRangeLo
, double nRangeHi
,
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
),
639 mpFilterOut(pFilterOut
)
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
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
),
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
) +
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
);
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
) +
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
) +
692 virtual OUString
getSummaryFormula(ScDocument
*pDoc
, int nTab
) const SAL_OVERRIDE
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
) +
704 ScCalcOptionsDialog
, TestClickHdl
, PushButton
*, pButton
)
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
)
719 xTestDocument
->addTest(BinOp("Minus", "-", -1000, 1000, 3e-10,
720 [] (double nLhs
, double nRhs
)
725 xTestDocument
->addTest(BinOp("Times", "*", -1000, 1000, 3e-10,
726 [] (double nLhs
, double nRhs
)
731 xTestDocument
->addTest(BinOp("Divided", "/", -1000, 1000, 3e-10,
732 [] (double nLhs
, double nRhs
)
736 [] (double, double nRhs
)
741 xTestDocument
->addTest(UnOp("Sin", "SIN", -10, 10, 3e-10,
747 xTestDocument
->addTest(UnOp("Cos", "COS", -10, 10, 3e-10,
753 xTestDocument
->addTest(UnOp("Tan", "TAN", 0, 10, -3e-10,
760 return (std::fmod(nArg
, M_PI
) == M_PI
/2);
763 xTestDocument
->addTest(UnOp("Atan", "ATAN", -10, 10, 3e-10,
769 xTestDocument
->addTest(UnOp("Sqrt", "SQRT", 0, 1000, 3e-10,
775 xTestDocument
->addTest(UnOp("Exp", "EXP", 0, 10, 3e-10,
781 xTestDocument
->addTest(UnOp("Ln", "LN", 0, 1000, 3e-10,
791 xTestDocument
->addTest(UnOp("NormSInv", "NORMSINV", 0, 1, 3e-10,
794 return ScInterpreter::gaussinv(nArg
);
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
);
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));
813 xTestDocument
->addTest(Reduction("Product", "PRODUCT", 1, 0.1, 2.5, 3e-10,
814 [] (double nAccum
, double nArg
, const Reduction
&)
816 return (nAccum
* nArg
);
819 xTestDocument
->addTest(Reduction("Min", "MIN", DBL_MAX
, -1000, 1000, 0,
820 [] (double nAccum
, double nArg
, const Reduction
&)
822 return std::min(nAccum
, nArg
);
825 xTestDocument
->addTest(Reduction("Max", "MAX", -DBL_MAX
, -1000, 1000, 0,
826 [] (double nAccum
, double nArg
, const Reduction
&)
828 return std::max(nAccum
, nArg
);
831 xTestDocument
->mpDoc
->CalcAll();
832 ScInterpreter::SetGlobalConfig(xTestDocument
->maOldCalcConfig
);
837 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */