33#include <rtl/math.hxx>
35#include <osl/diagnose.h>
43#include <mdds/multi_type_matrix.hpp>
44#include <mdds/multi_type_vector/types.hpp>
67struct matrix_flag_traits
70 typedef mdds::mtv::uint8_element_block integer_element_block;
80double convertStringToValue(
ScInterpreter* pErrorInterpreter,
const OUString& rStr )
82 if (pErrorInterpreter)
87 if (nError != FormulaError::NONE)
89 pErrorInterpreter->
SetError( nError);
99 double operator() (
double val)
const
101 if (!std::isfinite(val))
103 return val == 0.0 ? 1.0 : 0.0;
107struct ElemNotEqualZero
109 double operator() (
double val)
const
111 if (!std::isfinite(val))
113 return val != 0.0 ? 1.0 : 0.0;
117struct ElemGreaterZero
119 double operator() (
double val)
const
121 if (!std::isfinite(val))
123 return val > 0.0 ? 1.0 : 0.0;
129 double operator() (
double val)
const
131 if (!std::isfinite(val))
133 return val < 0.0 ? 1.0 : 0.0;
137struct ElemGreaterEqualZero
139 double operator() (
double val)
const
141 if (!std::isfinite(val))
143 return val >= 0.0 ? 1.0 : 0.0;
147struct ElemLessEqualZero
149 double operator() (
double val)
const
151 if (!std::isfinite(val))
153 return val <= 0.0 ? 1.0 : 0.0;
157template<
typename Comp>
158class CompareMatrixElemFunc
162 std::vector<double> maNewMatValues;
166 CompareMatrixElemFunc(
size_t nRow,
size_t nCol ) :
mnRow(nRow),
mnCol(nCol)
168 maNewMatValues.reserve(nRow*nCol);
171 CompareMatrixElemFunc(
const CompareMatrixElemFunc& ) =
delete;
172 CompareMatrixElemFunc& operator= (
const CompareMatrixElemFunc& ) =
delete;
174 CompareMatrixElemFunc( CompareMatrixElemFunc&& ) =
default;
175 CompareMatrixElemFunc& operator= ( CompareMatrixElemFunc&& ) =
default;
177 void operator() (
const MatrixImplType::element_block_node_type& node)
181 case mdds::mtm::element_numeric:
183 typedef MatrixImplType::numeric_block_type block_type;
185 block_type::const_iterator it = block_type::begin(*node.data);
186 block_type::const_iterator itEnd = block_type::end(*node.data);
187 for (; it != itEnd; ++it)
190 maNewMatValues.push_back(maComp(fVal));
194 case mdds::mtm::element_boolean:
196 typedef MatrixImplType::boolean_block_type block_type;
198 block_type::const_iterator it = block_type::begin(*node.data);
199 block_type::const_iterator itEnd = block_type::end(*node.data);
200 for (; it != itEnd; ++it)
202 double fVal = *it ? 1.0 : 0.0;
203 maNewMatValues.push_back(maComp(fVal));
207 case mdds::mtm::element_string:
208 case mdds::mtm::element_empty:
211 maNewMatValues.resize(maNewMatValues.size() + node.size, 0.0);
222template<
typename Comp>
223Comp CompareMatrixElemFunc<Comp>::maComp;
244 ScMatrixImpl(
size_t nC,
size_t nR,
const std::vector<double>& rInitVals );
314 size_t Count(
bool bCountStrings,
bool bCountErrors,
bool bIgnoreEmptyStrings)
const;
318 double GetMaxValue(
bool bTextAsZero,
bool bIgnoreErrorValues )
const;
319 double GetMinValue(
bool bTextAsZero,
bool bIgnoreErrorValues )
const;
325 void GetDoubleArray( std::vector<double>& rArray,
bool bEmptyAsZero )
const;
336 template<
typename T,
typename tRes>
344 bool IsValueOrEmpty(
const MatrixImplType::const_position_type & rPos )
const;
345 double GetDouble(
const MatrixImplType::const_position_type & rPos)
const;
347 bool IsValue(
const MatrixImplType::const_position_type & rPos )
const;
349 bool IsStringOrEmpty(
const MatrixImplType::const_position_type & rPos)
const;
376 constexpr size_t nPerElem = 12;
378 return nMemory / nPerElem;
381 constexpr size_t nMemMax = 0x40000000;
383 constexpr size_t nElemMax = nMemMax / nPerElem;
385 constexpr size_t nArbitraryLimit = size_t(
MAXROWCOUNT) * 128;
387 return std::min(nElemMax, nArbitraryLimit);
391 maMat(nR, nC), maMatFlag(nR, nC), pErrorInterpreter(nullptr)
397 maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(nullptr)
403 maMat(nR, nC, rInitVals.
begin(), rInitVals.
end()), maMatFlag(nR, nC), pErrorInterpreter(nullptr)
425 maMat.resize(nR, nC);
442 maMat.resize(nR, nC, fVal);
461 MatrixImplType::size_pair_type aSize =
maMat.size();
468 MatrixImplType::size_pair_type aSize =
maMat.size();
469 return aSize.row * aSize.column;
474 MatrixImplType::size_pair_type aSize =
maMat.size();
475 return nR < aSize.row && nC < aSize.column;
480 MatrixImplType::size_pair_type aSize =
maMat.size();
481 if (aSize.column == 1 && aSize.row == 1)
487 else if (aSize.column == 1 && rR < aSize.row)
493 else if (aSize.row == 1 && rC < aSize.column)
516 maMat.set(nR, nC, fVal);
519 OSL_FAIL(
"ScMatrixImpl::PutDouble: dimension error");
526 maMat.set(nR, nC, pArray, pArray + nLen);
529 OSL_FAIL(
"ScMatrixImpl::PutDouble: dimension error");
543 maMat.set(nR, nC, rStr);
546 OSL_FAIL(
"ScMatrixImpl::PutString: dimension error");
553 maMat.set(nR, nC, pArray, pArray + nLen);
556 OSL_FAIL(
"ScMatrixImpl::PutString: dimension error");
571 maMat.set_empty(nR, nC);
576 OSL_FAIL(
"ScMatrixImpl::PutEmpty: dimension error");
584 maMat.set_empty(nR, nC);
589 OSL_FAIL(
"ScMatrixImpl::PutEmptyPath: dimension error");
601 maMat.set(nR, nC, bVal);
604 OSL_FAIL(
"ScMatrixImpl::PutBoolean: dimension error");
612 double fVal =
maMat.get_numeric(nR, nC);
617 OSL_FAIL(
"ScMatrixImpl::GetError: dimension error");
618 return FormulaError::NoValue;
626 double fVal =
maMat.get_numeric(nR, nC);
630 if ( nError != FormulaError::NONE )
637 OSL_FAIL(
"ScMatrixImpl::GetDouble: dimension error");
665 OSL_FAIL(
"ScMatrixImpl::GetString: dimension error");
673 switch (
maMat.get_type(rPos))
675 case mdds::mtm::element_string:
676 return maMat.get_string(rPos);
677 case mdds::mtm::element_empty:
679 case mdds::mtm::element_numeric:
680 case mdds::mtm::element_boolean:
681 fErr =
maMat.get_numeric(rPos);
684 OSL_FAIL(
"ScMatrixImpl::GetString: access error, no string");
701 OSL_FAIL(
"ScMatrixImpl::GetString: dimension error");
706 MatrixImplType::const_position_type aPos =
maMat.position(nR, nC);
707 switch (
maMat.get_type(aPos))
709 case mdds::mtm::element_string:
710 return maMat.get_string(aPos);
711 case mdds::mtm::element_empty:
721 const Color* pColor =
nullptr;
725 case mdds::mtm::element_numeric:
726 case mdds::mtm::element_boolean:
727 fVal =
maMat.get_numeric(aPos);
734 if (nError != FormulaError::NONE)
752 MatrixImplType::const_position_type aPos =
maMat.position(nR, nC);
753 mdds::mtm::element_t
eType =
maMat.get_type(aPos);
756 case mdds::mtm::element_boolean:
758 aVal.
fVal = double(
maMat.get_boolean(aPos));
760 case mdds::mtm::element_numeric:
764 case mdds::mtm::element_string:
768 case mdds::mtm::element_empty:
773 case mdds::mtm::element_empty:
776 case mdds::mtm::element_integer:
791 OSL_FAIL(
"ScMatrixImpl::Get: dimension error");
808 switch (
maMat.get_type(nR, nC))
810 case mdds::mtm::element_empty:
811 case mdds::mtm::element_string:
826 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
837 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
838 maMatFlag.get_type(nR, nC) == mdds::mtm::element_empty;
848 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
856 return maMat.get_type(nR, nC) == mdds::mtm::element_empty &&
874 switch (
maMat.get_type(nR, nC))
876 case mdds::mtm::element_boolean:
877 case mdds::mtm::element_numeric:
890 switch (
maMat.get_type(nR, nC))
892 case mdds::mtm::element_boolean:
893 case mdds::mtm::element_numeric:
894 case mdds::mtm::element_empty:
907 return maMat.get_type(nR, nC) == mdds::mtm::element_boolean;
912 return maMat.numeric();
920 OSL_FAIL(
"ScMatrixImpl::MatCopy: dimension error");
930 mRes.
maMat.transpose();
937 for (
SCSIZE j = nC1; j <= nC2; ++j)
940 std::vector<double> aVals(nR2-nR1+1, fVal);
941 maMat.set(nR1, j, aVals.begin(), aVals.end());
946 OSL_FAIL(
"ScMatrixImpl::FillDouble: dimension error");
954 maMat.set(nR, nC, rVec.begin(), rVec.end());
958 OSL_FAIL(
"ScMatrixImpl::PutDoubleVector: dimension error");
966 maMat.set(nR, nC, rVec.begin(), rVec.end());
970 OSL_FAIL(
"ScMatrixImpl::PutStringVector: dimension error");
984 OSL_FAIL(
"ScMatrixImpl::PutEmptyVector: dimension error");
995 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
999 OSL_FAIL(
"ScMatrixImpl::PutEmptyResultVector: dimension error");
1010 maMatFlag.set(nR, nC, aVals.begin(), aVals.end());
1014 OSL_FAIL(
"ScMatrixImpl::PutEmptyPathVector: dimension error");
1020 MatrixImplType::size_pair_type aSize =
maMat.size();
1021 CompareMatrixElemFunc<ElemEqualZero> aFunc(aSize.row, aSize.column);
1022 aFunc =
maMat.walk(std::move(aFunc));
1028 MatrixImplType::size_pair_type aSize =
maMat.size();
1029 CompareMatrixElemFunc<ElemNotEqualZero> aFunc(aSize.row, aSize.column);
1030 aFunc =
maMat.walk(std::move(aFunc));
1036 MatrixImplType::size_pair_type aSize =
maMat.size();
1037 CompareMatrixElemFunc<ElemLessZero> aFunc(aSize.row, aSize.column);
1038 aFunc =
maMat.walk(std::move(aFunc));
1044 MatrixImplType::size_pair_type aSize =
maMat.size();
1045 CompareMatrixElemFunc<ElemGreaterZero> aFunc(aSize.row, aSize.column);
1046 aFunc =
maMat.walk(std::move(aFunc));
1052 MatrixImplType::size_pair_type aSize =
maMat.size();
1053 CompareMatrixElemFunc<ElemLessEqualZero> aFunc(aSize.row, aSize.column);
1054 aFunc =
maMat.walk(std::move(aFunc));
1060 MatrixImplType::size_pair_type aSize =
maMat.size();
1061 CompareMatrixElemFunc<ElemGreaterEqualZero> aFunc(aSize.row, aSize.column);
1062 aFunc =
maMat.walk(std::move(aFunc));
1071 void operate(
double fVal) { mbResult &= (fVal != 0.0); }
1072 bool result()
const {
return mbResult; }
1073 AndEvaluator() : mbResult(true) {}
1079 void operate(
double fVal) { mbResult |= (fVal != 0.0); }
1080 bool result()
const {
return mbResult; }
1081 OrEvaluator() : mbResult(false) {}
1087 void operate(
double fVal) { mbResult ^= (fVal != 0.0); }
1088 bool result()
const {
return mbResult; }
1089 XorEvaluator() : mbResult(false) {}
1094template <
typename Evaluator>
1098 size_t nRows = rMat.size().row, nCols = rMat.size().column;
1099 for (
size_t i = 0;
i < nRows; ++
i)
1101 for (
size_t j = 0; j < nCols; ++j)
1103 MatrixImplType::const_position_type aPos = rMat.position(i, j);
1104 mdds::mtm::element_t
eType = rMat.get_type(aPos);
1105 if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
1109 double fVal = rMat.get_numeric(aPos);
1110 if (!std::isfinite(fVal))
1114 aEval.operate(fVal);
1117 return aEval.result();
1126 return EvalMatrix<AndEvaluator>(
maMat);
1133 return EvalMatrix<OrEvaluator>(
maMat);
1140 return EvalMatrix<XorEvaluator>(
maMat);
1145template<
typename Op,
typename tRes>
1146class WalkElementBlocks
1150 bool mbTextAsZero:1;
1151 bool mbIgnoreErrorValues:1;
1153 WalkElementBlocks(
bool bTextAsZero,
bool bIgnoreErrorValues) :
1154 maRes(
Op::InitVal, 0),
1155 mbTextAsZero(bTextAsZero), mbIgnoreErrorValues(bIgnoreErrorValues)
1160 void operator() (
const MatrixImplType::element_block_node_type& node)
1164 case mdds::mtm::element_numeric:
1166 typedef MatrixImplType::numeric_block_type block_type;
1168 size_t nIgnored = 0;
1169 block_type::const_iterator it = block_type::begin(*node.data);
1170 block_type::const_iterator itEnd = block_type::end(*node.data);
1171 for (; it != itEnd; ++it)
1173 if (mbIgnoreErrorValues && !std::isfinite(*it))
1180 maRes.
mnCount += node.size - nIgnored;
1183 case mdds::mtm::element_boolean:
1185 typedef MatrixImplType::boolean_block_type block_type;
1187 block_type::const_iterator it = block_type::begin(*node.data);
1188 block_type::const_iterator itEnd = block_type::end(*node.data);
1189 for (; it != itEnd; ++it)
1196 case mdds::mtm::element_string:
1200 case mdds::mtm::element_empty:
1207template<
typename Op,
typename tRes>
1208class WalkElementBlocksMultipleValues
1210 const std::vector<Op>* mpOp;
1213 WalkElementBlocksMultipleValues(
const std::vector<Op>& aOp) :
1214 mpOp(&aOp), maRes(0)
1216 for (
const auto& rpOp : *mpOp)
1220 WalkElementBlocksMultipleValues(
const WalkElementBlocksMultipleValues& ) =
delete;
1221 WalkElementBlocksMultipleValues& operator= (
const WalkElementBlocksMultipleValues& ) =
delete;
1223 WalkElementBlocksMultipleValues(WalkElementBlocksMultipleValues&& r) noexcept
1224 : mpOp(r.mpOp), maRes(r.maRes.mnCount)
1229 WalkElementBlocksMultipleValues& operator=(WalkElementBlocksMultipleValues&& r)
noexcept
1233 maRes.
mnCount = r.maRes.mnCount;
1239 void operator() (
const MatrixImplType::element_block_node_type& node)
1243 case mdds::mtm::element_numeric:
1245 typedef MatrixImplType::numeric_block_type block_type;
1247 block_type::const_iterator it = block_type::begin(*node.data);
1248 block_type::const_iterator itEnd = block_type::end(*node.data);
1249 for (; it != itEnd; ++it)
1251 for (
size_t i = 0u;
i < mpOp->size(); ++
i)
1257 case mdds::mtm::element_boolean:
1259 typedef MatrixImplType::boolean_block_type block_type;
1261 block_type::const_iterator it = block_type::begin(*node.data);
1262 block_type::const_iterator itEnd = block_type::end(*node.data);
1263 for (; it != itEnd; ++it)
1265 for (
size_t i = 0u;
i < mpOp->size(); ++
i)
1271 case mdds::mtm::element_string:
1272 case mdds::mtm::element_empty:
1284 bool mbIgnoreEmptyStrings;
1286 explicit CountElements(
bool bCountString,
bool bCountErrors,
bool bIgnoreEmptyStrings) :
1287 mnCount(0), mbCountString(bCountString), mbCountErrors(bCountErrors),
1288 mbIgnoreEmptyStrings(bIgnoreEmptyStrings) {}
1290 size_t getCount()
const {
return mnCount; }
1292 void operator() (
const MatrixImplType::element_block_node_type& node)
1296 case mdds::mtm::element_numeric:
1300 typedef MatrixImplType::numeric_block_type block_type;
1302 block_type::const_iterator it = block_type::begin(*node.data);
1303 block_type::const_iterator itEnd = block_type::end(*node.data);
1304 for (; it != itEnd; ++it)
1306 if (!std::isfinite(*it))
1311 case mdds::mtm::element_boolean:
1314 case mdds::mtm::element_string:
1318 if (mbIgnoreEmptyStrings)
1320 typedef MatrixImplType::string_block_type block_type;
1322 block_type::const_iterator it = block_type::begin(*node.data);
1323 block_type::const_iterator itEnd = block_type::end(*node.data);
1324 for (; it != itEnd; ++it)
1332 case mdds::mtm::element_empty:
1339const size_t ResultNotSet = std::numeric_limits<size_t>::max();
1341template<
typename Type>
1342class WalkAndMatchElements
1351 WalkAndMatchElements(
Type aMatchValue,
const MatrixImplType::size_pair_type& aSize,
size_t nCol1,
size_t nCol2) :
1352 maMatchValue(
std::move(aMatchValue)),
1354 mnStopIndex( (nCol2 + 1) * aSize.row ),
1355 mnResult(ResultNotSet),
1358 assert( nCol1 < aSize.column && nCol2 < aSize.column);
1361 size_t getMatching()
const {
return mnResult; }
1363 size_t getRemainingCount()
const
1368 size_t compare(
const MatrixImplType::element_block_node_type& node)
const;
1370 void operator() (
const MatrixImplType::element_block_node_type& node)
1373 if (mnResult != ResultNotSet)
1377 if (mnStartIndex <= mnIndex && getRemainingCount() > 0)
1387size_t WalkAndMatchElements<double>::compare(
const MatrixImplType::element_block_node_type& node)
const
1392 case mdds::mtm::element_numeric:
1394 typedef MatrixImplType::numeric_block_type block_type;
1396 block_type::const_iterator it = block_type::begin(*node.data);
1397 block_type::const_iterator itEnd = block_type::end(*node.data);
1398 const size_t nRemaining = getRemainingCount();
1399 for (; it != itEnd &&
nCount < nRemaining; ++it, ++
nCount)
1401 if (*it == maMatchValue)
1408 case mdds::mtm::element_boolean:
1410 typedef MatrixImplType::boolean_block_type block_type;
1412 block_type::const_iterator it = block_type::begin(*node.data);
1413 block_type::const_iterator itEnd = block_type::end(*node.data);
1414 const size_t nRemaining = getRemainingCount();
1415 for (; it != itEnd &&
nCount < nRemaining; ++it, ++
nCount)
1417 if (
int(*it) == maMatchValue)
1425 case mdds::mtm::element_string:
1426 case mdds::mtm::element_empty:
1430 return ResultNotSet;
1434size_t WalkAndMatchElements<svl::SharedString>::compare(
const MatrixImplType::element_block_node_type& node)
const
1438 case mdds::mtm::element_string:
1441 typedef MatrixImplType::string_block_type block_type;
1443 block_type::const_iterator it = block_type::begin(*node.data);
1444 block_type::const_iterator itEnd = block_type::end(*node.data);
1445 const size_t nRemaining = getRemainingCount();
1446 for (; it != itEnd &&
nCount < nRemaining; ++it, ++
nCount)
1448 if (it->getDataIgnoreCase() == maMatchValue.getDataIgnoreCase())
1455 case mdds::mtm::element_boolean:
1456 case mdds::mtm::element_numeric:
1457 case mdds::mtm::element_empty:
1461 return ResultNotSet;
1466 static double init() {
return -std::numeric_limits<double>::max(); }
1467 static double compare(
double left,
double right)
1469 if (!std::isfinite(left))
1471 if (!std::isfinite(right))
1473 return std::max(left, right);
1476 static double boolValue(
1477 MatrixImplType::boolean_block_type::const_iterator it,
1478 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1481 it = std::find(it, itEnd,
true);
1482 return it == itEnd ? 0.0 : 1.0;
1488 static double init() {
return std::numeric_limits<double>::max(); }
1489 static double compare(
double left,
double right)
1491 if (!std::isfinite(left))
1493 if (!std::isfinite(right))
1495 return std::min(left, right);
1498 static double boolValue(
1499 MatrixImplType::boolean_block_type::const_iterator it,
1500 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1503 it = std::find(it, itEnd,
false);
1504 return it == itEnd ? 1.0 : 0.0;
1510 static double init() {
return 1.0; }
1511 static double calculate(
double fx,
double fy)
1516 static double boolValue(
1517 MatrixImplType::boolean_block_type::const_iterator it,
1518 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1521 it = std::find(it, itEnd,
false);
1522 return it == itEnd ? 1.0 : 0.0;
1528 static double init() {
return 0.0; }
1529 static double calculate(
double fx,
double fy)
1534 static double boolValue(
1535 MatrixImplType::boolean_block_type::const_iterator it,
1536 const MatrixImplType::boolean_block_type::const_iterator& itEnd)
1539 it = std::find(it, itEnd,
true);
1540 return it == itEnd ? 0.0 : 1.0;
1544template<
typename Op>
1545class CalcMaxMinValue
1549 bool mbIgnoreErrorValues;
1552 CalcMaxMinValue(
bool bTextAsZero,
bool bIgnoreErrorValues ) :
1554 mbTextAsZero(bTextAsZero),
1555 mbIgnoreErrorValues(bIgnoreErrorValues),
1556 mbHasValue(false) {}
1558 double getValue()
const {
return mbHasValue ?
mfVal : 0.0; }
1560 void operator() (
const MatrixImplType::element_block_node_type& node)
1565 case mdds::mtm::element_numeric:
1567 typedef MatrixImplType::numeric_block_type block_type;
1569 block_type::const_iterator it = block_type::begin(*node.data);
1570 block_type::const_iterator itEnd = block_type::end(*node.data);
1571 if (mbIgnoreErrorValues)
1573 for (; it != itEnd; ++it)
1575 if (std::isfinite(*it))
1581 for (; it != itEnd; ++it)
1588 case mdds::mtm::element_boolean:
1590 typedef MatrixImplType::boolean_block_type block_type;
1592 block_type::const_iterator it = block_type::begin(*node.data);
1593 block_type::const_iterator itEnd = block_type::end(*node.data);
1594 double fVal = Op::boolValue(it, itEnd);
1599 case mdds::mtm::element_string:
1600 case mdds::mtm::element_empty:
1616template<
typename Op>
1622 CalcGcdLcm() : mfval(
Op::
init()) {}
1624 double getResult()
const {
return mfval; }
1626 void operator() (
const MatrixImplType::element_block_node_type& node )
1630 case mdds::mtm::element_numeric:
1632 typedef MatrixImplType::numeric_block_type block_type;
1633 block_type::const_iterator it = block_type::begin(*node.data);
1634 block_type::const_iterator itEnd = block_type::end(*node.data);
1636 for ( ; it != itEnd; ++it)
1641 mfval = ::rtl::math::approxFloor( Op::calculate(*it,mfval));
1645 case mdds::mtm::element_boolean:
1647 typedef MatrixImplType::boolean_block_type block_type;
1648 block_type::const_iterator it = block_type::begin(*node.data);
1649 block_type::const_iterator itEnd = block_type::end(*node.data);
1651 mfval = Op::boolValue(it, itEnd);
1654 case mdds::mtm::element_empty:
1655 case mdds::mtm::element_string:
1666double evaluate(
double fVal,
ScQueryOp eOp )
1668 if (!std::isfinite(fVal))
1674 return fVal == 0.0 ? 1.0 : 0.0;
1676 return fVal < 0.0 ? 1.0 : 0.0;
1678 return fVal > 0.0 ? 1.0 : 0.0;
1680 return fVal <= 0.0 ? 1.0 : 0.0;
1682 return fVal >= 0.0 ? 1.0 : 0.0;
1684 return fVal != 0.0 ? 1.0 : 0.0;
1689 SAL_WARN(
"sc.core",
"evaluate: unhandled comparison operator: " <<
static_cast<int>(eOp));
1693class CompareMatrixFunc
1698 std::vector<double> maResValues;
1703 maResValues.push_back(evaluate(fVal, mrComp.
meOp));
1708 mrComp(rComp), mnMatPos(nMatPos), mpOptions(pOptions)
1710 maResValues.reserve(nResSize);
1713 CompareMatrixFunc(
const CompareMatrixFunc& ) =
delete;
1714 CompareMatrixFunc& operator= (
const CompareMatrixFunc& ) =
delete;
1716 CompareMatrixFunc(CompareMatrixFunc&& r) noexcept :
1718 mnMatPos(r.mnMatPos),
1719 mpOptions(r.mpOptions),
1720 maResValues(std::move(r.maResValues)) {}
1722 CompareMatrixFunc& operator=(CompareMatrixFunc&& r)
noexcept
1725 mnMatPos = r.mnMatPos;
1726 mpOptions = r.mpOptions;
1727 maResValues = std::move(r.maResValues);
1731 void operator() (
const MatrixImplType::element_block_node_type& node)
1737 case mdds::mtm::element_numeric:
1739 typedef MatrixImplType::numeric_block_type block_type;
1741 block_type::const_iterator it = block_type::begin(*node.data);
1742 block_type::const_iterator itEnd = block_type::end(*node.data);
1743 for (; it != itEnd; ++it)
1752 case mdds::mtm::element_boolean:
1754 typedef MatrixImplType::boolean_block_type block_type;
1756 block_type::const_iterator it = block_type::begin(*node.data);
1757 block_type::const_iterator itEnd = block_type::end(*node.data);
1758 for (; it != itEnd; ++it)
1767 case mdds::mtm::element_string:
1769 typedef MatrixImplType::string_block_type block_type;
1771 block_type::const_iterator it = block_type::begin(*node.data);
1772 block_type::const_iterator itEnd = block_type::end(*node.data);
1773 for (; it != itEnd; ++it)
1783 case mdds::mtm::element_empty:
1788 for (
size_t i = 0;
i < node.size; ++
i)
1797 const std::vector<double>& getValues()
const
1806class CompareMatrixToNumericFunc
1809 double mfRightValue;
1811 std::vector<double> maResValues;
1816 maResValues.push_back(evaluate(fVal, mrComp.
meOp));
1819 void compareLeftNumeric(
double fLeftVal )
1822 maResValues.push_back(evaluate(fVal, mrComp.
meOp));
1825 void compareLeftEmpty(
size_t nSize )
1828 bool bRes = evaluate(fVal, mrComp.
meOp);
1829 maResValues.resize(maResValues.size() + nSize, bRes ? 1.0 : 0.0);
1834 mrComp(rComp), mfRightValue(fRightValue), mpOptions(pOptions)
1836 maResValues.reserve(nResSize);
1839 CompareMatrixToNumericFunc(
const CompareMatrixToNumericFunc& ) =
delete;
1840 CompareMatrixToNumericFunc& operator= (
const CompareMatrixToNumericFunc& ) =
delete;
1842 CompareMatrixToNumericFunc(CompareMatrixToNumericFunc&& r) noexcept :
1844 mfRightValue(r.mfRightValue),
1845 mpOptions(r.mpOptions),
1846 maResValues(std::move(r.maResValues)) {}
1848 CompareMatrixToNumericFunc& operator=(CompareMatrixToNumericFunc&& r)
noexcept
1851 mfRightValue = r.mfRightValue;
1852 mpOptions = r.mpOptions;
1853 maResValues = std::move(r.maResValues);
1857 void operator() (
const MatrixImplType::element_block_node_type& node)
1861 case mdds::mtm::element_numeric:
1863 typedef MatrixImplType::numeric_block_type block_type;
1865 block_type::const_iterator it = block_type::begin(*node.data);
1866 block_type::const_iterator itEnd = block_type::end(*node.data);
1867 for (; it != itEnd; ++it)
1868 compareLeftNumeric(*it);
1871 case mdds::mtm::element_boolean:
1873 typedef MatrixImplType::boolean_block_type block_type;
1875 block_type::const_iterator it = block_type::begin(*node.data);
1876 block_type::const_iterator itEnd = block_type::end(*node.data);
1877 for (; it != itEnd; ++it)
1878 compareLeftNumeric(
double(*it));
1881 case mdds::mtm::element_string:
1883 typedef MatrixImplType::string_block_type block_type;
1885 block_type::const_iterator it = block_type::begin(*node.data);
1886 block_type::const_iterator itEnd = block_type::end(*node.data);
1887 for (; it != itEnd; ++it)
1898 case mdds::mtm::element_empty:
1899 compareLeftEmpty(node.size);
1906 const std::vector<double>& getValues()
const
1914 std::vector<double> maArray;
1915 std::vector<double>::iterator miPos;
1919 void moveArray( ToDoubleArray& r )
1924 size_t n = std::distance(r.maArray.begin(), r.miPos);
1925 maArray = std::move(r.maArray);
1926 miPos = maArray.begin();
1927 std::advance(miPos, n);
1931 ToDoubleArray(
size_t nSize,
bool bEmptyAsZero ) :
1932 maArray(nSize, 0.0), miPos(maArray.
begin()), mbEmptyAsZero(bEmptyAsZero)
1937 ToDoubleArray(
const ToDoubleArray& ) =
delete;
1938 ToDoubleArray& operator= (
const ToDoubleArray& ) =
delete;
1940 ToDoubleArray(ToDoubleArray&& r) noexcept :
1941 mfNaN(r.mfNaN), mbEmptyAsZero(r.mbEmptyAsZero)
1946 ToDoubleArray& operator=(ToDoubleArray&& r)
noexcept
1949 mbEmptyAsZero = r.mbEmptyAsZero;
1954 void operator() (
const MatrixImplType::element_block_node_type& node)
1956 using namespace mdds::mtv;
1960 case mdds::mtm::element_numeric:
1962 double_element_block::const_iterator it = double_element_block::begin(*node.data);
1963 double_element_block::const_iterator itEnd = double_element_block::end(*node.data);
1964 for (; it != itEnd; ++it, ++miPos)
1968 case mdds::mtm::element_boolean:
1970 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
1971 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
1972 for (; it != itEnd; ++it, ++miPos)
1973 *miPos = *it ? 1.0 : 0.0;
1976 case mdds::mtm::element_string:
1978 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
1982 case mdds::mtm::element_empty:
1986 std::advance(miPos, node.size);
1990 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
1999 void swap(std::vector<double>& rOther)
2001 maArray.swap(rOther);
2007 double operator() (
const double& lhs,
const double& rhs)
const
2013template<
typename Op>
2014class MergeDoubleArrayFunc
2016 std::vector<double>::iterator miPos;
2019 MergeDoubleArrayFunc(std::vector<double>& rArray) : miPos(rArray.
begin())
2024 MergeDoubleArrayFunc(
const MergeDoubleArrayFunc& ) =
delete;
2025 MergeDoubleArrayFunc& operator= (
const MergeDoubleArrayFunc& ) =
delete;
2027 MergeDoubleArrayFunc( MergeDoubleArrayFunc&& ) =
default;
2028 MergeDoubleArrayFunc& operator= ( MergeDoubleArrayFunc&& ) =
default;
2030 void operator() (
const MatrixImplType::element_block_node_type& node)
2032 using namespace mdds::mtv;
2037 case mdds::mtm::element_numeric:
2039 double_element_block::const_iterator it = double_element_block::begin(*node.data);
2040 double_element_block::const_iterator itEnd = double_element_block::end(*node.data);
2041 for (; it != itEnd; ++it, ++miPos)
2046 *miPos = op(*miPos, *it);
2050 case mdds::mtm::element_boolean:
2052 boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
2053 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
2054 for (; it != itEnd; ++it, ++miPos)
2059 *miPos = op(*miPos, *it ? 1.0 : 0.0);
2063 case mdds::mtm::element_string:
2065 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
2069 case mdds::mtm::element_empty:
2072 for (
size_t i = 0;
i < node.size; ++
i, ++miPos)
2077 *miPos = op(*miPos, 0.0);
2091template<
typename TOp,
typename tRes>
2094 WalkElementBlocks<TOp, tRes> aFunc(bTextAsZero, bIgnoreErrorValues);
2095 aFunc = maMat.walk(aFunc);
2096 return aFunc.getResult();
2103 return GetValueWithCount<sc::op::Sum, KahanSum>(bTextAsZero, bIgnoreErrorValues,
maMat);
2108 return GetValueWithCount<sc::op::SumSquare, KahanSum>(bTextAsZero, bIgnoreErrorValues,
maMat);
2113 return GetValueWithCount<sc::op::Product, double>(bTextAsZero, bIgnoreErrorValues,
maMat);
2118 CountElements aFunc(bCountStrings, bCountErrors, bIgnoreEmptyStrings);
2119 aFunc =
maMat.walk(aFunc);
2120 return aFunc.getCount();
2125 WalkAndMatchElements<double> aFunc(fValue,
maMat.size(), nCol1, nCol2);
2126 aFunc =
maMat.walk(aFunc);
2127 return aFunc.getMatching();
2132 WalkAndMatchElements<svl::SharedString> aFunc(rStr,
maMat.size(), nCol1, nCol2);
2133 aFunc =
maMat.walk(aFunc);
2134 return aFunc.getMatching();
2139 CalcMaxMinValue<MaxOp> aFunc(bTextAsZero, bIgnoreErrorValues);
2140 aFunc =
maMat.walk(aFunc);
2141 return aFunc.getValue();
2146 CalcMaxMinValue<MinOp> aFunc(bTextAsZero, bIgnoreErrorValues);
2147 aFunc =
maMat.walk(aFunc);
2148 return aFunc.getValue();
2153 CalcGcdLcm<Gcd> aFunc;
2154 aFunc =
maMat.walk(aFunc);
2155 return aFunc.getResult();
2160 CalcGcdLcm<Lcm> aFunc;
2161 aFunc =
maMat.walk(aFunc);
2162 return aFunc.getResult();
2168 MatrixImplType::size_pair_type aSize =
maMat.size();
2169 size_t nSize = aSize.column * aSize.row;
2177 CompareMatrixToNumericFunc aFunc(nSize, rComp, rComp.
maCells[1].
mfValue, pOptions);
2178 aFunc =
maMat.walk(std::move(aFunc));
2181 const std::vector<double>& rResVal = aFunc.getValues();
2182 assert (nSize == rResVal.size());
2183 if (nSize != rResVal.size())
2190 CompareMatrixFunc aFunc(nSize, rComp, nMatPos, pOptions);
2191 aFunc =
maMat.walk(std::move(aFunc));
2194 const std::vector<double>& rResVal = aFunc.getValues();
2195 assert (nSize == rResVal.size());
2196 if (nSize != rResVal.size())
2204 MatrixImplType::size_pair_type aSize =
maMat.size();
2205 ToDoubleArray aFunc(aSize.row*aSize.column, bEmptyAsZero);
2206 aFunc =
maMat.walk(std::move(aFunc));
2212 MatrixImplType::size_pair_type aSize =
maMat.size();
2213 size_t nSize = aSize.row*aSize.column;
2214 if (nSize != rArray.size())
2217 MergeDoubleArrayFunc<ArrayMul> aFunc(rArray);
2218 maMat.walk(std::move(aFunc));
2223template<
typename T,
typename U,
typename return_type>
2224struct wrapped_iterator
2226 typedef ::std::bidirectional_iterator_tag iterator_category;
2227 typedef typename T::const_iterator::value_type old_value_type;
2228 typedef return_type value_type;
2229 typedef value_type* pointer;
2230 typedef value_type& reference;
2231 typedef typename T::const_iterator::difference_type difference_type;
2233 typename T::const_iterator it;
2234 mutable value_type val;
2239 value_type calcVal()
const
2246 wrapped_iterator(
typename T::const_iterator it_, U
const & aOp):
2253 wrapped_iterator(
const wrapped_iterator& r):
2260 wrapped_iterator& operator=(
const wrapped_iterator& r)
2266 bool operator==(
const wrapped_iterator& r)
const
2271 bool operator!=(
const wrapped_iterator& r)
const
2283 wrapped_iterator& operator--()
2296 pointer operator->()
const
2303template<
typename T,
typename U,
typename return_type>
2304struct MatrixIteratorWrapper
2307 typename T::const_iterator m_itBegin;
2308 typename T::const_iterator m_itEnd;
2311 MatrixIteratorWrapper(
typename T::const_iterator itBegin,
typename T::const_iterator itEnd, U
const & aOp):
2312 m_itBegin(
std::move(itBegin)),
2313 m_itEnd(
std::move(itEnd)),
2318 wrapped_iterator<T, U, return_type>
begin()
2320 return wrapped_iterator<T, U, return_type>(m_itBegin,
maOp);
2323 wrapped_iterator<T, U, return_type>
end()
2325 return wrapped_iterator<T, U, return_type>(m_itEnd,
maOp);
2329MatrixImplType::position_type increment_position(
const MatrixImplType::position_type& pos,
size_t n)
2331 MatrixImplType::position_type ret =
pos;
2334 if (ret.second + n < ret.first->size)
2341 n -= (ret.first->size - ret.second);
2351struct MatrixOpWrapper
2355 MatrixImplType::position_type
pos;
2366 MatrixOpWrapper(
const MatrixOpWrapper& r ) : mrMat(r.mrMat),
pos(r.
pos), mpOp(r.mpOp) {}
2368 MatrixOpWrapper& operator= (
const MatrixOpWrapper& r ) =
default;
2370 void operator()(
const MatrixImplType::element_block_node_type& node)
2374 case mdds::mtm::element_numeric:
2376 typedef MatrixImplType::numeric_block_type block_type;
2378 block_type::const_iterator it = block_type::begin(*node.data);
2379 block_type::const_iterator itEnd = block_type::end(*node.data);
2380 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, *mpOp);
2381 pos = mrMat.set(pos,aFunc.begin(), aFunc.end());
2384 case mdds::mtm::element_boolean:
2386 typedef MatrixImplType::boolean_block_type block_type;
2388 block_type::const_iterator it = block_type::begin(*node.data);
2389 block_type::const_iterator itEnd = block_type::end(*node.data);
2391 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, *mpOp);
2392 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2395 case mdds::mtm::element_string:
2397 typedef MatrixImplType::string_block_type block_type;
2399 block_type::const_iterator it = block_type::begin(*node.data);
2400 block_type::const_iterator itEnd = block_type::end(*node.data);
2402 MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, *mpOp);
2403 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2406 case mdds::mtm::element_empty:
2408 if (mpOp->useFunctionForEmpty())
2410 std::vector<char> aVec(node.size);
2411 MatrixIteratorWrapper<std::vector<char>, T,
typename T::number_value_type>
2412 aFunc(aVec.begin(), aVec.end(), *mpOp);
2413 pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
2420 pos = increment_position(pos, node.size);
2429 MatrixOpWrapper<T> aFunc(rMat.
maMat, aOp);
2433template<
typename T,
typename tRes>
2436 WalkElementBlocksMultipleValues<T, tRes> aFunc(aOp);
2437 aFunc =
maMat.walk(std::move(aFunc));
2438 return aFunc.getResult();
2445 ElementBlock(
size_t nRowSize,
2450 mnRowSize(nRowSize),
2453 maDoubleFunc(
std::move(aDoubleFunc)),
2454 maBoolFunc(
std::move(aBoolFunc)),
2455 maStringFunc(
std::move(aStringFunc)),
2456 maEmptyFunc(
std::move(aEmptyFunc))
2470class WalkElementBlockOperation
2474 WalkElementBlockOperation(ElementBlock& rElementBlock)
2475 : mrElementBlock(rElementBlock)
2479 void operator()(
const MatrixImplType::element_block_node_type& node)
2483 case mdds::mtm::element_numeric:
2485 typedef MatrixImplType::numeric_block_type block_type;
2487 block_type::const_iterator it = block_type::begin(*node.data);
2488 std::advance(it, node.offset);
2489 block_type::const_iterator itEnd = it;
2490 std::advance(itEnd, node.size);
2491 for (
auto itr = it; itr != itEnd; ++itr)
2493 mrElementBlock.maDoubleFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos, *itr);
2494 ++mrElementBlock.mnRowPos;
2495 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2497 mrElementBlock.mnRowPos = 0;
2498 ++mrElementBlock.mnColPos;
2503 case mdds::mtm::element_string:
2505 typedef MatrixImplType::string_block_type block_type;
2507 block_type::const_iterator it = block_type::begin(*node.data);
2508 std::advance(it, node.offset);
2509 block_type::const_iterator itEnd = it;
2510 std::advance(itEnd, node.size);
2511 for (
auto itr = it; itr != itEnd; ++itr)
2513 mrElementBlock.maStringFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos, *itr);
2514 ++mrElementBlock.mnRowPos;
2515 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2517 mrElementBlock.mnRowPos = 0;
2518 ++mrElementBlock.mnColPos;
2523 case mdds::mtm::element_boolean:
2525 typedef MatrixImplType::boolean_block_type block_type;
2527 block_type::const_iterator it = block_type::begin(*node.data);
2528 std::advance(it, node.offset);
2529 block_type::const_iterator itEnd = it;
2530 std::advance(itEnd, node.size);
2531 for (
auto itr = it; itr != itEnd; ++itr)
2533 mrElementBlock.maBoolFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos, *itr);
2534 ++mrElementBlock.mnRowPos;
2535 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2537 mrElementBlock.mnRowPos = 0;
2538 ++mrElementBlock.mnColPos;
2543 case mdds::mtm::element_empty:
2545 for (
size_t i=0;
i < node.size; ++
i)
2547 mrElementBlock.maEmptyFunc(mrElementBlock.mnRowPos, mrElementBlock.mnColPos);
2548 ++mrElementBlock.mnRowPos;
2549 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2551 mrElementBlock.mnRowPos = 0;
2552 ++mrElementBlock.mnColPos;
2557 case mdds::mtm::element_integer:
2559 SAL_WARN(
"sc.core",
"WalkElementBlockOperation - unhandled element_integer");
2561 mrElementBlock.mnColPos += node.size / mrElementBlock.mnRowSize;
2562 mrElementBlock.mnRowPos += node.size % mrElementBlock.mnRowSize;
2563 if (mrElementBlock.mnRowPos >= mrElementBlock.mnRowSize)
2565 mrElementBlock.mnRowPos = 0;
2566 ++mrElementBlock.mnColPos;
2575 ElementBlock& mrElementBlock;
2585 ElementBlock aPayload(
maMat.size().row, aDoubleFunc, aBoolFunc, aStringFunc, aEmptyFunc);
2586 WalkElementBlockOperation aFunc(aPayload);
2589 MatrixImplType::size_pair_type(rStartPos.first, rStartPos.second),
2590 MatrixImplType::size_pair_type(rEndPos.first, rEndPos.second));
2595void ScMatrixImpl::Dump()
const
2597 cout <<
"-- matrix content" <<
endl;
2600 for (
SCSIZE nRow = 0; nRow < nRows; ++nRow)
2602 for (
SCSIZE nCol = 0; nCol < nCols; ++nCol)
2604 cout <<
" row=" << nRow <<
", col=" << nCol <<
" : ";
2605 switch (
maMat.get_type(nRow, nCol))
2607 case mdds::mtm::element_string:
2608 cout <<
"string (" <<
maMat.get_string(nRow, nCol).getString() <<
")";
2610 case mdds::mtm::element_numeric:
2611 cout <<
"numeric (" <<
maMat.get_numeric(nRow, nCol) <<
")";
2613 case mdds::mtm::element_boolean:
2614 cout <<
"boolean (" <<
maMat.get_boolean(nRow, nCol) <<
")";
2616 case mdds::mtm::element_empty:
2632 SAL_WARN_IF( !nRowSize,
"sc.core",
"ScMatrixImpl::CalcPosition: 0 rows!");
2634 rR =
nIndex - rC*nRowSize;
2639size_t get_index(
SCSIZE nMaxRow,
size_t nRow,
size_t nCol,
size_t nRowOffset,
size_t nColOffset)
2641 return nMaxRow * (nCol + nColOffset) + nRow + nRowOffset;
2651 xMat1->GetDimensions(nC1, nR1);
2652 xMat2->GetDimensions(nC2, nR2);
2657 std::vector<OUString> aString(nMaxCol * nMaxRow);
2658 std::vector<bool> aValid(nMaxCol * nMaxRow,
true);
2659 std::vector<FormulaError> nErrors(nMaxCol * nMaxRow,FormulaError::NONE);
2661 size_t nRowOffset = 0;
2662 size_t nColOffset = 0;
2663 std::function<void(
size_t,
size_t,
double)> aDoubleFunc =
2664 [&](
size_t nRow,
size_t nCol,
double nVal)
2667 if (nErr != FormulaError::NONE)
2669 aValid[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
false;
2670 nErrors[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = nErr;
2675 aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr;
2678 std::function<void(
size_t,
size_t,
bool)> aBoolFunc =
2679 [&](
size_t nRow,
size_t nCol,
bool nVal)
2683 aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr;
2689 aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr.getString();
2692 std::function<void(
size_t,
size_t)> aEmptyFunc =
2693 [](
size_t ,
size_t )
2699 if (nC1 == 1 || nR1 == 1)
2701 size_t nRowRep = nR1 == 1 ? nMaxRow : 1;
2702 size_t nColRep = nC1 == 1 ? nMaxCol : 1;
2704 for (
size_t i = 0;
i < nRowRep; ++
i)
2707 for (
size_t j = 0; j < nColRep; ++j)
2710 xMat1->ExecuteOperation(
2711 std::pair<size_t, size_t>(0, 0),
2712 std::pair<size_t, size_t>(std::min(nR1, nMaxRow) - 1, std::min(nC1, nMaxCol) - 1),
2713 aDoubleFunc, aBoolFunc, aStringFunc, aEmptyFunc);
2718 xMat1->ExecuteOperation(
2719 std::pair<size_t, size_t>(0, 0),
2720 std::pair<size_t, size_t>(nMaxRow - 1, nMaxCol - 1),
2721 std::move(aDoubleFunc), std::move(aBoolFunc), std::move(aStringFunc), std::move(aEmptyFunc));
2723 std::vector<svl::SharedString> aSharedString(nMaxCol*nMaxRow);
2725 std::function<void(
size_t,
size_t,
double)> aDoubleFunc2 =
2726 [&](
size_t nRow,
size_t nCol,
double nVal)
2729 if (nErr != FormulaError::NONE)
2731 aValid[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
false;
2732 nErrors[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = nErr;
2737 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr);
2740 std::function<void(
size_t,
size_t,
bool)> aBoolFunc2 =
2741 [&](
size_t nRow,
size_t nCol,
bool nVal)
2745 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] = rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr);
2751 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
2752 rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] +
aStr.getString());
2755 std::function<void(
size_t,
size_t)> aEmptyFunc2 =
2756 [&](
size_t nRow,
size_t nCol)
2758 aSharedString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)] =
2759 rStringPool.
intern(aString[get_index(nMaxRow, nRow, nCol, nRowOffset, nColOffset)]);
2764 if (nC2 == 1 || nR2 == 1)
2766 size_t nRowRep = nR2 == 1 ? nMaxRow : 1;
2767 size_t nColRep = nC2 == 1 ? nMaxCol : 1;
2769 for (
size_t i = 0;
i < nRowRep; ++
i)
2772 for (
size_t j = 0; j < nColRep; ++j)
2775 xMat2->ExecuteOperation(
2776 std::pair<size_t, size_t>(0, 0),
2777 std::pair<size_t, size_t>(std::min(nR2, nMaxRow) - 1, std::min(nC2, nMaxCol) - 1),
2778 aDoubleFunc2, aBoolFunc2, aStringFunc2, aEmptyFunc2);
2783 xMat2->ExecuteOperation(
2784 std::pair<size_t, size_t>(0, 0),
2785 std::pair<size_t, size_t>(nMaxRow - 1, nMaxCol - 1),
2786 std::move(aDoubleFunc2), std::move(aBoolFunc2), std::move(aStringFunc2), std::move(aEmptyFunc2));
2790 MatrixImplType::position_type
pos =
maMat.position(0, 0);
2793 for (
SCSIZE j = 0; j < nMaxRow &&
i < nMaxCol; ++j)
2795 if (aValid[nMaxRow *
i + j])
2797 auto itr = aValid.begin();
2798 std::advance(itr, nMaxRow *
i + j);
2799 auto itrEnd = std::find(itr, aValid.end(),
false);
2800 size_t nSteps = std::distance(itr, itrEnd);
2801 auto itrStr = aSharedString.begin();
2802 std::advance(itrStr, nMaxRow *
i + j);
2803 auto itrEndStr = itrStr;
2804 std::advance(itrEndStr, nSteps);
2806 size_t nColSteps = nSteps / nMaxRow;
2808 j += nSteps % nMaxRow;
2819 pos = MatrixImplType::next_position(
pos);
2826 switch (
maMat.get_type(rPos))
2828 case mdds::mtm::element_boolean:
2829 case mdds::mtm::element_numeric:
2830 case mdds::mtm::element_empty:
2840 double fVal =
maMat.get_numeric(rPos);
2844 if ( nError != FormulaError::NONE )
2855 switch (
maMat.get_type(rPos))
2857 case mdds::mtm::element_boolean:
2858 case mdds::mtm::element_numeric:
2868 double fVal =
maMat.get_numeric(rPos);
2874 switch (
maMat.get_type(rPos))
2876 case mdds::mtm::element_empty:
2877 case mdds::mtm::element_string:
2889 assert(
maMat.size().row == nMaxRow &&
maMat.size().column == nMaxCol
2890 &&
"the caller code should have sized the output matrix to the passed dimensions");
2891 auto & rMatImpl1 = *rInputMat1.
pImpl;
2892 auto & rMatImpl2 = *rInputMat2.
pImpl;
2894 if (rMatImpl1.maMat.size() == rMatImpl2.maMat.size()
2895 && rMatImpl1.maMat.size() ==
maMat.size())
2897 MatrixImplType::position_type aOutPos =
maMat.position(0, 0);
2898 MatrixImplType::const_position_type aPos1 = rMatImpl1.maMat.position(0, 0);
2899 MatrixImplType::const_position_type aPos2 = rMatImpl2.maMat.position(0, 0);
2902 for (
SCSIZE j = 0; j < nMaxRow; j++)
2904 bool bVal1 = rMatImpl1.IsValueOrEmpty(aPos1);
2905 bool bVal2 = rMatImpl2.IsValueOrEmpty(aPos2);
2909 double d =
Op(rMatImpl1.GetDouble(aPos1), rMatImpl2.GetDouble(aPos2));
2910 aOutPos =
maMat.set(aOutPos,
d);
2912 else if (((nErr = rMatImpl1.GetErrorIfNotString(aPos1)) != FormulaError::NONE) ||
2913 ((nErr = rMatImpl2.GetErrorIfNotString(aPos2)) != FormulaError::NONE))
2917 else if ((!bVal1 && rMatImpl1.IsStringOrEmpty(aPos1)) ||
2918 (!bVal2 && rMatImpl2.IsStringOrEmpty(aPos2)))
2922 double fVal1 = (bVal1 ? rMatImpl1.GetDouble(aPos1) :
2927 double fVal2 = (bVal2 ? rMatImpl2.GetDouble(aPos2) :
2930 if (nError1 != FormulaError::NONE)
2932 else if (nError2 != FormulaError::NONE)
2936 double d =
Op( fVal1, fVal2);
2937 aOutPos =
maMat.set(aOutPos,
d);
2942 aPos1 = MatrixImplType::next_position(aPos1);
2943 aPos2 = MatrixImplType::next_position(aPos2);
2944 aOutPos = MatrixImplType::next_position(aOutPos);
2955 MatrixImplType::position_type aOutPos =
maMat.position(0, 0);
2958 for (
SCSIZE j = 0; j < nMaxRow; j++)
2966 aOutPos =
maMat.set(aOutPos,
d);
2977 double fVal1 = (bVal1 ? rInputMat1.
GetDouble(
i,j) :
2982 double fVal2 = (bVal2 ? rInputMat2.
GetDouble(
i,j) :
2985 if (nError1 != FormulaError::NONE)
2987 else if (nError2 != FormulaError::NONE)
2991 double d =
Op( fVal1, fVal2);
2992 aOutPos =
maMat.set(aOutPos,
d);
2997 aOutPos = MatrixImplType::next_position(aOutPos);
3017 SAL_WARN_IF( !nC,
"sc.core",
"ScMatrix with 0 columns!");
3018 SAL_WARN_IF( !nR,
"sc.core",
"ScMatrix with 0 rows!");
3020 if ((nC && !nR) || (!nC && nR))
3022 SAL_WARN(
"sc.core",
"ScMatrix one-dimensional zero: " << nC <<
" columns * " << nR <<
" rows");
3031 const char* pEnv = std::getenv(
"SC_MAX_MATRIX_ELEMENTS");
3042#if SAL_TYPES_SIZEOFPOINTER < 8
3044 constexpr size_t nMemMax = 0x40000000;
3047 constexpr size_t nMemMax = 0x180000000;
3055 SAL_WARN(
"sc.core",
"ScMatrix overflow: " << nC <<
" columns * " << nR <<
" rows");
3062 nRefCnt(0), mbCloneIfConst(true)
3072 nRefCnt(0), mbCloneIfConst(true)
3082 nRefCnt(0), mbCloneIfConst(true)
3098 pImpl->GetDimensions(nC, nR);
3122 pImpl->Resize(nC, nR);
3127 pImpl->Resize(nC, nR, fVal);
3140 pImpl->SetErrorInterpreter(
p);
3145 pImpl->GetDimensions(rC, rR);
3150 return pImpl->GetElementCount();
3155 return pImpl->ValidColRow(nC, nR);
3160 return pImpl->ValidColRowReplicated(rC, rR);
3170 pImpl->PutDouble(fVal, nC, nR);
3180 pImpl->PutDouble(pArray, nLen, nC, nR);
3185 pImpl->PutString(rStr, nC, nR);
3195 pImpl->PutString(pArray, nLen, nC, nR);
3200 pImpl->PutEmpty(nC, nR);
3205 pImpl->PutEmptyPath(nC, nR);
3210 pImpl->PutError(nErrorCode, nC, nR);
3215 pImpl->PutBoolean(bVal, nC, nR);
3220 return pImpl->GetError(nC, nR);
3225 return pImpl->GetDouble(nC, nR);
3235 return pImpl->GetDoubleWithStringConversion(nC, nR);
3240 return pImpl->GetString(nC, nR);
3250 return pImpl->GetString(rFormatter, nC, nR);
3255 return pImpl->Get(nC, nR);
3265 return pImpl->IsStringOrEmpty(nC, nR);
3270 return pImpl->IsEmpty(nC, nR);
3275 return pImpl->IsEmptyCell(nC, nR);
3280 return pImpl->IsEmptyResult(nC, nR);
3285 return pImpl->IsEmptyPath(nC, nR);
3295 return pImpl->IsValue(nC, nR);
3300 return pImpl->IsValueOrEmpty(nC, nR);
3305 return pImpl->IsBoolean(nC, nR);
3310 return pImpl->IsNumeric();
3325 pImpl->FillDouble(fVal, nC1, nR1, nC2, nR2);
3330 pImpl->PutDoubleVector(rVec, nC, nR);
3335 pImpl->PutStringVector(rVec, nC, nR);
3355 pImpl->CompareEqual();
3360 pImpl->CompareNotEqual();
3365 pImpl->CompareLess();
3370 pImpl->CompareGreater();
3375 pImpl->CompareLessEqual();
3380 pImpl->CompareGreaterEqual();
3385 return pImpl->And();
3395 return pImpl->Xor();
3400 return pImpl->Sum(bTextAsZero, bIgnoreErrorValues);
3405 return pImpl->SumSquare(bTextAsZero, bIgnoreErrorValues);
3410 return pImpl->Product(bTextAsZero, bIgnoreErrorValues);
3413size_t ScMatrix::Count(
bool bCountStrings,
bool bCountErrors,
bool bIgnoreEmptyStrings)
const
3415 return pImpl->Count(bCountStrings, bCountErrors, bIgnoreEmptyStrings);
3420 return pImpl->MatchDoubleInColumns(fValue, nCol1, nCol2);
3425 return pImpl->MatchStringInColumns(rStr, nCol1, nCol2);
3430 return pImpl->GetMaxValue(bTextAsZero, bIgnoreErrorValues);
3435 return pImpl->GetMinValue(bTextAsZero, bIgnoreErrorValues);
3440 return pImpl->GetGcd();
3445 return pImpl->GetLcm();
3452 return pImpl->CompareMatrix(rComp, nMatPos, pOptions);
3457 pImpl->GetDoubleArray(rArray, bEmptyAsZero);
3462 pImpl->MergeDoubleArrayMultiply(rArray);
3476template<
typename TOp>
3485 typedef double number_value_type;
3488 double fVal = 0.0 ):
3496 if (nErr != FormulaError::NONE)
3501 double operator()(
double fVal)
const
3506 double operator()(
bool bVal)
const
3508 return maOp(
static_cast<double>(bVal),
mfVal);
3517 double operator()(
char)
const
3522 static bool useFunctionForEmpty()
3534 auto not_ = [](
double a, double){
return double(
a == 0.0);};
3535 matop::MatOp<
decltype(not_)> aOp(not_,
pImpl->GetErrorInterpreter());
3541 auto neg_ = [](
double a, double){
return -
a;};
3542 matop::MatOp<
decltype(neg_)> aOp(neg_,
pImpl->GetErrorInterpreter());
3548 auto add_ = [](
double a,
double b){
return a + b;};
3549 matop::MatOp<
decltype(add_)> aOp(add_,
pImpl->GetErrorInterpreter(), fVal);
3557 auto sub_ = [](
double a,
double b){
return b -
a;};
3558 matop::MatOp<
decltype(sub_)> aOp(sub_,
pImpl->GetErrorInterpreter(), fVal);
3563 auto sub_ = [](
double a,
double b){
return a - b;};
3564 matop::MatOp<
decltype(sub_)> aOp(sub_,
pImpl->GetErrorInterpreter(), fVal);
3571 auto mul_ = [](
double a,
double b){
return a * b;};
3572 matop::MatOp<
decltype(mul_)> aOp(mul_,
pImpl->GetErrorInterpreter(), fVal);
3580 auto div_ = [](
double a,
double b){
return sc::div(b,
a);};
3581 matop::MatOp<
decltype(div_)> aOp(div_,
pImpl->GetErrorInterpreter(), fVal);
3586 auto div_ = [](
double a,
double b){
return sc::div(
a, b);};
3587 matop::MatOp<
decltype(div_)> aOp(div_,
pImpl->GetErrorInterpreter(), fVal);
3596 auto pow_ = [](
double a,
double b){
return sc::power(b,
a);};
3597 matop::MatOp<
decltype(pow_)> aOp(pow_,
pImpl->GetErrorInterpreter(), fVal);
3602 auto pow_ = [](
double a,
double b){
return sc::power(
a, b);};
3603 matop::MatOp<
decltype(pow_)> aOp(pow_,
pImpl->GetErrorInterpreter(), fVal);
3612 pImpl->ExecuteOperation(rStartPos, rEndPos, aDoubleFunc, aBoolFunc, aStringFunc, aEmptyFunc);
3621void ScMatrix::Dump()
const
3630 pImpl->MatConcat(nMaxCol, nMaxRow, xMat1, xMat2, rFormatter, rPool);
3636 pImpl->ExecuteBinaryOp(nMaxCol, nMaxRow, rInputMat1, rInputMat2, pInterpreter, op);
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 ExecuteBinaryOp(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrix &rInputMat1, const ScMatrix &rInputMat2, ScInterpreter *pInterpreter, ScMatrix::CalculateOpFunction op)
FormulaError GetErrorIfNotString(const MatrixImplType::const_position_type &rPos) const
void PutEmpty(SCSIZE nC, SCSIZE nR)
ScMatrixRef CompareMatrix(sc::Compare &rComp, size_t nMatPos, sc::CompareOptions *pOptions) const
MatrixFlagImplType maMatFlag
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
FormulaError GetErrorIfNotString(SCSIZE nC, SCSIZE nR) const
Use in ScInterpreter to obtain the error code, if any.
std::function< double(double, double)> CalculateOpFunction
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 ExecuteBinaryOp(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrix &rInputMat1, const ScMatrix &rInputMat2, ScInterpreter *pInterpreter, CalculateOpFunction op)
Apply binary operation to values from two input matrices, storing result into this matrix.
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)
const OUString & getString() const
static const SharedString & getEmptyString()
#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_traits > 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_flag_traits > MatrixFlagImplType
mdds::multi_type_matrix< matrix_traits > MatrixImplType
static std::once_flag bElementsMaxFetched
ScInterpreter * mpErrorInterpreter
static std::atomic< 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)