33#include <rtl/math.hxx>
35#include <osl/diagnose.h>
41#include <mdds/multi_type_matrix.hpp>
42#include <mdds/multi_type_vector/types.hpp>
64 typedef mdds::mtv::custom_block_func1<sc::string_block> element_block_func;
73double convertStringToValue(
ScInterpreter* pErrorInterpreter,
const OUString& rStr )
75 if (pErrorInterpreter)
80 if (nError != FormulaError::NONE)
82 pErrorInterpreter->
SetError( nError);
92 double operator() (
double val)
const
94 if (!std::isfinite(val))
96 return val == 0.0 ? 1.0 : 0.0;
100struct ElemNotEqualZero
102 double operator() (
double val)
const
104 if (!std::isfinite(val))
106 return val != 0.0 ? 1.0 : 0.0;
110struct ElemGreaterZero
112 double operator() (
double val)
const
114 if (!std::isfinite(val))
116 return val > 0.0 ? 1.0 : 0.0;
122 double operator() (
double val)
const
124 if (!std::isfinite(val))
126 return val < 0.0 ? 1.0 : 0.0;
130struct ElemGreaterEqualZero
132 double operator() (
double val)
const
134 if (!std::isfinite(val))
136 return val >= 0.0 ? 1.0 : 0.0;
140struct ElemLessEqualZero
142 double operator() (
double val)
const
144 if (!std::isfinite(val))
146 return val <= 0.0 ? 1.0 : 0.0;
150template<
typename Comp>
151class CompareMatrixElemFunc
155 std::vector<double> maNewMatValues;
159 CompareMatrixElemFunc(
size_t nRow,
size_t nCol ) :
mnRow(nRow),
mnCol(nCol)
161 maNewMatValues.reserve(nRow*nCol);
164 CompareMatrixElemFunc(
const CompareMatrixElemFunc& ) =
delete;
165 CompareMatrixElemFunc& operator= (
const CompareMatrixElemFunc& ) =
delete;
167 CompareMatrixElemFunc( CompareMatrixElemFunc&& ) =
default;
168 CompareMatrixElemFunc& operator= ( CompareMatrixElemFunc&& ) =
default;
170 void operator() (
const MatrixImplType::element_block_node_type& node)
174 case mdds::mtm::element_numeric:
176 typedef MatrixImplType::numeric_block_type block_type;
178 block_type::const_iterator it = block_type::begin(*node.data);
179 block_type::const_iterator itEnd = block_type::end(*node.data);
180 for (; it != itEnd; ++it)
183 maNewMatValues.push_back(maComp(fVal));
187 case mdds::mtm::element_boolean:
189 typedef MatrixImplType::boolean_block_type block_type;
191 block_type::const_iterator it = block_type::begin(*node.data);
192 block_type::const_iterator itEnd = block_type::end(*node.data);
193 for (; it != itEnd; ++it)
195 double fVal = *it ? 1.0 : 0.0;
196 maNewMatValues.push_back(maComp(fVal));
200 case mdds::mtm::element_string:
201 case mdds::mtm::element_empty:
204 maNewMatValues.resize(maNewMatValues.size() + node.size, 0.0);
215template<
typename Comp>
216Comp CompareMatrixElemFunc<Comp>::maComp;
239 ScMatrixImpl(
size_t nC,
size_t nR,
const std::vector<double>& rInitVals );
309 size_t Count(
bool bCountStrings,
bool bCountErrors,
bool bIgnoreEmptyStrings)
const;
313 double GetMaxValue(
bool bTextAsZero,
bool bIgnoreErrorValues )
const;
314 double GetMinValue(
bool bTextAsZero,
bool bIgnoreErrorValues )
const;
320 void GetDoubleArray( std::vector<double>& rArray,
bool bEmptyAsZero )
const;
331 template<
typename T,
typename tRes>
361 constexpr size_t nPerElem = 12;
363 return nMemory / nPerElem;
366 constexpr size_t nMemMax = 0x40000000;
368 constexpr size_t nElemMax = nMemMax / nPerElem;
370 constexpr size_t nArbitraryLimit = size_t(
MAXROWCOUNT) * 128;
372 return std::min(nElemMax, nArbitraryLimit);
376 maMat(nR, nC), maMatFlag(nR, nC), pErrorInterpreter(nullptr)
382 maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(nullptr)
388 maMat(nR, nC, rInitVals.
begin(), rInitVals.
end()), maMatFlag(nR, nC), pErrorInterpreter(nullptr)
410 maMat.resize(nR, nC);
427 maMat.resize(nR, nC, fVal);
446 MatrixImplType::size_pair_type aSize =
maMat.size();
453 MatrixImplType::size_pair_type aSize =
maMat.size();
454 return aSize.row * aSize.column;
459 MatrixImplType::size_pair_type aSize =
maMat.size();
460 return nR < aSize.row && nC < aSize.column;
465 MatrixImplType::size_pair_type aSize =
maMat.size();
466 if (aSize.column == 1 && aSize.row == 1)
472 else if (aSize.column == 1 && rR < aSize.row)
478 else if (aSize.row == 1 && rC < aSize.column)
501 maMat.set(nR, nC, fVal);
504 OSL_FAIL(
"ScMatrixImpl::PutDouble: dimension error");
511 maMat.set(nR, nC, pArray, pArray + nLen);
514 OSL_FAIL(
"ScMatrixImpl::PutDouble: dimension error");
528 maMat.set(nR, nC, rStr);
531 OSL_FAIL(
"ScMatrixImpl::PutString: dimension error");
538 maMat.set(nR, nC, pArray, pArray + nLen);
541 OSL_FAIL(
"ScMatrixImpl::PutString: dimension error");
556 maMat.set_empty(nR, nC);
561 OSL_FAIL(
"ScMatrixImpl::PutEmpty: dimension error");
569 maMat.set_empty(nR, nC);
574 OSL_FAIL(
"ScMatrixImpl::PutEmptyPath: dimension error");
586 maMat.set(nR, nC, bVal);
589 OSL_FAIL(
"ScMatrixImpl::PutBoolean: dimension error");
597 double fVal =
maMat.get_numeric(nR, nC);
602 OSL_FAIL(
"ScMatrixImpl::GetError: dimension error");
603 return FormulaError::NoValue;
611 double fVal =
maMat.get_numeric(nR, nC);
615 if ( nError != FormulaError::NONE )
622 OSL_FAIL(
"ScMatrixImpl::GetDouble: dimension error");
647 MatrixImplType::const_position_type aPos =
maMat.position(nR, nC);
648 switch (
maMat.get_type(aPos))
650 case mdds::mtm::element_string:
651 return maMat.get_string(aPos);
652 case mdds::mtm::element_empty:
654 case mdds::mtm::element_numeric:
655 case mdds::mtm::element_boolean:
656 fErr =
maMat.get_numeric(aPos);
659 OSL_FAIL(
"ScMatrixImpl::GetString: access error, no string");
665 OSL_FAIL(
"ScMatrixImpl::GetString: dimension error");
681 OSL_FAIL(
"ScMatrixImpl::GetString: dimension error");
686 MatrixImplType::const_position_type aPos =
maMat.position(nR, nC);
687 switch (
maMat.get_type(aPos))
689 case mdds::mtm::element_string:
690 return maMat.get_string(aPos);
691 case mdds::mtm::element_empty:
701 const Color* pColor =
nullptr;
705 case mdds::mtm::element_numeric:
706 case mdds::mtm::element_boolean:
707 fVal =
maMat.get_numeric(aPos);
714 if (nError != FormulaError::NONE)
732 MatrixImplType::const_position_type aPos =
maMat.position(nR, nC);
733 mdds::mtm::element_t
eType =
maMat.get_type(aPos);
736 case mdds::mtm::element_boolean:
738 aVal.
fVal = double(
maMat.get_boolean(aPos));
740 case mdds::mtm::element_numeric:
744 case mdds::mtm::element_string:
748 case mdds::mtm::element_empty:
753 case mdds::mtm::element_empty:
756 case mdds::mtm::element_numeric:
771 OSL_FAIL(
"ScMatrixImpl::Get: dimension error");
786 switch (
maMat.get_type(nR, nC))
788 case mdds::mtm::element_empty:
789 case mdds::mtm::element_string:
802 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
811 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
812 maMatFlag.get_type(nR, nC) == mdds::mtm::element_empty;
820 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
828 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
844 switch (
maMat.get_type(nR, nC))
846 case mdds::mtm::element_boolean:
847 case mdds::mtm::element_numeric:
858 switch (
maMat.get_type(nR, nC))
860 case mdds::mtm::element_boolean:
861 case mdds::mtm::element_numeric:
862 case mdds::mtm::element_empty:
873 return maMat.get_type(nR, nC) == mdds::mtm::element_boolean;
878 return maMat.numeric();
886 OSL_FAIL(
"ScMatrixImpl::MatCopy: dimension error");
896 mRes.
maMat.transpose();
903 for (
SCSIZE j = nC1; j <= nC2; ++j)
906 std::vector<double> aVals(nR2-nR1+1, fVal);
907 maMat.set(nR1, j, aVals.begin(), aVals.end());
912 OSL_FAIL(
"ScMatrixImpl::FillDouble: dimension error");
920 maMat.set(nR, nC, rVec.begin(), rVec.end());
924 OSL_FAIL(
"ScMatrixImpl::PutDoubleVector: dimension error");
932 maMat.set(nR, nC, rVec.begin(), rVec.end());
936 OSL_FAIL(
"ScMatrixImpl::PutStringVector: dimension error");
950 OSL_FAIL(
"ScMatrixImpl::PutEmptyVector: dimension error");
961 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
965 OSL_FAIL(
"ScMatrixImpl::PutEmptyResultVector: dimension error");
976 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
980 OSL_FAIL(
"ScMatrixImpl::PutEmptyPathVector: dimension error");
986 MatrixImplType::size_pair_type aSize =
maMat.size();
987 CompareMatrixElemFunc<ElemEqualZero> aFunc(aSize.row, aSize.column);
988 aFunc =
maMat.walk(std::move(aFunc));
994 MatrixImplType::size_pair_type aSize =
maMat.size();
995 CompareMatrixElemFunc<ElemNotEqualZero> aFunc(aSize.row, aSize.column);
996 aFunc =
maMat.walk(std::move(aFunc));
1002 MatrixImplType::size_pair_type aSize =
maMat.size();
1003 CompareMatrixElemFunc<ElemLessZero> aFunc(aSize.row, aSize.column);
1004 aFunc =
maMat.walk(std::move(aFunc));
1010 MatrixImplType::size_pair_type aSize =
maMat.size();
1011 CompareMatrixElemFunc<ElemGreaterZero> aFunc(aSize.row, aSize.column);
1012 aFunc =
maMat.walk(std::move(aFunc));
1018 MatrixImplType::size_pair_type aSize =
maMat.size();
1019 CompareMatrixElemFunc<ElemLessEqualZero> aFunc(aSize.row, aSize.column);
1020 aFunc =
maMat.walk(std::move(aFunc));
1026 MatrixImplType::size_pair_type aSize =
maMat.size();
1027 CompareMatrixElemFunc<ElemGreaterEqualZero> aFunc(aSize.row, aSize.column);
1028 aFunc =
maMat.walk(std::move(aFunc));
1037 void operate(
double fVal) { mbResult &= (fVal != 0.0); }
1038 bool result()
const {
return mbResult; }
1039 AndEvaluator() : mbResult(true) {}
1045 void operate(
double fVal) { mbResult |= (fVal != 0.0); }
1046 bool result()
const {
return mbResult; }
1047 OrEvaluator() : mbResult(false) {}
1053 void operate(
double fVal) { mbResult ^= (fVal != 0.0); }
1054 bool result()
const {
return mbResult; }
1055 XorEvaluator() : mbResult(false) {}
1060template <
typename Evaluator>
1064 size_t nRows = rMat.size().row, nCols = rMat.size().column;
1065 for (
size_t i = 0;
i < nRows; ++
i)
1067 for (
size_t j = 0; j < nCols; ++j)
1069 MatrixImplType::const_position_type aPos = rMat.position(i, j);
1070 mdds::mtm::element_t
eType = rMat.get_type(aPos);
1071 if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
1075 double fVal = rMat.get_numeric(aPos);
1076 if (!std::isfinite(fVal))
1080 aEval.operate(fVal);
1083 return aEval.result();
1092 return EvalMatrix<AndEvaluator>(
maMat);
1099 return EvalMatrix<OrEvaluator>(
maMat);
1106 return EvalMatrix<XorEvaluator>(
maMat);
1111template<
typename Op,
typename tRes>
1112class WalkElementBlocks
1116 bool mbTextAsZero:1;
1117 bool mbIgnoreErrorValues:1;
1119 WalkElementBlocks(
bool bTextAsZero,
bool bIgnoreErrorValues) :
1120 maRes(
Op::InitVal, 0),
1121 mbTextAsZero(bTextAsZero), mbIgnoreErrorValues(bIgnoreErrorValues)
1126 void operator() (
const MatrixImplType::element_block_node_type& node)
1130 case mdds::mtm::element_numeric:
1132 typedef MatrixImplType::numeric_block_type block_type;
1134 size_t nIgnored = 0;
1135 block_type::const_iterator it = block_type::begin(*node.data);
1136 block_type::const_iterator itEnd = block_type::end(*node.data);
1137 for (; it != itEnd; ++it)
1139 if (mbIgnoreErrorValues && !std::isfinite(*it))
1146 maRes.
mnCount += node.size - nIgnored;
1149 case mdds::mtm::element_boolean:
1151 typedef MatrixImplType::boolean_block_type block_type;
1153 block_type::const_iterator it = block_type::begin(*node.data);
1154 block_type::const_iterator itEnd = block_type::end(*node.data);
1155 for (; it != itEnd; ++it)
1162 case mdds::mtm::element_string:
1166 case mdds::mtm::element_empty:
1173template<
typename Op,
typename tRes>
1174class WalkElementBlocksMultipleValues
1176 const std::vector<Op>* mpOp;
1179 WalkElementBlocksMultipleValues(
const std::vector<Op>& aOp) :
1180 mpOp(&aOp), maRes(0)
1182 for (
const auto& rpOp : *mpOp)
1186 WalkElementBlocksMultipleValues(
const WalkElementBlocksMultipleValues& ) =
delete;
1187 WalkElementBlocksMultipleValues& operator= (
const WalkElementBlocksMultipleValues& ) =
delete;
1189 WalkElementBlocksMultipleValues(WalkElementBlocksMultipleValues&& r) noexcept
1190 : mpOp(r.mpOp), maRes(r.maRes.mnCount)
1195 WalkElementBlocksMultipleValues& operator=(WalkElementBlocksMultipleValues&& r)
noexcept
1199 maRes.
mnCount = r.maRes.mnCount;
1205 void operator() (
const MatrixImplType::element_block_node_type& node)
1209 case mdds::mtm::element_numeric:
1211 typedef MatrixImplType::numeric_block_type block_type;
1213 block_type::const_iterator it = block_type::begin(*node.data);
1214 block_type::const_iterator itEnd = block_type::end(*node.data);
1215 for (; it != itEnd; ++it)
1217 for (
size_t i = 0u;
i < mpOp->size(); ++
i)
1223 case mdds::mtm::element_boolean:
1225 typedef MatrixImplType::boolean_block_type block_type;
1227 block_type::const_iterator it = block_type::begin(*node.data);
1228 block_type::const_iterator itEnd = block_type::end(*node.data);
1229 for (; it != itEnd; ++it)
1231 for (
size_t i = 0u;
i < mpOp->size(); ++
i)
1237 case mdds::mtm::element_string:
1238 case mdds::mtm::element_empty:
1250 bool mbIgnoreEmptyStrings;
1252 explicit CountElements(
bool bCountString,
bool bCountErrors,
bool bIgnoreEmptyStrings) :
1253 mnCount(0), mbCountString(bCountString), mbCountErrors(bCountErrors),
1254 mbIgnoreEmptyStrings(bIgnoreEmptyStrings) {}
1256 size_t getCount()
const {
return mnCount; }
1258 void operator() (
const MatrixImplType::element_block_node_type& node)
1262 case mdds::mtm::element_numeric:
1266 typedef MatrixImplType::numeric_block_type block_type;
1268 block_type::const_iterator it = block_type::begin(*node.data);
1269 block_type::const_iterator itEnd = block_type::end(*node.data);
1270 for (; it != itEnd; ++it)
1272 if (!std::isfinite(*it))
1277 case mdds::mtm::element_boolean:
1280 case mdds::mtm::element_string:
1284 if (mbIgnoreEmptyStrings)
1286 typedef MatrixImplType::string_block_type block_type;
1288 block_type::const_iterator it = block_type::begin(*node.data);
1289 block_type::const_iterator itEnd = block_type::end(*node.data);
1290 for (; it != itEnd; ++it)
1298 case mdds::mtm::element_empty:
1305const size_t ResultNotSet = std::numeric_limits<size_t>::max();
1307template<
typename Type>
1308class WalkAndMatchElements
1317 WalkAndMatchElements(
Type aMatchValue,
const MatrixImplType::size_pair_type& aSize,
size_t nCol1,
size_t nCol2) :
1318 maMatchValue(aMatchValue),
1320 mnStopIndex( (nCol2 + 1) * aSize.row ),
1321 mnResult(ResultNotSet),
1324 assert( nCol1 < aSize.column && nCol2 < aSize.column);
1327 size_t getMatching()
const {
return mnResult; }
1329 size_t getRemainingCount()
const
1334 size_t compare(
const MatrixImplType::element_block_node_type& node)
const;
1336 void operator() (
const MatrixImplType::element_block_node_type& node)
1339 if (mnResult != ResultNotSet)
1343 if (mnStartIndex <= mnIndex && getRemainingCount() > 0)
1353size_t WalkAndMatchElements<double>::compare(
const MatrixImplType::element_block_node_type& node)
const
1358 case mdds::mtm::element_numeric:
1360 typedef MatrixImplType::numeric_block_type block_type;
1362 block_type::const_iterator it = block_type::begin(*node.data);
1363 block_type::const_iterator itEnd = block_type::end(*node.data);
1364 const size_t nRemaining = getRemainingCount();
1365 for (; it != itEnd &&
nCount < nRemaining; ++it, ++
nCount)
1367 if (*it == maMatchValue)
1374 case mdds::mtm::element_boolean:
1376 typedef MatrixImplType::boolean_block_type block_type;
1378 block_type::const_iterator it = block_type::begin(*node.data);
1379 block_type::const_iterator itEnd = block_type::end(*node.data);
1380 const size_t nRemaining = getRemainingCount();
1381 for (; it != itEnd &&
nCount < nRemaining; ++it, ++
nCount)
1383 if (
int(*it) == maMatchValue)
1391 case mdds::mtm::element_string:
1392 case mdds::mtm::element_empty:
1396 return ResultNotSet;
1400size_t WalkAndMatchElements<svl::SharedString>::compare(
const MatrixImplType::element_block_node_type& node)
const
1404 case mdds::mtm::element_string:
1407 typedef MatrixImplType::string_block_type block_type;
1409 block_type::const_iterator it = block_type::begin(*node.data);
1410 block_type::const_iterator itEnd = block_type::end(*node.data);
1411 const size_t nRemaining = getRemainingCount();
1412 for (; it != itEnd &&
nCount < nRemaining; ++it, ++
nCount)
1414 if (it->getDataIgnoreCase() == maMatchValue.getDataIgnoreCase())
1421 case mdds::mtm::element_boolean:
1422 case mdds::mtm::element_numeric:
1423 case mdds::mtm::element_empty:
1427 return ResultNotSet;
1432 static double init() {
return -std::numeric_limits<double>::max(); }
1433 static double compare(
double left,
double right)
1435 if (!std::isfinite(left))
1437 if (!std::isfinite(right))
1439 return std::max(left, right);
1442 static double boolValue(
1443 MatrixImplType::boolean_block_type::const_iterator it,
1444 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1447 it = std::find(it, itEnd,
true);
1448 return it == itEnd ? 0.0 : 1.0;
1454 static double init() {
return std::numeric_limits<double>::max(); }
1455 static double compare(
double left,
double right)
1457 if (!std::isfinite(left))
1459 if (!std::isfinite(right))
1461 return std::min(left, right);
1464 static double boolValue(
1465 MatrixImplType::boolean_block_type::const_iterator it,
1466 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1469 it = std::find(it, itEnd,
false);
1470 return it == itEnd ? 1.0 : 0.0;
1476 static double init() {
return 1.0; }
1477 static double calculate(
double fx,
double fy)
1482 static double boolValue(
1483 MatrixImplType::boolean_block_type::const_iterator it,
1484 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1487 it = std::find(it, itEnd,
false);
1488 return it == itEnd ? 1.0 : 0.0;
1494 static double init() {
return 0.0; }
1495 static double calculate(
double fx,
double fy)
1500 static double boolValue(
1501 MatrixImplType::boolean_block_type::const_iterator it,
1502 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1505 it = std::find(it, itEnd,
true);
1506 return it == itEnd ? 0.0 : 1.0;
1510template<
typename Op>
1511class CalcMaxMinValue
1515 bool mbIgnoreErrorValues;
1518 CalcMaxMinValue(
bool bTextAsZero,
bool bIgnoreErrorValues ) :
1520 mbTextAsZero(bTextAsZero),
1521 mbIgnoreErrorValues(bIgnoreErrorValues),
1522 mbHasValue(false) {}
1524 double getValue()
const {
return mbHasValue ?
mfVal : 0.0; }
1526 void operator() (
const MatrixImplType::element_block_node_type& node)
1531 case mdds::mtm::element_numeric:
1533 typedef MatrixImplType::numeric_block_type block_type;
1535 block_type::const_iterator it = block_type::begin(*node.data);
1536 block_type::const_iterator itEnd = block_type::end(*node.data);
1537 if (mbIgnoreErrorValues)
1539 for (; it != itEnd; ++it)
1541 if (std::isfinite(*it))
1547 for (; it != itEnd; ++it)
1554 case mdds::mtm::element_boolean:
1556 typedef MatrixImplType::boolean_block_type block_type;
1558 block_type::const_iterator it = block_type::begin(*node.data);
1559 block_type::const_iterator itEnd = block_type::end(*node.data);
1560 double fVal = Op::boolValue(it, itEnd);
1565 case mdds::mtm::element_string:
1566 case mdds::mtm::element_empty:
1582template<
typename Op>
1588 CalcGcdLcm() : mfval(
Op::
init()) {}
1590 double getResult()
const {
return mfval; }
1592 void operator() (
const MatrixImplType::element_block_node_type& node )
1596 case mdds::mtm::element_numeric:
1598 typedef MatrixImplType::numeric_block_type block_type;
1599 block_type::const_iterator it = block_type::begin(*node.data);
1600 block_type::const_iterator itEnd = block_type::end(*node.data);
1602 for ( ; it != itEnd; ++it)
1607 mfval = ::rtl::math::approxFloor( Op::calculate(*it,mfval));
1611 case mdds::mtm::element_boolean:
1613 typedef MatrixImplType::boolean_block_type block_type;
1614 block_type::const_iterator it = block_type::begin(*node.data);
1615 block_type::const_iterator itEnd = block_type::end(*node.data);
1617 mfval = Op::boolValue(it, itEnd);
1620 case mdds::mtm::element_empty:
1621 case mdds::mtm::element_string:
1632double evaluate(
double fVal,
ScQueryOp eOp )
1634 if (!std::isfinite(fVal))
1640 return fVal == 0.0 ? 1.0 : 0.0;
1642 return fVal < 0.0 ? 1.0 : 0.0;
1644 return fVal > 0.0 ? 1.0 : 0.0;
1646 return fVal <= 0.0 ? 1.0 : 0.0;
1648 return fVal >= 0.0 ? 1.0 : 0.0;
1650 return fVal != 0.0 ? 1.0 : 0.0;
1655 SAL_WARN(
"sc.core",
"evaluate: unhandled comparison operator: " <<
static_cast<int>(eOp));
1659class CompareMatrixFunc
1664 std::vector<double> maResValues;
1669 maResValues.push_back(evaluate(fVal, mrComp.
meOp));
1674 mrComp(rComp), mnMatPos(nMatPos), mpOptions(pOptions)
1676 maResValues.reserve(nResSize);
1679 CompareMatrixFunc(
const CompareMatrixFunc& ) =
delete;
1680 CompareMatrixFunc& operator= (
const CompareMatrixFunc& ) =
delete;
1682 CompareMatrixFunc(CompareMatrixFunc&& r) noexcept :
1684 mnMatPos(r.mnMatPos),
1685 mpOptions(r.mpOptions),
1686 maResValues(std::move(r.maResValues)) {}
1688 CompareMatrixFunc& operator=(CompareMatrixFunc&& r)
noexcept
1691 mnMatPos = r.mnMatPos;
1692 mpOptions = r.mpOptions;
1693 maResValues = std::move(r.maResValues);
1697 void operator() (
const MatrixImplType::element_block_node_type& node)
1703 case mdds::mtm::element_numeric:
1705 typedef MatrixImplType::numeric_block_type block_type;
1707 block_type::const_iterator it = block_type::begin(*node.data);
1708 block_type::const_iterator itEnd = block_type::end(*node.data);
1709 for (; it != itEnd; ++it)
1718 case mdds::mtm::element_boolean:
1720 typedef MatrixImplType::boolean_block_type block_type;
1722 block_type::const_iterator it = block_type::begin(*node.data);
1723 block_type::const_iterator itEnd = block_type::end(*node.data);
1724 for (; it != itEnd; ++it)
1733 case mdds::mtm::element_string:
1735 typedef MatrixImplType::string_block_type block_type;
1737 block_type::const_iterator it = block_type::begin(*node.data);
1738 block_type::const_iterator itEnd = block_type::end(*node.data);
1739 for (; it != itEnd; ++it)
1749 case mdds::mtm::element_empty:
1754 for (
size_t i = 0;
i < node.size; ++
i)
1763 const std::vector<double>& getValues()
const
1772class CompareMatrixToNumericFunc
1775 double mfRightValue;
1777 std::vector<double> maResValues;
1782 maResValues.push_back(evaluate(fVal, mrComp.
meOp));
1785 void compareLeftNumeric(
double fLeftVal )
1788 maResValues.push_back(evaluate(fVal, mrComp.
meOp));
1791 void compareLeftEmpty(
size_t nSize )
1794 bool bRes = evaluate(fVal, mrComp.
meOp);
1795 maResValues.resize(maResValues.size() + nSize, bRes ? 1.0 : 0.0);
1800 mrComp(rComp), mfRightValue(fRightValue), mpOptions(pOptions)
1802 maResValues.reserve(nResSize);
1805 CompareMatrixToNumericFunc(
const CompareMatrixToNumericFunc& ) =
delete;
1806 CompareMatrixToNumericFunc& operator= (
const CompareMatrixToNumericFunc& ) =
delete;
1808 CompareMatrixToNumericFunc(CompareMatrixToNumericFunc&& r) noexcept :
1810 mfRightValue(r.mfRightValue),
1811 mpOptions(r.mpOptions),
1812 maResValues(std::move(r.maResValues)) {}
1814 CompareMatrixToNumericFunc& operator=(CompareMatrixToNumericFunc&& r)
noexcept
1817 mfRightValue = r.mfRightValue;
1818 mpOptions = r.mpOptions;
1819 maResValues = std::move(r.maResValues);
1823 void operator() (
const MatrixImplType::element_block_node_type& node)
1827 case mdds::mtm::element_numeric:
1829 typedef MatrixImplType::numeric_block_type block_type;
1831 block_type::const_iterator it = block_type::begin(*node.data);
1832 block_type::const_iterator itEnd = block_type::end(*node.data);
1833 for (; it != itEnd; ++it)
1834 compareLeftNumeric(*it);
1837 case mdds::mtm::element_boolean:
1839 typedef MatrixImplType::boolean_block_type block_type;
1841 block_type::const_iterator it = block_type::begin(*node.data);
1842 block_type::const_iterator itEnd = block_type::end(*node.data);
1843 for (; it != itEnd; ++it)
1844 compareLeftNumeric(
double(*it));
1847 case mdds::mtm::element_string:
1849 typedef MatrixImplType::string_block_type block_type;
1851 block_type::const_iterator it = block_type::begin(*node.data);
1852 block_type::const_iterator itEnd = block_type::end(*node.data);
1853 for (; it != itEnd; ++it)
1864 case mdds::mtm::element_empty:
1865 compareLeftEmpty(node.size);
1872 const std::vector<double>& getValues()
const
1880 std::vector<double> maArray;
1881 std::vector<double>::iterator miPos;
1885 void moveArray( ToDoubleArray& r )
1890 size_t n = std::distance(r.maArray.begin(), r.miPos);
1891 maArray = std::move(r.maArray);
1892 miPos = maArray.begin();
1893 std::advance(miPos, n);
1897 ToDoubleArray(
size_t nSize,
bool bEmptyAsZero ) :
1898 maArray(nSize, 0.0), miPos(maArray.
begin()), mbEmptyAsZero(bEmptyAsZero)
1903 ToDoubleArray(
const ToDoubleArray& ) =
delete;
1904 ToDoubleArray& operator= (
const ToDoubleArray& ) =
delete;
1906 ToDoubleArray(ToDoubleArray&& r) noexcept :
1907 mfNaN(r.mfNaN), mbEmptyAsZero(r.mbEmptyAsZero)
1912 ToDoubleArray& operator=(ToDoubleArray&& r)
noexcept
1915 mbEmptyAsZero = r.mbEmptyAsZero;
1920 void operator() (
const MatrixImplType::element_block_node_type& node)
1922 using namespace mdds::mtv;
1926 case mdds::mtm::element_numeric:
1928 double_element_block::const_iterator it = double_element_block::begin(*node.data);
1929 double_element_block::const_iterator itEnd = double_element_block::end(*node.data);
1930 for (; it != itEnd; ++it, ++miPos)
1934 case mdds::mtm::element_boolean:
1936 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
1937 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
1938 for (; it != itEnd; ++it, ++miPos)
1939 *miPos = *it ? 1.0 : 0.0;
1942 case mdds::mtm::element_string:
1944 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
1948 case mdds::mtm::element_empty:
1952 std::advance(miPos, node.size);
1956 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
1965 void swap(std::vector<double>& rOther)
1967 maArray.swap(rOther);
1973 double operator() (
const double& lhs,
const double& rhs)
const
1979template<
typename Op>
1980class MergeDoubleArrayFunc
1982 std::vector<double>::iterator miPos;
1985 MergeDoubleArrayFunc(std::vector<double>& rArray) : miPos(rArray.
begin())
1990 MergeDoubleArrayFunc(
const MergeDoubleArrayFunc& ) =
delete;
1991 MergeDoubleArrayFunc& operator= (
const MergeDoubleArrayFunc& ) =
delete;
1993 MergeDoubleArrayFunc( MergeDoubleArrayFunc&& ) =
default;
1994 MergeDoubleArrayFunc& operator= ( MergeDoubleArrayFunc&& ) =
default;
1996 void operator() (
const MatrixImplType::element_block_node_type& node)
1998 using namespace mdds::mtv;
2003 case mdds::mtm::element_numeric:
2005 double_element_block::const_iterator it = double_element_block::begin(*node.data);
2006 double_element_block::const_iterator itEnd = double_element_block::end(*node.data);
2007 for (; it != itEnd; ++it, ++miPos)
2012 *miPos = op(*miPos, *it);
2016 case mdds::mtm::element_boolean:
2018 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
2019 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
2020 for (; it != itEnd; ++it, ++miPos)
2025 *miPos = op(*miPos, *it ? 1.0 : 0.0);
2029 case mdds::mtm::element_string:
2031 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
2035 case mdds::mtm::element_empty:
2038 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
2043 *miPos = op(*miPos, 0.0);
2057template<
typename TOp,
typename tRes>
2060 WalkElementBlocks<TOp, tRes> aFunc(bTextAsZero, bIgnoreErrorValues);
2061 aFunc = maMat.walk(aFunc);
2062 return aFunc.getResult();
2069 return GetValueWithCount<sc::op::Sum, KahanSum>(bTextAsZero, bIgnoreErrorValues,
maMat);
2074 return GetValueWithCount<sc::op::SumSquare, KahanSum>(bTextAsZero, bIgnoreErrorValues,
maMat);
2079 return GetValueWithCount<sc::op::Product, double>(bTextAsZero, bIgnoreErrorValues,
maMat);
2084 CountElements aFunc(bCountStrings, bCountErrors, bIgnoreEmptyStrings);
2085 aFunc =
maMat.walk(aFunc);
2086 return aFunc.getCount();
2091 WalkAndMatchElements<double> aFunc(fValue,
maMat.size(), nCol1, nCol2);
2092 aFunc =
maMat.walk(aFunc);
2093 return aFunc.getMatching();
2098 WalkAndMatchElements<svl::SharedString> aFunc(rStr,
maMat.size(), nCol1, nCol2);
2099 aFunc =
maMat.walk(aFunc);
2100 return aFunc.getMatching();
2105 CalcMaxMinValue<MaxOp> aFunc(bTextAsZero, bIgnoreErrorValues);
2106 aFunc =
maMat.walk(aFunc);
2107 return aFunc.getValue();
2112 CalcMaxMinValue<MinOp> aFunc(bTextAsZero, bIgnoreErrorValues);
2113 aFunc =
maMat.walk(aFunc);
2114 return aFunc.getValue();
2119 CalcGcdLcm<Gcd> aFunc;
2120 aFunc =
maMat.walk(aFunc);
2121 return aFunc.getResult();
2126 CalcGcdLcm<Lcm> aFunc;
2127 aFunc =
maMat.walk(aFunc);
2128 return aFunc.getResult();
2134 MatrixImplType::size_pair_type aSize =
maMat.size();
2135 size_t nSize = aSize.column * aSize.row;
2143 CompareMatrixToNumericFunc aFunc(nSize, rComp, rComp.
maCells[1].
mfValue, pOptions);
2144 aFunc =
maMat.walk(std::move(aFunc));
2147 const std::vector<double>& rResVal = aFunc.getValues();
2148 assert (nSize == rResVal.size());
2149 if (nSize != rResVal.size())
2156 CompareMatrixFunc aFunc(nSize, rComp, nMatPos, pOptions);
2157 aFunc =
maMat.walk(std::move(aFunc));
2160 const std::vector<double>& rResVal = aFunc.getValues();
2161 assert (nSize == rResVal.size());
2162 if (nSize != rResVal.size())
2170 MatrixImplType::size_pair_type aSize =
maMat.size();
2171 ToDoubleArray aFunc(aSize.row*aSize.column, bEmptyAsZero);
2172 aFunc =
maMat.walk(std::move(aFunc));
2178 MatrixImplType::size_pair_type aSize =
maMat.size();
2179 size_t nSize = aSize.row*aSize.column;
2180 if (nSize != rArray.size())
2183 MergeDoubleArrayFunc<ArrayMul> aFunc(rArray);
2184 maMat.walk(std::move(aFunc));
2189template<
typename T,
typename U,
typename return_type>
2190struct wrapped_iterator
2192 typedef ::std::bidirectional_iterator_tag iterator_category;
2193 typedef typename T::const_iterator::value_type old_value_type;
2194 typedef return_type value_type;
2195 typedef value_type* pointer;
2196 typedef value_type& reference;
2197 typedef typename T::const_iterator::difference_type difference_type;
2199 typename T::const_iterator it;
2200 mutable value_type val;
2205 value_type calcVal()
const
2212 wrapped_iterator(
typename T::const_iterator
const & it_, U
const & aOp):
2219 wrapped_iterator(
const wrapped_iterator& r):
2226 wrapped_iterator& operator=(
const wrapped_iterator& r)
2232 bool operator==(
const wrapped_iterator& r)
const
2237 bool operator!=(
const wrapped_iterator& r)
const
2249 wrapped_iterator& operator--()
2262 pointer operator->()
const
2269template<
typename T,
typename U,
typename return_type>
2270struct MatrixIteratorWrapper
2273 typename T::const_iterator m_itBegin;
2274 typename T::const_iterator m_itEnd;
2277 MatrixIteratorWrapper(
typename T::const_iterator
const & itBegin,
typename T::const_iterator
const & itEnd, U
const & aOp):
2284 wrapped_iterator<T, U, return_type>
begin()
2286 return wrapped_iterator<T, U, return_type>(m_itBegin,
maOp);
2289 wrapped_iterator<T, U, return_type>
end()
2291 return wrapped_iterator<T, U, return_type>(m_itEnd,
maOp);
2295MatrixImplType::position_type increment_position(
const MatrixImplType::position_type& pos,
size_t n)
2297 MatrixImplType::position_type ret =
pos;
2300 if (ret.second + n < ret.first->size)
2307 n -= (ret.first->size - ret.second);
2317struct MatrixOpWrapper
2321 MatrixImplType::position_type
pos;
2332 MatrixOpWrapper(
const MatrixOpWrapper& r ) : mrMat(r.mrMat),
pos(r.
pos), mpOp(r.mpOp) {}
2334 MatrixOpWrapper& operator= (
const MatrixOpWrapper& r ) =
default;
2336 void operator()(
const MatrixImplType::element_block_node_type& node)
2340 case mdds::mtm::element_numeric:
2342 typedef MatrixImplType::numeric_block_type block_type;
2344 block_type::const_iterator it = block_type::begin(*node.data);
2345 block_type::const_iterator itEnd = block_type::end(*node.data);
2346 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, *mpOp);
2347 pos = mrMat.set(pos,aFunc.begin(), aFunc.end());
2350 case mdds::mtm::element_boolean:
2352 typedef MatrixImplType::boolean_block_type block_type;
2354 block_type::const_iterator it = block_type::begin(*node.data);
2355 block_type::const_iterator itEnd = block_type::end(*node.data);
2357 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, *mpOp);
2358 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2361 case mdds::mtm::element_string:
2363 typedef MatrixImplType::string_block_type block_type;
2365 block_type::const_iterator it = block_type::begin(*node.data);
2366 block_type::const_iterator itEnd = block_type::end(*node.data);
2368 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, *mpOp);
2369 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2372 case mdds::mtm::element_empty:
2374 if (mpOp->useFunctionForEmpty())
2376 std::vector<char> aVec(node.size);
2377 MatrixIteratorWrapper<std::vector<char>, T,
typename T::number_value_type>
2378 aFunc(aVec.begin(), aVec.end(), *mpOp);
2379 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2386 pos = increment_position(pos, node.size);
2395 MatrixOpWrapper<T> aFunc(rMat.
maMat, aOp);
2399template<
typename T,
typename tRes>
2402 WalkElementBlocksMultipleValues<T, tRes> aFunc(aOp);
2403 aFunc =
maMat.walk(std::move(aFunc));
2404 return aFunc.getResult();
2411 ElementBlock(
size_t nRowSize,
2416 mnRowSize(nRowSize),
2419 maDoubleFunc(aDoubleFunc),
2420 maBoolFunc(aBoolFunc),
2421 maStringFunc(aStringFunc),
2422 maEmptyFunc(aEmptyFunc)
2436class WalkElementBlockOperation
2440 WalkElementBlockOperation(ElementBlock& rElementBlock)
2441 : mrElementBlock(rElementBlock)
2445 void operator()(
const MatrixImplType::element_block_node_type& node)
2449 case mdds::mtm::element_numeric:
2451 typedef MatrixImplType::numeric_block_type block_type;
2453 block_type::const_iterator it = block_type::begin(*node.data);
2454 std::advance(it, node.offset);
2455 block_type::const_iterator itEnd = it;
2456 std::advance(itEnd, node.size);
2457 for (
auto itr = it; itr != itEnd; ++itr)
2459 mrElementBlock.maDoubleFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos, *itr);
2460 ++mrElementBlock.mnRowPos;
2461 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2463 mrElementBlock.mnRowPos = 0;
2464 ++mrElementBlock.mnColPos;
2469 case mdds::mtm::element_string:
2471 typedef MatrixImplType::string_block_type block_type;
2473 block_type::const_iterator it = block_type::begin(*node.data);
2474 std::advance(it, node.offset);
2475 block_type::const_iterator itEnd = it;
2476 std::advance(itEnd, node.size);
2477 for (
auto itr = it; itr != itEnd; ++itr)
2479 mrElementBlock.maStringFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos, *itr);
2480 ++mrElementBlock.mnRowPos;
2481 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2483 mrElementBlock.mnRowPos = 0;
2484 ++mrElementBlock.mnColPos;
2489 case mdds::mtm::element_boolean:
2491 typedef MatrixImplType::boolean_block_type block_type;
2493 block_type::const_iterator it = block_type::begin(*node.data);
2494 std::advance(it, node.offset);
2495 block_type::const_iterator itEnd = it;
2496 std::advance(itEnd, node.size);
2497 for (
auto itr = it; itr != itEnd; ++itr)
2499 mrElementBlock.maBoolFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos, *itr);
2500 ++mrElementBlock.mnRowPos;
2501 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2503 mrElementBlock.mnRowPos = 0;
2504 ++mrElementBlock.mnColPos;
2509 case mdds::mtm::element_empty:
2511 for (
size_t i=0;
i < node.size; ++
i)
2513 mrElementBlock.maEmptyFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos);
2514 ++mrElementBlock.mnRowPos;
2515 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2517 mrElementBlock.mnRowPos = 0;
2518 ++mrElementBlock.mnColPos;
2523 case mdds::mtm::element_integer:
2525 SAL_WARN(
"sc.core",
"WalkElementBlockOperation - unhandled element_integer");
2527 mrElementBlock.mnColPos += node.size / mrElementBlock.mnRowSize;
2528 mrElementBlock.mnRowPos += node.size % mrElementBlock.mnRowSize;
2529 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2531 mrElementBlock.mnRowPos = 0;
2532 ++mrElementBlock.mnColPos;
2541 ElementBlock& mrElementBlock;
2551 ElementBlock aPayload(
maMat.size().row, aDoubleFunc, aBoolFunc, aStringFunc, aEmptyFunc);
2552 WalkElementBlockOperation aFunc(aPayload);
2555 MatrixImplType::size_pair_type(rStartPos.first, rStartPos.second),
2556 MatrixImplType::size_pair_type(rEndPos.first, rEndPos.second));
2561void ScMatrixImpl::Dump()
const
2563 cout <<
"-- matrix content" <<
endl;
2566 for (
SCSIZE nRow = 0; nRow < nRows; ++nRow)
2568 for (
SCSIZE nCol = 0; nCol < nCols; ++nCol)
2570 cout <<
" row=" << nRow <<
", col=" << nCol <<
" : ";
2571 switch (
maMat.get_type(nRow, nCol))
2573 case mdds::mtm::element_string:
2574 cout <<
"string (" <<
maMat.get_string(nRow, nCol).getString() <<
")";
2576 case mdds::mtm::element_numeric:
2577 cout <<
"numeric (" <<
maMat.get_numeric(nRow, nCol) <<
")";
2579 case mdds::mtm::element_boolean:
2580 cout <<
"boolean (" <<
maMat.get_boolean(nRow, nCol) <<
")";
2582 case mdds::mtm::element_empty:
2598 SAL_WARN_IF( !nRowSize,
"sc.core",
"ScMatrixImpl::CalcPosition: 0 rows!");
2600 rR =
nIndex - rC*nRowSize;
2605size_t get_index(
SCSIZE nMaxRow,
size_t nRow,
size_t nCol,
size_t nRowOffset,
size_t nColOffset)
2607 return nMaxRow * (nCol + nColOffset) + nRow + nRowOffset;
2617 xMat1->GetDimensions(nC1, nR1);
2618 xMat2->GetDimensions(nC2, nR2);
2623 std::vector<OUString> aString(nMaxCol * nMaxRow);
2624 std::vector<bool> aValid(nMaxCol * nMaxRow,
true);
2625 std::vector<FormulaError> nErrors(nMaxCol * nMaxRow,FormulaError::NONE);
2627 size_t nRowOffset = 0;
2628 size_t nColOffset = 0;
2629 std::function<void(
size_t,
size_t,
double)> aDoubleFunc =
2630 [&](
size_t nRow,
size_t nCol,
double nVal)
2633 if (nErr != FormulaError::NONE)
2635 aValid[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
false;
2636 nErrors[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = nErr;
2641 aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr;
2644 std::function<void(
size_t,
size_t,
bool)> aBoolFunc =
2645 [&](
size_t nRow,
size_t nCol,
bool nVal)
2649 aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr;
2655 aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr.getString();
2658 std::function<void(
size_t,
size_t)> aEmptyFunc =
2659 [](
size_t ,
size_t )
2665 if (nC1 == 1 || nR1 == 1)
2667 size_t nRowRep = nR1 == 1 ? nMaxRow : 1;
2668 size_t nColRep = nC1 == 1 ? nMaxCol : 1;
2670 for (
size_t i = 0;
i < nRowRep; ++
i)
2673 for (
size_t j = 0; j < nColRep; ++j)
2676 xMat1->ExecuteOperation(
2677 std::pair<size_t, size_t>(0, 0),
2678 std::pair<size_t, size_t>(std::min(nR1, nMaxRow) - 1, std::min(nC1, nMaxCol) - 1),
2679 aDoubleFunc, aBoolFunc, aStringFunc, aEmptyFunc);
2684 xMat1->ExecuteOperation(
2685 std::pair<size_t, size_t>(0, 0),
2686 std::pair<size_t, size_t>(nMaxRow - 1, nMaxCol - 1),
2687 aDoubleFunc, aBoolFunc, aStringFunc, aEmptyFunc);
2689 std::vector<svl::SharedString> aSharedString(nMaxCol*nMaxRow);
2691 std::function<void(
size_t,
size_t,
double)> aDoubleFunc2 =
2692 [&](
size_t nRow,
size_t nCol,
double nVal)
2695 if (nErr != FormulaError::NONE)
2697 aValid[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
false;
2698 nErrors[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = nErr;
2703 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr);
2706 std::function<void(
size_t,
size_t,
bool)> aBoolFunc2 =
2707 [&](
size_t nRow,
size_t nCol,
bool nVal)
2711 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr);
2717 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
2718 rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr.getString());
2721 std::function<void(
size_t,
size_t)> aEmptyFunc2 =
2722 [&](
size_t nRow,
size_t nCol)
2724 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
2725 rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)]);
2730 if (nC2 == 1 || nR2 == 1)
2732 size_t nRowRep = nR2 == 1 ? nMaxRow : 1;
2733 size_t nColRep = nC2 == 1 ? nMaxCol : 1;
2735 for (
size_t i = 0;
i < nRowRep; ++
i)
2738 for (
size_t j = 0; j < nColRep; ++j)
2741 xMat2->ExecuteOperation(
2742 std::pair<size_t, size_t>(0, 0),
2743 std::pair<size_t, size_t>(std::min(nR2, nMaxRow) - 1, std::min(nC2, nMaxCol) - 1),
2744 aDoubleFunc2, aBoolFunc2, aStringFunc2, aEmptyFunc2);
2749 xMat2->ExecuteOperation(
2750 std::pair<size_t, size_t>(0, 0),
2751 std::pair<size_t, size_t>(nMaxRow - 1, nMaxCol - 1),
2752 aDoubleFunc2, aBoolFunc2, aStringFunc2, aEmptyFunc2);
2756 MatrixImplType::position_type
pos =
maMat.position(0, 0);
2759 for (
SCSIZE j = 0; j < nMaxRow &&
i < nMaxCol; ++j)
2761 if (aValid[nMaxRow *
i + j])
2763 auto itr = aValid.begin();
2764 std::advance(itr, nMaxRow *
i + j);
2765 auto itrEnd = std::find(itr, aValid.end(),
false);
2766 size_t nSteps = std::distance(itr, itrEnd);
2767 auto itrStr = aSharedString.begin();
2768 std::advance(itrStr, nMaxRow *
i + j);
2769 auto itrEndStr = itrStr;
2770 std::advance(itrEndStr, nSteps);
2772 size_t nColSteps = nSteps / nMaxRow;
2774 j += nSteps % nMaxRow;
2785 pos = MatrixImplType::next_position(
pos);
2804 SAL_WARN_IF( !nC,
"sc.core",
"ScMatrix with 0 columns!");
2805 SAL_WARN_IF( !nR,
"sc.core",
"ScMatrix with 0 rows!");
2807 if ((nC && !nR) || (!nC && nR))
2809 SAL_WARN(
"sc.core",
"ScMatrix one-dimensional zero: " << nC <<
" columns * " << nR <<
" rows");
2817 const char* pEnv = std::getenv(
"SC_MAX_MATRIX_ELEMENTS");
2828#if SAL_TYPES_SIZEOFPOINTER < 8
2830 constexpr size_t nMemMax = 0x40000000;
2833 constexpr size_t nMemMax = 0x180000000;
2842 SAL_WARN(
"sc.core",
"ScMatrix overflow: " << nC <<
" columns * " << nR <<
" rows");
2849 nRefCnt(0), mbCloneIfConst(true)
2859 nRefCnt(0), mbCloneIfConst(true)
2869 nRefCnt(0), mbCloneIfConst(true)
2885 pImpl->GetDimensions(nC, nR);
2909 pImpl->Resize(nC, nR);
2914 pImpl->Resize(nC, nR, fVal);
2927 pImpl->SetErrorInterpreter(
p);
2932 pImpl->GetDimensions(rC, rR);
2937 return pImpl->GetElementCount();
2942 return pImpl->ValidColRow(nC, nR);
2947 return pImpl->ValidColRowReplicated(rC, rR);
2957 pImpl->PutDouble(fVal, nC, nR);
2967 pImpl->PutDouble(pArray, nLen, nC, nR);
2972 pImpl->PutString(rStr, nC, nR);
2982 pImpl->PutString(pArray, nLen, nC, nR);
2987 pImpl->PutEmpty(nC, nR);
2992 pImpl->PutEmptyPath(nC, nR);
2997 pImpl->PutError(nErrorCode, nC, nR);
3002 pImpl->PutBoolean(bVal, nC, nR);
3007 return pImpl->GetError(nC, nR);
3012 return pImpl->GetDouble(nC, nR);
3022 return pImpl->GetDoubleWithStringConversion(nC, nR);
3027 return pImpl->GetString(nC, nR);
3037 return pImpl->GetString(rFormatter, nC, nR);
3042 return pImpl->Get(nC, nR);
3052 return pImpl->IsStringOrEmpty(nC, nR);
3057 return pImpl->IsEmpty(nC, nR);
3062 return pImpl->IsEmptyCell(nC, nR);
3067 return pImpl->IsEmptyResult(nC, nR);
3072 return pImpl->IsEmptyPath(nC, nR);
3082 return pImpl->IsValue(nC, nR);
3087 return pImpl->IsValueOrEmpty(nC, nR);
3092 return pImpl->IsBoolean(nC, nR);
3097 return pImpl->IsNumeric();
3112 pImpl->FillDouble(fVal, nC1, nR1, nC2, nR2);
3117 pImpl->PutDoubleVector(rVec, nC, nR);
3122 pImpl->PutStringVector(rVec, nC, nR);
3142 pImpl->CompareEqual();
3147 pImpl->CompareNotEqual();
3152 pImpl->CompareLess();
3157 pImpl->CompareGreater();
3162 pImpl->CompareLessEqual();
3167 pImpl->CompareGreaterEqual();
3172 return pImpl->And();
3182 return pImpl->Xor();
3187 return pImpl->Sum(bTextAsZero, bIgnoreErrorValues);
3192 return pImpl->SumSquare(bTextAsZero, bIgnoreErrorValues);
3197 return pImpl->Product(bTextAsZero, bIgnoreErrorValues);
3200size_t ScMatrix::Count(
bool bCountStrings,
bool bCountErrors,
bool bIgnoreEmptyStrings)
const
3202 return pImpl->Count(bCountStrings, bCountErrors, bIgnoreEmptyStrings);
3207 return pImpl->MatchDoubleInColumns(fValue, nCol1, nCol2);
3212 return pImpl->MatchStringInColumns(rStr, nCol1, nCol2);
3217 return pImpl->GetMaxValue(bTextAsZero, bIgnoreErrorValues);
3222 return pImpl->GetMinValue(bTextAsZero, bIgnoreErrorValues);
3227 return pImpl->GetGcd();
3232 return pImpl->GetLcm();
3239 return pImpl->CompareMatrix(rComp, nMatPos, pOptions);
3244 pImpl->GetDoubleArray(rArray, bEmptyAsZero);
3249 pImpl->MergeDoubleArrayMultiply(rArray);
3263template<
typename TOp>
3272 typedef double number_value_type;
3275 double fVal = 0.0 ):
3283 if (nErr != FormulaError::NONE)
3288 double operator()(
double fVal)
const
3293 double operator()(
bool bVal)
const
3295 return maOp(
static_cast<double>(bVal),
mfVal);
3304 double operator()(
char)
const
3309 static bool useFunctionForEmpty()
3321 auto not_ = [](
double a, double){
return double(
a == 0.0);};
3322 matop::MatOp<
decltype(not_)> aOp(not_,
pImpl->GetErrorInterpreter());
3328 auto neg_ = [](
double a, double){
return -
a;};
3329 matop::MatOp<
decltype(neg_)> aOp(neg_,
pImpl->GetErrorInterpreter());
3335 auto add_ = [](
double a,
double b){
return a + b;};
3336 matop::MatOp<
decltype(add_)> aOp(add_,
pImpl->GetErrorInterpreter(), fVal);
3344 auto sub_ = [](
double a,
double b){
return b -
a;};
3345 matop::MatOp<
decltype(sub_)> aOp(sub_,
pImpl->GetErrorInterpreter(), fVal);
3350 auto sub_ = [](
double a,
double b){
return a - b;};
3351 matop::MatOp<
decltype(sub_)> aOp(sub_,
pImpl->GetErrorInterpreter(), fVal);
3358 auto mul_ = [](
double a,
double b){
return a * b;};
3359 matop::MatOp<
decltype(mul_)> aOp(mul_,
pImpl->GetErrorInterpreter(), fVal);
3367 auto div_ = [](
double a,
double b){
return sc::div(b,
a);};
3368 matop::MatOp<
decltype(div_)> aOp(div_,
pImpl->GetErrorInterpreter(), fVal);
3373 auto div_ = [](
double a,
double b){
return sc::div(
a, b);};
3374 matop::MatOp<
decltype(div_)> aOp(div_,
pImpl->GetErrorInterpreter(), fVal);
3383 auto pow_ = [](
double a,
double b){
return sc::power(b,
a);};
3384 matop::MatOp<
decltype(pow_)> aOp(pow_,
pImpl->GetErrorInterpreter(), fVal);
3389 auto pow_ = [](
double a,
double b){
return sc::power(
a, b);};
3390 matop::MatOp<
decltype(pow_)> aOp(pow_,
pImpl->GetErrorInterpreter(), fVal);
3399 pImpl->ExecuteOperation(rStartPos, rEndPos, aDoubleFunc, aBoolFunc, aStringFunc, aEmptyFunc);
3408void ScMatrix::Dump()
const
3417 pImpl->MatConcat(nMaxCol, nMaxRow, xMat1, xMat2, rFormatter, rPool);
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
FILE * init(int, char **)
This class provides LO with Kahan summation algorithm About this algorithm: https://en....
static SC_DLLPUBLIC LanguageType eLnge
static OUString GetErrorString(FormulaError nErrNumber)
void SetError(FormulaError nError)
double ConvertStringToValue(const OUString &)
FormulaError GetError() const
static double ScGetGCD(double fx, double fy)
void PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
void PutEmptyVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
bool IsStringOrEmpty(SCSIZE nIndex) const
void PutError(FormulaError nErrorCode, SCSIZE nC, SCSIZE nR)
bool IsEmptyPath(SCSIZE nC, SCSIZE nR) const
double GetMinValue(bool bTextAsZero, bool bIgnoreErrorValues) const
svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const
void PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
double GetMaxValue(bool bTextAsZero, bool bIgnoreErrorValues) const
FormulaError GetError(SCSIZE nC, SCSIZE nR) const
ScMatrix::IterateResultMultiple< tRes > ApplyCollectOperation(const std::vector< T > &aOp)
void FillDouble(double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2)
ScMatrix::KahanIterateResult SumSquare(bool bTextAsZero, bool bIgnoreErrorValues) const
void GetDoubleArray(std::vector< double > &rArray, bool bEmptyAsZero) const
ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const
void CompareGreaterEqual()
bool IsEmptyResult(SCSIZE nC, SCSIZE nR) const
ScInterpreter * pErrorInterpreter
void MatCopy(ScMatrixImpl &mRes) const
void SetErrorInterpreter(ScInterpreter *p)
ScMatrix::KahanIterateResult Sum(bool bTextAsZero, bool bIgnoreErrorValues) const
bool IsValueOrEmpty(SCSIZE nC, SCSIZE nR) const
ScMatrix::DoubleIterateResult Product(bool bTextAsZero, bool bIgnoreErrorValues) const
double GetDoubleWithStringConversion(SCSIZE nC, SCSIZE nR) const
void ExecuteOperation(const std::pair< size_t, size_t > &rStartPos, const std::pair< size_t, size_t > &rEndPos, const ScMatrix::DoubleOpFunction &aDoubleFunc, const ScMatrix::BoolOpFunction &aBoolFunc, const ScMatrix::StringOpFunction &aStringFunc, const ScMatrix::EmptyOpFunction &aEmptyFunc) const
void CalcPosition(SCSIZE nIndex, SCSIZE &rC, SCSIZE &rR) const
size_t MatchStringInColumns(const svl::SharedString &rStr, size_t nCol1, size_t nCol2) const
void PutStringVector(const ::std::vector< svl::SharedString > &rVec, SCSIZE nC, SCSIZE nR)
void PutEmpty(SCSIZE nC, SCSIZE nR)
ScMatrixRef CompareMatrix(sc::Compare &rComp, size_t nMatPos, sc::CompareOptions *pOptions) const
void PutDoubleVector(const ::std::vector< double > &rVec, SCSIZE nC, SCSIZE nR)
bool IsBoolean(SCSIZE nC, SCSIZE nR) const
bool ValidColRowReplicated(SCSIZE &rC, SCSIZE &rR) const
bool IsValue(SCSIZE nIndex) const
bool ValidColRowOrReplicated(SCSIZE &rC, SCSIZE &rR) const
bool IsEmpty(SCSIZE nC, SCSIZE nR) const
void PutEmptyPathVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
bool IsEmptyCell(SCSIZE nC, SCSIZE nR) const
void PutString(const svl::SharedString &rStr, SCSIZE nC, SCSIZE nR)
void MatTrans(ScMatrixImpl &mRes) const
void ApplyOperation(T aOp, ScMatrixImpl &rMat)
ScInterpreter * GetErrorInterpreter() const
void MergeDoubleArrayMultiply(std::vector< double > &rArray) const
void PutEmptyPath(SCSIZE nC, SCSIZE nR)
double GetDouble(SCSIZE nC, SCSIZE nR) const
void MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef &xMat1, const ScMatrixRef &xMat2, SvNumberFormatter &rFormatter, svl::SharedStringPool &rPool)
void SetErrorAtInterpreter(FormulaError nError) const
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
const ScMatrixImpl & operator=(const ScMatrixImpl &)=delete
void PutEmptyResultVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
void Resize(SCSIZE nC, SCSIZE nR)
SCSIZE GetElementCount() const
size_t Count(bool bCountStrings, bool bCountErrors, bool bIgnoreEmptyStrings) const
ScMatrixImpl(const ScMatrixImpl &)=delete
bool ValidColRow(SCSIZE nC, SCSIZE nR) const
Matrix data type that can store values of mixed types.
void PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const
@ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate an empty string!
svl::SharedString GetString(SCSIZE nC, SCSIZE nR) const
void NotOp(const ScMatrix &rMat)
bool IsStringOrEmpty(SCSIZE nIndex) const
void MatCopy(const ScMatrix &mRes) const
bool IsEmpty(SCSIZE nC, SCSIZE nR) const
void PutDoubleVector(const ::std::vector< double > &rVec, SCSIZE nC, SCSIZE nR)
Put a column vector of doubles, starting at row nR, must fit into dimensions.
std::function< void(size_t, size_t)> EmptyOpFunction
void NegOp(const ScMatrix &rMat)
void PutString(const svl::SharedString &rStr, SCSIZE nC, SCSIZE nR)
KahanIterateResult SumSquare(bool bTextAsZero, bool bIgnoreErrorValues=false) const
std::function< void(size_t, size_t, svl::SharedString)> StringOpFunction
void FillDouble(double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2)
bool IsBoolean(SCSIZE nC, SCSIZE nR) const
void SetErrorInterpreter(ScInterpreter *p)
ScMatrix * Clone() const
Clone the matrix.
size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
void SubOp(bool bFlag, double fVal, const ScMatrix &rMat)
double GetDouble(SCSIZE nC, SCSIZE nR) const
void ExecuteOperation(const std::pair< size_t, size_t > &rStartPos, const std::pair< size_t, size_t > &rEndPos, DoubleOpFunction aDoubleFunc, BoolOpFunction aBoolFunc, StringOpFunction aStringFunc, EmptyOpFunction aEmptyFunc) const
SCSIZE GetElementCount() const
void PutEmptyResultVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
Put a column vector of empty results, starting at row nR, must fit into dimensions.
KahanIterateResult Sum(bool bTextAsZero, bool bIgnoreErrorValues=false) const
bool IsValueOrEmpty(SCSIZE nC, SCSIZE nR) const
void SetMutable()
Set the matrix to mutable for CloneIfConst(), only the interpreter should do this and know the conseq...
std::function< void(size_t, size_t, double)> DoubleOpFunction
void PutEmptyPath(SCSIZE nC, SCSIZE nR)
Jump sal_False without path.
void AddOp(double fVal, const ScMatrix &rMat)
void MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef &xMat1, const ScMatrixRef &xMat2, SvNumberFormatter &rFormatter, svl::SharedStringPool &rPool)
FormulaError GetError(SCSIZE nC, SCSIZE nR) const
May be used before obtaining the double value of an element to avoid passing its NAN around.
void PutEmpty(SCSIZE nC, SCSIZE nR)
void PutEmptyPathVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
Put a column vector of empty paths, starting at row nR, must fit into dimensions.
static bool IsSizeAllocatable(SCSIZE nC, SCSIZE nR)
Checks nC or nR for zero and uses GetElementsMax() whether a matrix of the size of nC*nR could be all...
DoubleIterateResult Product(bool bTextAsZero, bool bIgnoreErrorValues=false) const
void MatTrans(const ScMatrix &mRes) const
void MergeDoubleArrayMultiply(std::vector< double > &rArray) const
ScMatrix(const ScMatrix &)=delete
void PutStringVector(const ::std::vector< svl::SharedString > &rVec, SCSIZE nC, SCSIZE nR)
Put a column vector of strings, starting at row nR, must fit into dimensions.
bool IsEmptyCell(SCSIZE nC, SCSIZE nR) const
void DivOp(bool bFlag, double fVal, const ScMatrix &rMat)
void PowOp(bool bFlag, double fVal, const ScMatrix &rMat)
double GetDoubleWithStringConversion(SCSIZE nC, SCSIZE nR) const
KahanIterateResultMultiple CollectKahan(const std::vector< sc::op::kOp > &aOp)
void Resize(SCSIZE nC, SCSIZE nR)
Resize the matrix to specified new dimension.
bool ValidColRowReplicated(SCSIZE &rC, SCSIZE &rR) const
For a row vector or column vector, if the position does not point into the vector but is a valid colu...
std::function< void(size_t, size_t, bool)> BoolOpFunction
friend class ScMatrixImpl
size_t Count(bool bCountStrings, bool bCountErrors, bool bIgnoreEmptyStrings=false) const
std::unique_ptr< ScMatrixImpl > pImpl
bool IsEmptyResult(SCSIZE nC, SCSIZE nR) const
bool ValidColRow(SCSIZE nC, SCSIZE nR) const
bool ValidColRowOrReplicated(SCSIZE &rC, SCSIZE &rR) const
Checks if the matrix position is within the matrix.
ScMatrixRef CompareMatrix(sc::Compare &rComp, size_t nMatPos, sc::CompareOptions *pOptions) const
void PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
void SetImmutable() const
Set the matrix to immutable for CloneIfConst(), only the interpreter should do this and know the cons...
bool IsEmptyPath(SCSIZE nC, SCSIZE nR) const
double GetMinValue(bool bTextAsZero, bool bIgnoreErrorValues=false) const
void GetDoubleArray(std::vector< double > &rArray, bool bEmptyAsZero=true) const
Convert the content of matrix into a linear array of numeric values.
void PutEmptyVector(SCSIZE nCount, SCSIZE nC, SCSIZE nR)
Put a column vector of empties, starting at row nR, must fit into dimensions.
void CompareGreaterEqual()
void MulOp(double fVal, const ScMatrix &rMat)
void PutError(FormulaError nErrorCode, SCSIZE nC, SCSIZE nR)
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
size_t MatchStringInColumns(const svl::SharedString &rStr, size_t nCol1, size_t nCol2) const
ScMatrix * CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
Clone the matrix and extend it to the new size.
ScMatrix * CloneIfConst()
Clone the matrix if mbCloneIfConst (immutable) is set, otherwise return this matrix,...
bool IsValue(SCSIZE nIndex) const
double GetMaxValue(bool bTextAsZero, bool bIgnoreErrorValues=false) const
SharedString intern(const OUString &rStr)
static const SharedString & getEmptyString()
OUString getString() const
#define suppress_fun_call_w_exception(expr)
double CreateDoubleError(FormulaError nErr)
FormulaError GetDoubleErrorValue(double fVal)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
enumrange< T >::Iterator begin(enumrange< T >)
Op_< std::function< void(KahanSum &, double)>, KahanSum > kOp
Op_< std::function< void(double &, double)>, double > Op
mdds::mtv::uint16_element_block uint16_block
double power(const double &fVal1, const double &fVal2)
Return pow(fVal1,fVal2) with error handling.
double CompareFunc(const Compare &rComp, CompareOptions *pOptions)
double div(const double &fNumerator, const double &fDenominator)
Return fNumerator/fDenominator if fDenominator!=0 else #DIV/0! error coded into double.
mdds::mtv::default_element_block< element_type_string, svl::SharedString > string_block
double CompareEmptyToNumericFunc(double fCell2)
Left cell is empty while the right cell is numeric.
HSLColor operator*(double nFactor, const HSLColor &rRHS)
mdds::multi_type_matrix< matrix_trait > MatrixImplType
SbxDecimal::CmpResult compare(SAL_UNUSED_PARAMETER const SbxDecimal &, SAL_UNUSED_PARAMETER const SbxDecimal &)
static size_t GetElementsMax(size_t nMemory)
The maximum number of elements a matrix or the pool may have at runtime.
mdds::multi_type_matrix< matrix_trait > MatrixImplType
static bool bElementsMaxFetched
ScInterpreter * mpErrorInterpreter
static size_t nElementsMax
const TMatFlag SC_MATFLAG_EMPTYPATH
const TMatFlag SC_MATFLAG_EMPTYRESULT
TOOLS_DLLPUBLIC SvStream & endl(SvStream &rStr)
Try NOT to use this struct.
When adding all numerical matrix elements for a scalar result such as summation, the interpreter want...
std::vector< tRes > maAccumulator
Iterator for executing one operation with the matrix data.
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
bool operator!=(const XclExpString &rLeft, const XclExpString &rRight)
bool operator==(const XclFontData &rLeft, const XclFontData &rRight)