Files
libreoffice/sc/source/core/tool/calcconfig.cxx
Tor Lillqvist ad582ce757 Drop Add, Sub, Mul and Div from the default opcode subset
Those are supposed to obey the current setting for "Conversion from text to
number", and the OpenCL code does not currently take that setting into
consideration.

Change-Id: Iff6eeda6238c78f4aeb8eb27898ce7ea243b9dea
2015-01-12 20:42:16 +02:00

204 lines
6.5 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <ostream>
#include <set>
#include <formula/FormulaCompiler.hxx>
#include <formula/grammar.hxx>
#include <formula/opcode.hxx>
#include <rtl/ustring.hxx>
#include <sfx2/objsh.hxx>
#include "calcconfig.hxx"
#include "compiler.hxx"
#include "docsh.hxx"
ScCalcConfig::ScCalcConfig() :
meStringRefAddressSyntax(formula::FormulaGrammar::CONV_UNSPECIFIED),
meStringConversion(STRING_CONVERSION_LOCALE_DEPENDENT), // old LibreOffice behavior
mbEmptyStringAsZero(false)
{
setOpenCLConfigToDefault();
// SAL _DEBUG(__FILE__ ":" << __LINE__ << ": ScCalcConfig::ScCalcConfig(): " << *this);
}
void ScCalcConfig::setOpenCLConfigToDefault()
{
// Note that these defaults better be kept in sync with those in
// officecfg/registry/schema/org/openoffice/Office/Calc.xcs.
// Crazy.
mbOpenCLSubsetOnly = true;
mbOpenCLAutoSelect = true;
mnOpenCLMinimumFormulaGroupSize = 10000;
// Keep in order of opcode value, is that clearest? (Random order,
// at least, would make no sense at all.)
maOpenCLSubsetOpCodes.insert(ocRandom);
maOpenCLSubsetOpCodes.insert(ocSin);
maOpenCLSubsetOpCodes.insert(ocCos);
maOpenCLSubsetOpCodes.insert(ocTan);
maOpenCLSubsetOpCodes.insert(ocArcTan);
maOpenCLSubsetOpCodes.insert(ocExp);
maOpenCLSubsetOpCodes.insert(ocLn);
maOpenCLSubsetOpCodes.insert(ocSqrt);
maOpenCLSubsetOpCodes.insert(ocSNormInv);
maOpenCLSubsetOpCodes.insert(ocRound);
maOpenCLSubsetOpCodes.insert(ocPower);
maOpenCLSubsetOpCodes.insert(ocSumProduct);
maOpenCLSubsetOpCodes.insert(ocMin);
maOpenCLSubsetOpCodes.insert(ocMax);
maOpenCLSubsetOpCodes.insert(ocSum);
maOpenCLSubsetOpCodes.insert(ocProduct);
maOpenCLSubsetOpCodes.insert(ocAverage);
maOpenCLSubsetOpCodes.insert(ocCount);
maOpenCLSubsetOpCodes.insert(ocNormDist);
maOpenCLSubsetOpCodes.insert(ocSumIfs);
}
void ScCalcConfig::reset()
{
*this = ScCalcConfig();
}
void ScCalcConfig::MergeDocumentSpecific( const ScCalcConfig& r )
{
// String conversion options are per document.
meStringConversion = r.meStringConversion;
mbEmptyStringAsZero = r.mbEmptyStringAsZero;
// INDIRECT ref syntax is per document.
meStringRefAddressSyntax = r.meStringRefAddressSyntax;
}
bool ScCalcConfig::operator== (const ScCalcConfig& r) const
{
return meStringRefAddressSyntax == r.meStringRefAddressSyntax &&
meStringConversion == r.meStringConversion &&
mbEmptyStringAsZero == r.mbEmptyStringAsZero &&
mbOpenCLSubsetOnly == r.mbOpenCLSubsetOnly &&
mbOpenCLAutoSelect == r.mbOpenCLAutoSelect &&
maOpenCLDevice == r.maOpenCLDevice &&
mnOpenCLMinimumFormulaGroupSize == r.mnOpenCLMinimumFormulaGroupSize &&
maOpenCLSubsetOpCodes == r.maOpenCLSubsetOpCodes &&
true;
}
bool ScCalcConfig::operator!= (const ScCalcConfig& r) const
{
return !operator==(r);
}
std::ostream& operator<<(std::ostream& rStream, const ScCalcConfig& rConfig)
{
rStream << "{"
"StringRefAddressSyntax=" << rConfig.meStringRefAddressSyntax << ","
"StringConversion=" << rConfig.meStringConversion << ","
"EmptyStringAsZero=" << (rConfig.mbEmptyStringAsZero?"Y":"N") << ","
"OpenCLSubsetOnly=" << (rConfig.mbOpenCLSubsetOnly?"Y":"N") << ","
"OpenCLAutoSelect=" << (rConfig.mbOpenCLAutoSelect?"Y":"N") << ","
"OpenCLDevice='" << rConfig.maOpenCLDevice << "',"
"OpenCLMinimumFormulaGroupSize=" << rConfig.mnOpenCLMinimumFormulaGroupSize << ","
"OpenCLSubsetOpCodes={" << ScOpCodeSetToSymbolicString(rConfig.maOpenCLSubsetOpCodes) << "},"
"}";
return rStream;
}
namespace {
formula::FormulaCompiler::OpCodeMapPtr setup()
{
SfxObjectShell* pObjShell = SfxObjectShell::Current();
ScDocShell* pScDocShell = PTR_CAST(ScDocShell, pObjShell);
if (pScDocShell)
{
ScDocument& rDoc(pScDocShell->GetDocument());
ScCompiler* pComp(new ScCompiler(&rDoc, ScAddress()));
return pComp->GetOpCodeMap(css::sheet::FormulaLanguage::NATIVE);
}
return nullptr;
}
} // anonymous namespace
OUString ScOpCodeSetToNumberString(const ScCalcConfig::OpCodeSet& rOpCodes)
{
OUStringBuffer result;
for (auto i = rOpCodes.cbegin(); i != rOpCodes.cend(); ++i)
{
if (i != rOpCodes.cbegin())
result.append(';');
result.append(static_cast<sal_Int32>(*i));
}
return result.toString();
}
OUString ScOpCodeSetToSymbolicString(const ScCalcConfig::OpCodeSet& rOpCodes)
{
OUStringBuffer result;
formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(setup());
if (!pOpCodeMap)
return ScOpCodeSetToNumberString(rOpCodes);
for (auto i = rOpCodes.cbegin(); i != rOpCodes.cend(); ++i)
{
if (i != rOpCodes.cbegin())
result.append(';');
result.append(pOpCodeMap->getSymbol(*i));
}
return result.toString();
}
ScCalcConfig::OpCodeSet ScStringToOpCodeSet(const OUString& rOpCodes)
{
ScCalcConfig::OpCodeSet result;
formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(setup());
OUString s(rOpCodes + ";");
const formula::OpCodeHashMap *pHashMap(nullptr);
if (pOpCodeMap)
pHashMap = pOpCodeMap->getHashMap();
sal_Int32 fromIndex(0);
sal_Int32 semicolon;
while ((semicolon = s.indexOf(';', fromIndex)) >= 0)
{
if (semicolon > fromIndex)
{
OUString element(s.copy(fromIndex, semicolon - fromIndex));
sal_Int32 n = element.toInt32();
if (n > 0 || (n == 0 && element == "0"))
result.insert(static_cast<OpCode>(n));
else if (pHashMap)
{
auto opcode(pHashMap->find(element));
if (opcode != pHashMap->end())
result.insert(static_cast<OpCode>(opcode->second));
else
SAL_WARN("sc.opencl", "Unrecognized OpCode " << element << " in OpCode set string");
}
else
{
SAL_WARN("sc.opencl", "No current doc, can't convert from OpCode name to value");
}
}
fromIndex = semicolon+1;
}
return result;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */