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 <ostream>
11 : #include <set>
12 :
13 : #include <formula/FormulaCompiler.hxx>
14 : #include <formula/grammar.hxx>
15 : #include <formula/opcode.hxx>
16 : #include <rtl/ustring.hxx>
17 : #include <sfx2/objsh.hxx>
18 :
19 : #include "calcconfig.hxx"
20 : #include "compiler.hxx"
21 : #include "docsh.hxx"
22 :
23 11966 : ScCalcConfig::ScCalcConfig() :
24 : meStringRefAddressSyntax(formula::FormulaGrammar::CONV_UNSPECIFIED),
25 : meStringConversion(StringConversion::LOCALE), // old LibreOffice behavior
26 11966 : mbEmptyStringAsZero(false)
27 : {
28 11966 : setOpenCLConfigToDefault();
29 :
30 : // SAL _DEBUG(__FILE__ ":" << __LINE__ << ": ScCalcConfig::ScCalcConfig(): " << *this);
31 11966 : }
32 :
33 11966 : void ScCalcConfig::setOpenCLConfigToDefault()
34 : {
35 : // Note that these defaults better be kept in sync with those in
36 : // officecfg/registry/schema/org/openoffice/Office/Calc.xcs.
37 : // Crazy.
38 11966 : mbOpenCLSubsetOnly = true;
39 11966 : mbOpenCLAutoSelect = true;
40 11966 : mnOpenCLMinimumFormulaGroupSize = 100;
41 :
42 : // Keep in order of opcode value, is that clearest? (Random order,
43 : // at least, would make no sense at all.)
44 11966 : maOpenCLSubsetOpCodes.insert(ocAdd);
45 11966 : maOpenCLSubsetOpCodes.insert(ocSub);
46 11966 : maOpenCLSubsetOpCodes.insert(ocMul);
47 11966 : maOpenCLSubsetOpCodes.insert(ocDiv);
48 11966 : maOpenCLSubsetOpCodes.insert(ocRandom);
49 11966 : maOpenCLSubsetOpCodes.insert(ocSin);
50 11966 : maOpenCLSubsetOpCodes.insert(ocCos);
51 11966 : maOpenCLSubsetOpCodes.insert(ocTan);
52 11966 : maOpenCLSubsetOpCodes.insert(ocArcTan);
53 11966 : maOpenCLSubsetOpCodes.insert(ocExp);
54 11966 : maOpenCLSubsetOpCodes.insert(ocLn);
55 11966 : maOpenCLSubsetOpCodes.insert(ocSqrt);
56 11966 : maOpenCLSubsetOpCodes.insert(ocStdNormDist);
57 11966 : maOpenCLSubsetOpCodes.insert(ocSNormInv);
58 11966 : maOpenCLSubsetOpCodes.insert(ocRound);
59 11966 : maOpenCLSubsetOpCodes.insert(ocPower);
60 11966 : maOpenCLSubsetOpCodes.insert(ocSumProduct);
61 11966 : maOpenCLSubsetOpCodes.insert(ocMin);
62 11966 : maOpenCLSubsetOpCodes.insert(ocMax);
63 11966 : maOpenCLSubsetOpCodes.insert(ocSum);
64 11966 : maOpenCLSubsetOpCodes.insert(ocProduct);
65 11966 : maOpenCLSubsetOpCodes.insert(ocAverage);
66 11966 : maOpenCLSubsetOpCodes.insert(ocCount);
67 11966 : maOpenCLSubsetOpCodes.insert(ocVar);
68 11966 : maOpenCLSubsetOpCodes.insert(ocNormDist);
69 11966 : maOpenCLSubsetOpCodes.insert(ocCorrel);
70 11966 : maOpenCLSubsetOpCodes.insert(ocCovar);
71 11966 : maOpenCLSubsetOpCodes.insert(ocPearson);
72 11966 : maOpenCLSubsetOpCodes.insert(ocSlope);
73 11966 : maOpenCLSubsetOpCodes.insert(ocSumIfs);
74 11966 : }
75 :
76 54 : void ScCalcConfig::reset()
77 : {
78 54 : *this = ScCalcConfig();
79 54 : }
80 :
81 11804 : void ScCalcConfig::MergeDocumentSpecific( const ScCalcConfig& r )
82 : {
83 : // String conversion options are per document.
84 11804 : meStringConversion = r.meStringConversion;
85 11804 : mbEmptyStringAsZero = r.mbEmptyStringAsZero;
86 : // INDIRECT ref syntax is per document.
87 11804 : meStringRefAddressSyntax = r.meStringRefAddressSyntax;
88 11804 : }
89 :
90 0 : bool ScCalcConfig::operator== (const ScCalcConfig& r) const
91 : {
92 0 : return meStringRefAddressSyntax == r.meStringRefAddressSyntax &&
93 0 : meStringConversion == r.meStringConversion &&
94 0 : mbEmptyStringAsZero == r.mbEmptyStringAsZero &&
95 0 : mbOpenCLSubsetOnly == r.mbOpenCLSubsetOnly &&
96 0 : mbOpenCLAutoSelect == r.mbOpenCLAutoSelect &&
97 0 : maOpenCLDevice == r.maOpenCLDevice &&
98 0 : mnOpenCLMinimumFormulaGroupSize == r.mnOpenCLMinimumFormulaGroupSize &&
99 0 : maOpenCLSubsetOpCodes == r.maOpenCLSubsetOpCodes &&
100 0 : true;
101 : }
102 :
103 0 : bool ScCalcConfig::operator!= (const ScCalcConfig& r) const
104 : {
105 0 : return !operator==(r);
106 : }
107 :
108 : namespace {
109 :
110 0 : OUString StringConversionToString(ScCalcConfig::StringConversion eConv)
111 : {
112 0 : switch (eConv)
113 : {
114 0 : case ScCalcConfig::StringConversion::ILLEGAL: return OUString("ILLEGAL");
115 0 : case ScCalcConfig::StringConversion::ZERO: return OUString("ZERO");
116 0 : case ScCalcConfig::StringConversion::UNAMBIGUOUS: return OUString("UNAMBIGUOUS");
117 0 : case ScCalcConfig::StringConversion::LOCALE: return OUString("LOCALE");
118 0 : default: return OUString::number((int) eConv);
119 : }
120 : }
121 :
122 : } // anonymous namespace
123 :
124 0 : std::ostream& operator<<(std::ostream& rStream, const ScCalcConfig& rConfig)
125 : {
126 : rStream << "{"
127 0 : "StringRefAddressSyntax=" << rConfig.meStringRefAddressSyntax << ","
128 0 : "StringConversion=" << StringConversionToString(rConfig.meStringConversion) << ","
129 0 : "EmptyStringAsZero=" << (rConfig.mbEmptyStringAsZero?"Y":"N") << ","
130 0 : "OpenCLSubsetOnly=" << (rConfig.mbOpenCLSubsetOnly?"Y":"N") << ","
131 0 : "OpenCLAutoSelect=" << (rConfig.mbOpenCLAutoSelect?"Y":"N") << ","
132 0 : "OpenCLDevice='" << rConfig.maOpenCLDevice << "',"
133 0 : "OpenCLMinimumFormulaGroupSize=" << rConfig.mnOpenCLMinimumFormulaGroupSize << ","
134 0 : "OpenCLSubsetOpCodes={" << ScOpCodeSetToSymbolicString(rConfig.maOpenCLSubsetOpCodes) << "},"
135 0 : "}";
136 0 : return rStream;
137 : }
138 :
139 49 : OUString ScOpCodeSetToSymbolicString(const ScCalcConfig::OpCodeSet& rOpCodes)
140 : {
141 49 : OUStringBuffer result;
142 98 : formula::FormulaCompiler aCompiler;
143 98 : formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(aCompiler.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH));
144 :
145 1519 : for (auto i = rOpCodes.cbegin(); i != rOpCodes.cend(); ++i)
146 : {
147 1470 : if (i != rOpCodes.cbegin())
148 1421 : result.append(';');
149 1470 : result.append(pOpCodeMap->getSymbol(*i));
150 : }
151 :
152 98 : return result.toString();
153 : }
154 :
155 49 : ScCalcConfig::OpCodeSet ScStringToOpCodeSet(const OUString& rOpCodes)
156 : {
157 49 : ScCalcConfig::OpCodeSet result;
158 98 : formula::FormulaCompiler aCompiler;
159 98 : formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(aCompiler.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH));
160 :
161 49 : const formula::OpCodeHashMap *pHashMap(pOpCodeMap->getHashMap());
162 :
163 49 : sal_Int32 fromIndex(0);
164 : sal_Int32 semicolon;
165 98 : OUString s(rOpCodes + ";");
166 :
167 1568 : while ((semicolon = s.indexOf(';', fromIndex)) >= 0)
168 : {
169 1470 : if (semicolon > fromIndex)
170 : {
171 1470 : OUString element(s.copy(fromIndex, semicolon - fromIndex));
172 1470 : sal_Int32 n = element.toInt32();
173 1470 : if (n > 0 || (n == 0 && element == "0"))
174 0 : result.insert(static_cast<OpCode>(n));
175 : else
176 : {
177 1470 : auto opcode(pHashMap->find(element));
178 1470 : if (opcode != pHashMap->end())
179 1470 : result.insert(static_cast<OpCode>(opcode->second));
180 : else
181 : SAL_WARN("sc.opencl", "Unrecognized OpCode " << element << " in OpCode set string");
182 1470 : }
183 : }
184 1470 : fromIndex = semicolon+1;
185 : }
186 98 : return result;
187 156 : }
188 :
189 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|