27 #include <osl/thread.h>
38 #include <rtl/character.hxx>
39 #include <rtl/ustring.hxx>
41 #include <osl/diagnose.h>
42 #include <unicode/uchar.h>
43 #include <unicode/regex.h>
48 #include <document.hxx>
59 #include <compiler.hxx>
65 #include <tokenarray.hxx>
77 #include <string_view>
80 const sal_uInt64
n2power48 = SAL_CONST_UINT64( 281474976710656);
85 using ::std::unique_ptr;
89 const short* pJump = pCur->GetJump();
90 short nJumpCount = pJump[ 0 ];
91 MatrixJumpConditionToMatrix();
92 switch ( GetStackType() )
98 PushIllegalParameter();
102 ScTokenMatrixMap::const_iterator aMapIter;
104 pMat->SetErrorInterpreter(
nullptr);
106 pMat->GetDimensions( nCols, nRows );
107 if ( nCols == 0 || nRows == 0 )
109 PushIllegalArgument();
112 else if ((aMapIter = maTokenMatrixMap.find( pCur)) != maTokenMatrixMap.end())
113 xNew = (*aMapIter).second;
116 std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>(
117 pCur->GetOpCode(), nCols, nRows));
118 for (
SCSIZE nC=0; nC < nCols; ++nC )
120 for (
SCSIZE nR=0; nR < nRows; ++nR )
124 bool bIsValue = pMat->IsValue(nC, nR);
127 fVal = pMat->GetDouble(nC, nR);
128 bIsValue = std::isfinite(fVal);
129 bTrue = bIsValue && (fVal != 0.0);
139 bIsValue = pMat->IsValueOrEmpty(nC, nR);
145 if( nJumpCount >= 2 )
147 pJumpMat->SetJump( nC, nR, fVal,
149 pJump[ nJumpCount ]);
153 pJumpMat->SetJump( nC, nR, fVal,
155 pJump[ nJumpCount ]);
160 if( nJumpCount == 3 && bIsValue )
162 pJumpMat->SetJump( nC, nR, fVal,
164 pJump[ nJumpCount ]);
169 pJumpMat->SetJump( nC, nR, fVal,
171 pJump[ nJumpCount ]);
177 GetTokenMatrixMap().emplace(pCur, xNew);
181 PushIllegalArgument();
186 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
192 const bool bCondition = GetBool();
193 if (nGlobalError != FormulaError::NONE)
195 PushError(nGlobalError);
196 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
198 else if ( bCondition )
200 if( nJumpCount >= 2 )
202 aCode.Jump( pJump[ 1 ], pJump[ nJumpCount ] );
206 nFuncFmtType = SvNumFormatType::LOGICAL;
208 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
213 if( nJumpCount == 3 )
215 aCode.Jump( pJump[ 2 ], pJump[ nJumpCount ] );
219 nFuncFmtType = SvNumFormatType::LOGICAL;
221 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
239 else if ( pMat->
IsEmpty( nC, nR ) )
252 short nJumpCount = pJump[ 0 ];
253 if (!
sp || nJumpCount != 2)
256 nGlobalError = (
sp ? FormulaError::ParameterExpected : FormulaError::UnknownStackVariable);
258 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
273 if (nOldGlobalError != FormulaError::NONE)
320 SCSIZE nErrorCol = ::std::numeric_limits<SCSIZE>::max(),
321 nErrorRow = ::std::numeric_limits<SCSIZE>::max();
323 pMat->GetDimensions( nCols, nRows );
324 if (nCols == 0 || nRows == 0)
329 for (
SCSIZE nC=0; nC < nCols && !bError; ++nC)
331 for (
SCSIZE nR=0; nR < nRows && !bError; ++nR)
334 if (nErr != FormulaError::NONE && (!bNAonly || nErr == FormulaError::NotAvailable))
346 ScTokenMatrixMap::const_iterator aMapIter;
349 xNew = (*aMapIter).second;
353 const ScMatrix* pMatPtr = pMat.get();
354 std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>(
359 pJumpMat->SetAllJumps( fFlagResult, pJump[ nJumpCount ], pJump[ nJumpCount ] );
363 for ( ; nC < nCols && (nC != nErrorCol || nR != nErrorRow); )
365 for (nR = 0 ; nR < nRows && (nC != nErrorCol || nR != nErrorRow); ++nR)
369 if (nC != nErrorCol && nR != nErrorRow)
373 for ( ; nC < nCols; ++nC)
375 for ( ; nR < nRows; ++nR)
378 if (nErr != FormulaError::NONE && (!bNAonly || nErr == FormulaError::NotAvailable))
380 pJumpMat->SetJump( nC, nR, 1.0, pJump[ 1 ], pJump[ nJumpCount ] );
395 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
401 if (bError && (!bNAonly ||
nGlobalError == FormulaError::NotAvailable))
405 aCode.
Jump( pJump[ 1 ], pJump[ nJumpCount ] );
412 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
420 bool bHaveJump =
false;
422 short nJumpCount = pJump[ 0 ];
434 ScTokenMatrixMap::const_iterator aMapIter;
436 pMat->SetErrorInterpreter(
nullptr);
438 pMat->GetDimensions( nCols, nRows );
439 if ( nCols == 0 || nRows == 0 )
443 xNew = (*aMapIter).second;
446 std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>(
448 for (
SCSIZE nC=0; nC < nCols; ++nC )
450 for (
SCSIZE nR=0; nR < nRows; ++nR )
453 bool bIsValue = pMat->IsValue(nC, nR);
456 fVal = pMat->GetDouble(nC, nR);
457 bIsValue = std::isfinite( fVal );
460 fVal = ::rtl::math::approxFloor( fVal);
461 if ( (fVal < 1) || (fVal >= nJumpCount))
465 FormulaError::IllegalArgument);
475 pJumpMat->SetJump( nC, nR, fVal,
476 pJump[ static_cast<short>(fVal) ],
477 pJump[ nJumpCount ]);
481 pJumpMat->SetJump( nC, nR, fVal,
483 pJump[ nJumpCount ]);
494 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
503 if (
nGlobalError == FormulaError::NONE && (nJumpIndex >= 1) && (nJumpIndex < nJumpCount))
505 aCode.
Jump( pJump[ static_cast<short>(nJumpIndex) ], pJump[ nJumpCount ] );
513 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
518 SCSIZE nJumpCols, nJumpRows;
519 SCSIZE nResCols, nResRows;
520 SCSIZE nAdjustCols, nAdjustRows;
523 if (!(( nJumpCols == 1 && nParmCols > nResCols ) ||
524 ( nJumpRows == 1 && nParmRows > nResRows )))
527 if ( nJumpCols == 1 && nJumpRows == 1 )
529 nAdjustCols = std::max(nParmCols, nResCols);
530 nAdjustRows = std::max(nParmRows, nResRows);
532 else if ( nJumpCols == 1 )
534 nAdjustCols = nParmCols;
535 nAdjustRows = nResRows;
539 nAdjustCols = nResCols;
540 nAdjustRows = nParmRows;
550 if ( nStackLevel == 2 )
556 assert(!
"pop goes the weasel");
562 SetError( FormulaError::UnknownStackVariable );
636 if (eReturnType == ParamClass::Reference)
641 aRef.
Ref1 = aRef.
Ref2 = *(xRef->GetSingleRef());
682 aAdr.
SetCol( static_cast<SCCOL>(nCol) );
683 aAdr.
SetRow( static_cast<SCROW>(nRow) );
718 if (eReturnType == ParamClass::Reference)
737 switch (pToken->GetType())
752 assert(!
"unhandled svExternalSingleRef case");
754 FormulaError::UnknownStackVariable), nC, nR );
778 pMat->GetDimensions( nCols, nRows );
779 if ((nCols <= nC && nCols != 1) ||
780 (nRows <= nR && nRows != 1))
790 pMat->SetErrorInterpreter(
nullptr);
818 short nStart, nNext, nStop;
820 while ( bCont && nStart == nNext )
834 if ( bCont && nStart != nNext )
837 for (
auto const &
i : rParams )
890 for(
short i = 1;
i >= 0;
i-- )
937 SetError( FormulaError::IllegalParameter);
942 pMat->GetDimensions(nC, nR);
945 SetError( FormulaError::IllegalParameter);
948 if (pMat->IsEmpty(0, 0))
950 else if (pMat->IsStringOrEmpty(0, 0))
952 rCell.
maStr = pMat->GetString(0, 0);
957 rCell.
mfValue = pMat->GetDouble(0, 0);
972 SetError( FormulaError::IllegalParameter);
989 for(
short i = 1;
i >= 0;
i-- )
1034 SetError( FormulaError::IllegalParameter);
1036 aMat[
i].
mpMat->SetErrorInterpreter(
nullptr);
1041 SetError( FormulaError::IllegalParameter);
1054 if (aMat[0].mpMat && aMat[1].mpMat)
1058 aMat[0].
mpMat->GetDimensions(nC0, nR0);
1059 aMat[1].
mpMat->GetDimensions(nC1, nR1);
1060 SCSIZE nC = std::max( nC0, nC1 );
1061 SCSIZE nR = std::max( nR0, nR1 );
1065 for (
SCSIZE j=0; j<nC; j++ )
1067 for (
SCSIZE k=0; k<nR; k++ )
1069 SCSIZE nCol = j, nRow = k;
1070 if (aMat[0].mpMat->ValidColRowOrReplicated(nCol, nRow) &&
1071 aMat[1].
mpMat->ValidColRowOrReplicated(nCol, nRow))
1073 for (
short i=1;
i>=0;
i-- )
1077 if (aMat[
i].mpMat->IsStringOrEmpty(j, k))
1093 aRes.
mpMat->PutError( FormulaError::NoValue, j, k);
1100 aRes.
mpMat->CompareEqual();
1103 aRes.
mpMat->CompareLess();
1106 aRes.
mpMat->CompareGreater();
1109 aRes.
mpMat->CompareLessEqual();
1112 aRes.
mpMat->CompareGreaterEqual();
1115 aRes.
mpMat->CompareNotEqual();
1118 SAL_WARN(
"sc",
"ScInterpreter::QueryMat: unhandled comparison operator: " << static_cast<int>(eOp));
1123 else if (aMat[0].mpMat || aMat[1].mpMat)
1125 size_t i = ( aMat[0].
mpMat ? 0 : 1);
1157 if (
nGlobalError != FormulaError::NONE || !pResultMatrix)
1159 SetError( FormulaError::IllegalParameter);
1160 return pResultMatrix;
1163 return pResultMatrix;
1275 bool bHaveValue =
false;
1277 size_t nRefInList = 0;
1278 while( nParamCount-- > 0)
1318 if ( aValIter.
GetFirst( fVal, nErr ) && nErr == FormulaError::NONE )
1323 bRes &= ( fVal != 0.0 );
1324 }
while ( (nErr == FormulaError::NONE) &&
1325 aValIter.
GetNext( fVal, nErr ) );
1339 double fVal = pMat->And();
1341 if ( nErr != FormulaError::NONE )
1347 bRes &= (fVal != 0.0);
1354 SetError( FormulaError::IllegalParameter);
1373 bool bHaveValue =
false;
1375 size_t nRefInList = 0;
1376 while( nParamCount-- > 0)
1416 if ( aValIter.
GetFirst( fVal, nErr ) )
1421 bRes |= ( fVal != 0.0 );
1422 }
while ( (nErr == FormulaError::NONE) &&
1423 aValIter.
GetNext( fVal, nErr ) );
1438 double fVal = pMat->Or();
1440 if ( nErr != FormulaError::NONE )
1446 bRes |= (fVal != 0.0);
1453 SetError( FormulaError::IllegalParameter);
1473 bool bHaveValue =
false;
1475 size_t nRefInList = 0;
1476 while( nParamCount-- > 0)
1518 if ( aValIter.
GetFirst( fVal, nErr ) )
1523 bRes ^= ( fVal != 0.0 );
1524 }
while ( (nErr == FormulaError::NONE) &&
1525 aValIter.
GetNext( fVal, nErr ) );
1540 double fVal = pMat->Xor();
1542 if ( nErr != FormulaError::NONE )
1548 bRes ^= ( fVal != 0.0 );
1555 SetError( FormulaError::IllegalParameter);
1582 pMat->GetDimensions( nC, nR );
1588 pMat->NegOp( *pResMat);
1626 pMat->GetDimensions( nC, nR );
1632 pMat->NotOp( *pResMat);
1649 double num1 = ::rtl::math::approxFloor(
GetDouble());
1650 double num2 = ::rtl::math::approxFloor(
GetDouble());
1651 if ( (num1 >=
n2power48) || (num1 < 0) ||
1655 PushDouble (static_cast<sal_uInt64>(num1) & static_cast<sal_uInt64>(num2));
1664 double num1 = ::rtl::math::approxFloor(
GetDouble());
1665 double num2 = ::rtl::math::approxFloor(
GetDouble());
1666 if ( (num1 >=
n2power48) || (num1 < 0) ||
1670 PushDouble (static_cast<sal_uInt64>(num1) | static_cast<sal_uInt64>(num2));
1679 double num1 = ::rtl::math::approxFloor(
GetDouble());
1680 double num2 = ::rtl::math::approxFloor(
GetDouble());
1681 if ( (num1 >=
n2power48) || (num1 < 0) ||
1685 PushDouble (static_cast<sal_uInt64>(num1) ^ static_cast<sal_uInt64>(num2));
1694 double fShift = ::rtl::math::approxFloor(
GetDouble());
1695 double num = ::rtl::math::approxFloor(
GetDouble());
1702 fRes = ::rtl::math::approxFloor( num / pow( 2.0, -fShift));
1703 else if (fShift == 0)
1706 fRes = num * pow( 2.0, fShift);
1717 double fShift = ::rtl::math::approxFloor(
GetDouble());
1718 double num = ::rtl::math::approxFloor(
GetDouble());
1725 fRes = num * pow( 2.0, -fShift);
1726 else if (fShift == 0)
1729 fRes = ::rtl::math::approxFloor( num / pow( 2.0, fShift));
1740 double fFirst,
double fLast )
1753 nCols = std::max<SCCOL>(0,
static_cast<SCCOL>(nC));
1754 nRows = std::max<SCROW>(0,
static_cast<SCROW>(nR));
1759 if (nCols == 1 && nRows == 1)
1778 ScMatrixRef pResMat =
GetNewMat( static_cast<SCSIZE>(nCols), static_cast<SCSIZE>(nRows),
true );
1785 for (
SCROW j=0; j < nRows; ++j)
1787 pResMat->PutDouble( RandomFunc( fFirst, fLast),
1788 static_cast<SCSIZE>(
i), static_cast<SCSIZE>(j));
1802 auto RandomFunc = []( double, double )
1816 double fMax = rtl::math::round(
GetDouble(), 0, rtl_math_RoundingMode_Up);
1817 double fMin = rtl::math::round(
GetDouble(), 0, rtl_math_RoundingMode_Up);
1823 fMax = std::nextafter( fMax+1, -DBL_MAX);
1824 auto RandomFunc = [](
double fFirst,
double fLast )
1930 if (fabs(fVal) >= 1.0)
1939 if (fabs(nVal) <= 1.0)
1988 if (!static_cast<const ScEmptyCellToken*>(p.get())->IsInherited())
2014 nRes = pMat->IsEmptyCell( 0, 0) ? 1 : 0;
2017 SCSIZE nCols, nRows, nC, nR;
2018 pMat->GetDimensions( nCols, nRows);
2020 if ( nC < nCols && nR < nRows )
2021 nRes = pMat->IsEmptyCell( nC, nR) ? 1 : 0;
2083 bRes = pMat->IsStringOrEmpty(0, 0) && !pMat->IsEmpty(0, 0);
2086 SCSIZE nCols, nRows, nC, nR;
2087 pMat->GetDimensions( nCols, nRows);
2089 if ( nC < nCols && nR < nRows )
2090 bRes = pMat->IsStringOrEmpty( nC, nR) && !pMat->IsEmpty( nC, nR);
2145 bRes = (
nCurFmtType == SvNumFormatType::LOGICAL );
2235 return pFormat && pFormat->
GetColor( 1 );
2259 if( nParamCount == 2 )
2276 aCellPos = aRange.
aStart;
2297 if( aInfoType ==
"COL" )
2301 else if( aInfoType ==
"ROW" )
2305 else if( aInfoType ==
"SHEET" )
2309 else if( aInfoType ==
"ADDRESS" )
2315 else if( aInfoType ==
"FILENAME" )
2318 OUString aFuncResult;
2339 else if( aInfoType ==
"COORD" )
2342 OUString aCellStr1 =
2345 OUString aCellStr2 =
2348 OUString aFuncResult = aCellStr1 +
":" + aCellStr2;
2353 else if( aInfoType ==
"CONTENTS" )
2364 else if( aInfoType ==
"TYPE" )
2373 else if( aInfoType ==
"WIDTH" )
2383 pPrinter->
SetFont( aDefFont );
2385 assert(nZeroWidth != 0);
2386 pPrinter->
SetFont( aOldFont );
2391 else if( aInfoType ==
"PREFIX" )
2397 switch( pJustAttr->GetValue() )
2399 case SvxCellHorJustify::Standard:
2400 case SvxCellHorJustify::Left:
2401 case SvxCellHorJustify::Block: c =
'\'';
break;
2402 case SvxCellHorJustify::Center: c =
'^';
break;
2403 case SvxCellHorJustify::Right: c =
'"';
break;
2404 case SvxCellHorJustify::Repeat: c =
'\\';
break;
2409 else if( aInfoType ==
"PROTECT" )
2416 else if( aInfoType ==
"FORMAT" )
2418 OUString aFuncResult;
2420 getFormatString(
pFormatter, nFormat, aFuncResult);
2423 else if( aInfoType ==
"COLOR" )
2428 else if( aInfoType ==
"PARENTHESES" )
2474 if ( aInfoType ==
"COL" )
2476 else if ( aInfoType ==
"ROW" )
2478 else if ( aInfoType ==
"SHEET" )
2488 else if ( aInfoType ==
"ADDRESS" )
2498 else if ( aInfoType ==
"FILENAME" )
2510 OUString
aBuf =
"'" + *p +
"'#$" + aTabName;
2513 else if ( aInfoType ==
"CONTENTS" )
2515 switch (pToken->GetType())
2521 PushString(OUString::number(pToken->GetDouble()));
2530 else if ( aInfoType ==
"TYPE" )
2533 switch (pToken->GetType())
2546 else if ( aInfoType ==
"FORMAT" )
2553 else if ( aInfoType ==
"COLOR" )
2564 else if ( aInfoType ==
"PARENTHESES" )
2605 bRes = !x->GetRefList()->empty();
2681 if (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NONE)
2682 bRes = pMat->IsValue( 0, 0);
2686 SCSIZE nCols, nRows, nC, nR;
2687 pMat->GetDimensions( nCols, nRows);
2689 if ( nC < nCols && nR < nRows )
2690 if (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NONE)
2691 bRes = pMat->IsValue( nC, nR);
2714 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2727 static_cast<SCSIZE>(nRow2 - nRow1 + 1),
true);
2737 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2740 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2782 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2788 SetError( FormulaError::IllegalArgument);
2799 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2802 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2813 pResMat->PutError( FormulaError::NotAvailable, i,j);
2838 SetError( FormulaError::NotAvailable );
2844 SetError( FormulaError::NotAvailable );
2866 bRes = (nErr == FormulaError::NotAvailable);
2875 (pToken && pToken->GetType() ==
svError && pToken->GetError() == FormulaError::NotAvailable))
2886 bRes = (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NotAvailable);
2889 SCSIZE nCols, nRows, nC, nR;
2890 pMat->GetDimensions( nCols, nRows);
2892 if ( nC < nCols && nR < nRows )
2893 bRes = (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NotAvailable);
2923 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
2932 (pToken->GetType() ==
svError && pToken->GetError() != FormulaError::NotAvailable))
2945 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
2949 SCSIZE nCols, nRows, nC, nR;
2950 pMat->GetDimensions( nCols, nRows);
2952 if ( nC < nCols && nR < nRows )
2954 FormulaError nErr = pMat->GetErrorIfNotString( nC, nR);
2955 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
3008 bRes = (pMat->GetErrorIfNotString( 0, 0) != FormulaError::NONE);
3011 SCSIZE nCols, nRows, nC, nR;
3012 pMat->GetDimensions( nCols, nRows);
3014 if ( nC < nCols && nR < nRows )
3015 bRes = (pMat->GetErrorIfNotString( nC, nR) != FormulaError::NONE);
3044 if (nErr != FormulaError::NONE)
3079 fVal = pToken->GetDouble();
3092 bRes = pMat->IsValue( 0, 0);
3094 fVal = pMat->GetDouble( 0, 0);
3098 SCSIZE nCols, nRows, nC, nR;
3099 pMat->GetDimensions( nCols, nRows);
3101 if ( nC < nCols && nR < nRows )
3103 bRes = pMat->IsValue( nC, nR);
3105 fVal = pMat->GetDouble( nC, nR);
3116 SetError( FormulaError::IllegalParameter);
3118 bRes = ( fmod( ::rtl::math::approxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
3142 if (nErr != FormulaError::NONE)
3153 OUStringBuffer
aStr;
3155 const sal_Unicode*
const pEnd = p + aVal.getLength();
3158 if ( *p !=
' ' || p[-1] !=
' ' )
3175 const sal_Int32 nLen = aStr.getLength();
3182 while( nPos < nLen )
3184 OUString aTmpStr( aStr[nPos-1] );
3186 aStr[nPos] = aUpr[nPos];
3188 aStr[nPos] = aLwr[nPos];
3206 while ( nIdx < aStr.getLength() )
3208 aStr.iterateCodePoints( &nIdx );
3227 bool bValue =
false;
3277 PushError( FormulaError::UnknownOpCode);
3283 OUString aInputString;
3352 sal_uInt32 nFIndex = 0;
3367 OUString aInputString;
3368 OUString aGroupSeparator;
3371 if ( nParamCount == 3 )
3374 if ( nParamCount >= 2 )
3377 if ( aDecimalSeparator.getLength() == 1 )
3378 cDecimalSeparator = aDecimalSeparator[ 0 ];
3386 if ( cDecimalSeparator && aGroupSeparator.indexOf( cDecimalSeparator ) != -1 )
3404 if ( aInputString.isEmpty() )
3413 sal_Int32 nDecSep = aInputString.indexOf( cDecimalSeparator );
3416 OUString aTemporary( nDecSep >= 0 ? aInputString.copy( 0, nDecSep ) : aInputString );
3418 while (nIndex < aGroupSeparator.getLength())
3420 sal_uInt32 nChar = aGroupSeparator.iterateCodePoints( &nIndex );
3421 aTemporary = aTemporary.replaceAll( OUString( &nChar, 1 ),
"" );
3424 aInputString = aTemporary + aInputString.subView( nDecSep );
3426 aInputString = aTemporary;
3429 for ( sal_Int32
i = aInputString.getLength(); --
i >= 0; )
3432 if ( c == 0x0020 || c == 0x0009 || c == 0x000A || c == 0x000D )
3433 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3435 sal_Int32 nPercentCount = 0;
3436 for ( sal_Int32
i = aInputString.getLength() - 1;
i >= 0 && aInputString[
i ] == 0x0025;
i-- )
3438 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3442 rtl_math_ConversionStatus eStatus;
3443 sal_Int32 nParseEnd;
3444 double fVal = ::rtl::math::stringToDouble( aInputString, cDecimalSeparator, 0, &eStatus, &nParseEnd );
3445 if ( eStatus == rtl_math_ConversionStatus_Ok && nParseEnd == aInputString.getLength() )
3448 fVal *= pow( 10.0, -(nPercentCount * 2));
3457 return ( !u_isISOControl(nCodePoint)
3458 && u_isdefined(nCodePoint) );
3466 OUStringBuffer
aBuf( aStr.getLength() );
3468 while ( nIdx < aStr.getLength() )
3470 sal_uInt32 c = aStr.iterateCodePoints( &nIdx );
3472 aBuf.appendUtf32( c );
3487 const sal_uInt32 convertFlags =
3488 RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
3489 RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE |
3490 RTL_UNICODETOTEXT_FLAGS_FLUSH |
3491 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
3492 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
3493 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE;
3494 PushInt( static_cast<unsigned char>(
OUStringToOString(OUStringChar(aStr[0]), osl_getThreadTextEncoding(), convertFlags).toChar()) );
3502 if (fVal < 0.0 || fVal >= 256.0)
3507 const sal_uInt32 convertFlags =
3508 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
3509 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
3510 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT;
3512 char cEncodedChar =
static_cast<char>(fVal);
3513 OUString
aStr(&cEncodedChar, 1, osl_getThreadTextEncoding(), convertFlags);
3533 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3545 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3595 if (
nGlobalError != FormulaError::NONE || !rtl::isUnicodeCodePoint(nCodePoint))
3599 OUString
aStr( &nCodePoint, 1 );
3606 const std::function<
void(
SCSIZE i,
double fCurrent )>& MatOpFunc,
bool bDoMatOp )
3615 assert(nMatRows > 0);
3616 xResMat =
GetNewMat( 1, nMatRows,
true);
3617 xResMat->FillDouble( fCurrent, 0,0, 0,nMatRows-1);
3623 for (
SCSIZE i=0; i < nMatRows; ++i)
3625 MatOpFunc( i, fCurrent);
3638 double nMin = ::std::numeric_limits<double>::max();
3639 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMin )
3641 double fVecRes = xResMat->GetDouble(0,i);
3642 if (fVecRes > fCurMin)
3643 xResMat->PutDouble( fCurMin, 0,i);
3646 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3651 size_t nRefInList = 0;
3652 while (nParamCount-- > 0)
3659 if (nMin > nVal) nMin = nVal;
3671 if (nMin > nVal) nMin = nVal;
3673 else if (bTextAsZero && aCell.
hasString())
3685 nRefArrayPos == std::numeric_limits<size_t>::max()))
3687 nRefArrayPos = nRefInList;
3702 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3709 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3712 MatOpFunc( nRefArrayPos, nMin);
3715 nMin = std::numeric_limits<double>::max();
3717 nRefArrayPos = std::numeric_limits<size_t>::max();
3744 SetError(FormulaError::IllegalParameter);
3749 SetError(FormulaError::IllegalParameter);
3756 if (nMin < std::numeric_limits<double>::max())
3758 for (
SCSIZE i=0; i < nMatRows; ++i)
3760 MatOpFunc( i, nMin);
3769 for (
SCSIZE i=0; i < nMatRows; ++i)
3771 double fVecRes = xResMat->GetDouble(0,i);
3772 if (fVecRes == std::numeric_limits<double>::max())
3773 xResMat->PutDouble( 0.0, 0,i);
3780 if (!std::isfinite(nVal))
3782 else if ( nVal < nMin )
3796 double nMax = std::numeric_limits<double>::lowest();
3797 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMax )
3799 double fVecRes = xResMat->GetDouble(0,i);
3800 if (fVecRes < fCurMax)
3801 xResMat->PutDouble( fCurMax, 0,i);
3804 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3809 size_t nRefInList = 0;
3810 while (nParamCount-- > 0)
3817 if (nMax < nVal) nMax = nVal;
3829 if (nMax < nVal) nMax = nVal;
3831 else if (bTextAsZero && aCell.
hasString())
3843 nRefArrayPos == std::numeric_limits<size_t>::max()))
3845 nRefArrayPos = nRefInList;
3860 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3867 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3870 MatOpFunc( nRefArrayPos, nMax);
3873 nMax = std::numeric_limits<double>::lowest();
3875 nRefArrayPos = std::numeric_limits<size_t>::max();
3902 SetError(FormulaError::IllegalParameter);
3907 SetError(FormulaError::IllegalParameter);
3914 if (nMax > std::numeric_limits<double>::lowest())
3916 for (
SCSIZE i=0; i < nMatRows; ++i)
3918 MatOpFunc( i, nMax);
3927 for (
SCSIZE i=0; i < nMatRows; ++i)
3929 double fVecRes = xResMat->GetDouble(0,i);
3930 if (fVecRes == -std::numeric_limits<double>::max())
3931 xResMat->PutDouble( 0.0, 0,i);
3938 if (!std::isfinite(nVal))
3940 else if ( nVal > nMax )
3952 struct ArrayRefListValue
3954 std::vector<double> mvValues;
3956 ArrayRefListValue() =
default;
3957 double get()
const {
return mfSum.
get(); }
3959 std::vector<ArrayRefListValue> vArrayValues;
3961 std::vector<double>
values;
3966 size_t nRefInList = 0;
3967 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
3976 values.push_back(fVal);
3990 values.push_back(fVal);
3994 else if (bTextAsZero && aCell.
hasString())
3996 values.push_back(0.0);
4005 size_t nRefArrayPos = nRefInList;
4006 if (vArrayValues.empty())
4009 assert(nMatRows > 0);
4010 vArrayValues.resize(nMatRows);
4011 for (ArrayRefListValue & it : vArrayValues)
4013 it.mvValues = values;
4021 for (ArrayRefListValue & it : vArrayValues)
4023 it.mvValues.insert( it.mvValues.end(), values.begin(), values.end());
4027 ArrayRefListValue& rArrayValue = vArrayValues[nRefArrayPos];
4035 rArrayValue.mvValues.push_back(fVal);
4036 rArrayValue.mfSum += fVal;
4038 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4040 if ( nErr != FormulaError::NONE )
4045 std::vector<double>().
swap(values);
4060 values.push_back(fVal);
4063 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4065 if ( nErr != FormulaError::NONE )
4080 pMat->GetDimensions(nC, nR);
4081 for (
SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
4083 for (
SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
4085 if (!pMat->IsStringOrEmpty(nMatCol,nMatRow))
4087 fVal= pMat->GetDouble(nMatCol,nMatRow);
4090 values.push_back(fVal);
4093 else if (bIgnoreErrVal)
4096 else if ( bTextAsZero )
4098 values.push_back(0.0);
4110 values.push_back(0.0);
4113 SetError(FormulaError::IllegalParameter);
4118 SetError(FormulaError::IllegalParameter);
4122 if (!vArrayValues.empty())
4125 if (!values.empty())
4127 for (
auto & it : vArrayValues)
4129 it.mvValues.insert( it.mvValues.end(), values.begin(), values.end());
4134 for (
SCSIZE r=0; r < nMatRows; ++r)
4136 ::std::vector<double>::size_type
n = vArrayValues[r].mvValues.size();
4138 xResMat->PutError( FormulaError::DivisionByZero, 0, r);
4141 ArrayRefListValue& rArrayValue = vArrayValues[r];
4143 const double vMean = rArrayValue.get() / n;
4144 for (::std::vector<double>::size_type
i = 0;
i < n;
i++)
4145 vSum += ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean) *
4146 ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean);
4147 xResMat->PutDouble( VarResult( vSum, n), 0, r);
4154 ::std::vector<double>::size_type
n = values.size();
4156 SetError( FormulaError::DivisionByZero);
4160 const double vMean = fSum.
get() / n;
4161 for (::std::vector<double>::size_type
i = 0;
i < n;
i++)
4162 vSum += ::rtl::math::approxSub( values[
i], vMean) * ::rtl::math::approxSub( values[i], vMean);
4170 auto VarResult = [](
double fVal,
size_t nValCount )
4175 return fVal / (nValCount - 1);
4182 auto VarResult = [](
double fVal,
size_t nValCount )
4184 return sc::div( fVal, nValCount);
4192 auto VarResult = [](
double fVal,
size_t nValCount )
4197 return sqrt( fVal / (nValCount - 1));
4204 auto VarResult = [](
double fVal,
size_t nValCount )
4209 return sqrt( fVal / nValCount);
4241 while (nParamCount-- > 0)
4250 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4251 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4252 static_cast<sal_uLong>(nCol2 - nCol1 + 1);
4260 pMat->GetDimensions(nC, nR);
4282 SetError(FormulaError::IllegalParameter);
4298 while (nParamCount-- > 0)
4307 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4308 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4309 static_cast<sal_uLong>(nRow2 - nRow1 + 1);
4317 pMat->GetDimensions(nC, nR);
4339 SetError(FormulaError::IllegalParameter);
4349 if ( nParamCount == 0 )
4360 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
4370 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4371 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1);
4385 SetError( FormulaError::IllegalParameter );
4399 if (nParamCount == 0)
4419 pResMat->PutDouble( nVal +
i, static_cast<SCSIZE>(
i), 0);
4435 nVal =
static_cast<double>(nCol1 + 1);
4445 nVal =
static_cast<double>( aAbsRef.
Col() + 1 );
4460 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4475 static_cast<SCSIZE>(nCol2-nCol1+1), 1,
true);
4478 for (
SCCOL i = nCol1;
i <= nCol2;
i++)
4479 pResMat->PutDouble(static_cast<double>(
i+1),
4480 static_cast<SCSIZE>(
i-nCol1), 0);
4486 nVal =
static_cast<double>(nCol1 + 1);
4490 SetError( FormulaError::IllegalParameter );
4503 if (nParamCount == 0)
4523 pResMat->PutDouble( nVal +
i, 0, static_cast<SCSIZE>(
i));
4539 nVal =
static_cast<double>(nRow1 + 1);
4549 nVal =
static_cast<double>( aAbsRef.
Row() + 1 );
4563 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4578 static_cast<SCSIZE>(nRow2-nRow1+1),
true);
4581 for (
SCROW i = nRow1;
i <= nRow2;
i++)
4582 pResMat->PutDouble(static_cast<double>(
i+1), 0,
4583 static_cast<SCSIZE>(
i-nRow1));
4589 nVal =
static_cast<double>(nRow1 + 1);
4593 SetError( FormulaError::IllegalParameter );
4606 if ( nParamCount == 0 )
4618 SetError( FormulaError::IllegalArgument );
4638 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4643 SetError( FormulaError::IllegalParameter );
4653 class VectorMatrixAccessor
4656 VectorMatrixAccessor(
const ScMatrix& rMat,
bool bColVec) :
4657 mrMat(rMat), mbColVec(bColVec) {}
4659 bool IsEmpty(
SCSIZE i)
const
4661 return mbColVec ? mrMat.IsEmpty(0, i) : mrMat.IsEmpty(i, 0);
4664 bool IsEmptyPath(
SCSIZE i)
const
4666 return mbColVec ? mrMat.IsEmptyPath(0, i) : mrMat.IsEmptyPath(i, 0);
4669 bool IsValue(
SCSIZE i)
const
4671 return mbColVec ? mrMat.IsValue(0, i) : mrMat.IsValue(i, 0);
4674 bool IsStringOrEmpty(
SCSIZE i)
const
4676 return mbColVec ? mrMat.IsStringOrEmpty(0, i) : mrMat.IsStringOrEmpty(i, 0);
4679 double GetDouble(
SCSIZE i)
const
4681 return mbColVec ? mrMat.GetDouble(0, i) : mrMat.GetDouble(i, 0);
4686 return mbColVec ? mrMat.GetString(0, i).getString() : mrMat.GetString(i, 0).getString();
4689 SCSIZE GetElementCount()
const
4692 mrMat.GetDimensions(nC, nR);
4693 return mbColVec ? nR : nC;
4704 sal_Int32 lcl_CompareMatrix2Query(
4707 if (rMat.IsEmpty(i))
4718 if (rMat.IsValue(i))
4720 const double nVal1 = rMat.GetDouble(i);
4721 if (!std::isfinite(nVal1))
4737 return nVal1 < nVal2 ? -1 : 1;
4743 OUString aStr1 = rMat.GetString(i);
4751 void lcl_GetLastMatch(
SCSIZE& rIndex,
const VectorMatrixAccessor& rMat,
4754 if (rMat.IsValue(rIndex))
4756 double nVal = rMat.GetDouble(rIndex);
4757 while (rIndex < nMatCount-1 && rMat.IsValue(rIndex+1) &&
4758 nVal == rMat.GetDouble(rIndex+1))
4762 else if (rMat.IsEmptyPath(rIndex))
4764 while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
4767 else if (rMat.IsEmpty(rIndex))
4769 while (rIndex < nMatCount-1 && rMat.IsEmpty(rIndex+1))
4772 else if (rMat.IsStringOrEmpty(rIndex))
4774 OUString
aStr( rMat.GetString(rIndex));
4775 while (rIndex < nMatCount-1 && rMat.IsStringOrEmpty(rIndex+1) &&
4776 aStr == rMat.GetString(rIndex+1))
4781 OSL_FAIL(
"lcl_GetLastMatch: unhandled matrix type");
4795 if (nParamCount == 3)
4816 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4817 if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
4848 rParam.
nCol1 = nCol1;
4849 rParam.
nRow1 = nRow1;
4850 rParam.
nCol2 = nCol2;
4851 rParam.
nTab = nTab1;
4859 else if (fTyp > 0.0)
4913 rItem.
mfVal = pToken->GetDouble();
4918 rItem.
maString = pToken->GetString();
4952 pMatSrc->GetDimensions( nC, nR);
4953 if (nC > 1 && nR > 1)
4961 pMatSrc->SetErrorInterpreter(
nullptr);
4963 SCSIZE nMatCount = (nC == 1) ? nR : nC;
4964 VectorMatrixAccessor aMatAcc(*pMatSrc, nC == 1);
4971 for (
SCSIZE i = 0; i < nMatCount; ++i)
4973 if (lcl_CompareMatrix2Query( i, aMatAcc, rEntry) == 0)
4987 SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
4988 for (
SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
4990 SCSIZE nMid = nFirst + nLen/2;
4991 sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, aMatAcc, rEntry);
4995 lcl_GetLastMatch( nMid, aMatAcc, nMatCount);
5003 nHitIndex = bAscOrder ? nLast : nFirst;
5005 nHitIndex = bAscOrder ? nFirst : nLast;
5025 if (nHitIndex == nMatCount-1)
5027 sal_Int32 nCmp = lcl_CompareMatrix2Query( nHitIndex, aMatAcc, rEntry);
5028 if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
5050 rParam.
nRow2 = nRow2;
5052 ScAddress aResultPos( nCol1, nRow1, nTab1);
5058 nDelta = aResultPos.
Row() - nRow1;
5064 rParam.
nRow2 = nRow1;
5088 nDelta = nC - nCol1;
5149 if (!isCellContentEmpty(aCell))
5158 SCSIZE nRefListArrayPos = 0;
5159 size_t nRefInList = 0;
5160 while (nParam-- > 0)
5162 nRefListArrayPos = nRefInList;
5170 for (
bool bHas = aIter.
first(); bHas; bHas = aIter.
next())
5173 if (!isCellContentEmpty(rCell))
5178 xResMat->PutDouble( nMaxCount -
nCount, 0, nRefListArrayPos);
5190 SetError( FormulaError::IllegalParameter);
5194 xMat->GetDimensions( nC, nR);
5195 nMaxCount = nC * nR;
5200 nCount = xMat->Count(
true,
true,
true);
5204 default :
SetError(FormulaError::IllegalParameter);
break;
5223 bool bSumExtraRange = (nParamCount == 3);
5236 PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
5237 if ( nTabJunk != nTab3 )
5239 PushError( FormulaError::IllegalParameter);
5263 pSumExtraMatrix->PutDouble(pToken->GetDouble(), 0, 0);
5265 pSumExtraMatrix->PutString(pToken->GetString(), 0, 0);
5272 PushError( FormulaError::IllegalParameter);
5279 bool bIsString =
true;
5336 fVal = pToken->GetDouble();
5340 aString = pToken->GetString();
5353 double fCount = 0.0;
5358 SCSIZE nRefListArrayPos = 0;
5359 size_t nRefInList = 0;
5360 while (nParam-- > 0)
5375 SetError( FormulaError::IllegalParameter);
5379 nRefListArrayPos = nRefInList;
5382 aRange.
GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
5386 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
5401 PushError( FormulaError::IllegalParameter);