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>
80const sal_uInt64
n2power48 = SAL_CONST_UINT64( 281474976710656);
85using ::std::unique_ptr;
90 short nJumpCount = pJump[ 0 ];
102 ScTokenMatrixMap::const_iterator aMapIter;
104 pMat->SetErrorInterpreter(
nullptr);
106 pMat->GetDimensions( nCols, nRows );
107 if ( nCols == 0 || nRows == 0 )
113 xNew = (*aMapIter).second;
116 std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>(
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 ]);
186 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
192 const bool bCondition =
GetBool();
196 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
198 else if ( bCondition )
200 if( nJumpCount >= 2 )
202 aCode.
Jump( pJump[ 1 ], pJump[ nJumpCount ] );
208 aCode.
Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
213 if( nJumpCount == 3 )
215 aCode.
Jump( pJump[ 2 ], pJump[ nJumpCount ] );
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());
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;
1271 short nParamCount =
GetByte();
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);
1369 short nParamCount =
GetByte();
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);
1469 short nParamCount =
GetByte();
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)
1785 for (
SCROW j=0; j < nRows; ++j)
1787 pResMat->PutDouble( RandomFunc( fFirst, fLast),
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)
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" )
2322 case FormulaGrammar::CONV_OOO:
2323 case FormulaGrammar::CONV_XL_A1:
2324 case FormulaGrammar::CONV_XL_R1C1:
2333 else if( aInfoType ==
"FILENAME" )
2336 OUString aFuncResult;
2351 if (eConv == FormulaGrammar::CONV_UNSPECIFIED)
2354 if (eConv == FormulaGrammar::CONV_XL_A1 ||
2355 eConv == FormulaGrammar::CONV_XL_R1C1 ||
2356 eConv == FormulaGrammar::CONV_XL_OOX)
2375 else if( aInfoType ==
"COORD" )
2378 OUString aCellStr1 =
2381 OUString aCellStr2 =
2384 OUString aFuncResult = aCellStr1 +
":" + aCellStr2;
2389 else if( aInfoType ==
"CONTENTS" )
2400 else if( aInfoType ==
"TYPE" )
2409 else if( aInfoType ==
"WIDTH" )
2421 assert(nZeroWidth != 0);
2422 pPrinter->
SetFont( aOldFont );
2427 else if( aInfoType ==
"PREFIX" )
2433 switch( pJustAttr->GetValue() )
2435 case SvxCellHorJustify::Standard:
2436 case SvxCellHorJustify::Left:
2437 case SvxCellHorJustify::Block: c =
'\'';
break;
2438 case SvxCellHorJustify::Center: c =
'^';
break;
2439 case SvxCellHorJustify::Right: c =
'"';
break;
2440 case SvxCellHorJustify::Repeat: c =
'\\';
break;
2445 else if( aInfoType ==
"PROTECT" )
2452 else if( aInfoType ==
"FORMAT" )
2454 OUString aFuncResult;
2456 getFormatString(
pFormatter, nFormat, aFuncResult);
2459 else if( aInfoType ==
"COLOR" )
2464 else if( aInfoType ==
"PARENTHESES" )
2510 if ( aInfoType ==
"COL" )
2512 else if ( aInfoType ==
"ROW" )
2514 else if ( aInfoType ==
"SHEET" )
2524 else if ( aInfoType ==
"ADDRESS" )
2534 else if ( aInfoType ==
"FILENAME" )
2546 if (eConv == FormulaGrammar::CONV_UNSPECIFIED)
2549 if (eConv == FormulaGrammar::CONV_XL_A1 ||
2550 eConv == FormulaGrammar::CONV_XL_R1C1 ||
2551 eConv == FormulaGrammar::CONV_XL_OOX)
2554 sal_Int32
nPos =
p->lastIndexOf(
'/');
2555 aBuf = OUString::Concat(
p->subView(0,
nPos + 1))
2556 +
"[" +
p->subView(
nPos + 1) +
"]"
2562 aBuf =
"'" + *
p +
"'#$" + aTabName;
2567 else if ( aInfoType ==
"CONTENTS" )
2569 switch (pToken->GetType())
2575 PushString(OUString::number(pToken->GetDouble()));
2584 else if ( aInfoType ==
"TYPE" )
2587 switch (pToken->GetType())
2600 else if ( aInfoType ==
"FORMAT" )
2607 else if ( aInfoType ==
"COLOR" )
2618 else if ( aInfoType ==
"PARENTHESES" )
2659 bRes = !
x->GetRefList()->empty();
2735 if (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NONE)
2736 bRes = pMat->IsValue( 0, 0);
2740 SCSIZE nCols, nRows, nC, nR;
2741 pMat->GetDimensions( nCols, nRows);
2743 if ( nC < nCols && nR < nRows )
2744 if (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NONE)
2745 bRes = pMat->IsValue( nC, nR);
2768 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2781 static_cast<SCSIZE>(nRow2 - nRow1 + 1),
true);
2791 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2794 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2836 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2842 SetError( FormulaError::IllegalArgument);
2853 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2856 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2867 pResMat->PutError( FormulaError::NotAvailable,
i,j);
2892 SetError( FormulaError::NotAvailable );
2898 SetError( FormulaError::NotAvailable );
2920 bRes = (nErr == FormulaError::NotAvailable);
2929 (pToken && pToken->GetType() ==
svError && pToken->GetError() == FormulaError::NotAvailable))
2940 bRes = (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NotAvailable);
2943 SCSIZE nCols, nRows, nC, nR;
2944 pMat->GetDimensions( nCols, nRows);
2946 if ( nC < nCols && nR < nRows )
2947 bRes = (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NotAvailable);
2977 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
2986 (pToken->GetType() ==
svError && pToken->GetError() != FormulaError::NotAvailable))
2999 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
3003 SCSIZE nCols, nRows, nC, nR;
3004 pMat->GetDimensions( nCols, nRows);
3006 if ( nC < nCols && nR < nRows )
3008 FormulaError nErr = pMat->GetErrorIfNotString( nC, nR);
3009 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
3062 bRes = (pMat->GetErrorIfNotString( 0, 0) != FormulaError::NONE);
3065 SCSIZE nCols, nRows, nC, nR;
3066 pMat->GetDimensions( nCols, nRows);
3068 if ( nC < nCols && nR < nRows )
3069 bRes = (pMat->GetErrorIfNotString( nC, nR) != FormulaError::NONE);
3098 if (nErr != FormulaError::NONE)
3133 fVal = pToken->GetDouble();
3146 bRes = pMat->IsValue( 0, 0);
3148 fVal = pMat->GetDouble( 0, 0);
3152 SCSIZE nCols, nRows, nC, nR;
3153 pMat->GetDimensions( nCols, nRows);
3155 if ( nC < nCols && nR < nRows )
3157 bRes = pMat->IsValue( nC, nR);
3159 fVal = pMat->GetDouble( nC, nR);
3170 SetError( FormulaError::IllegalParameter);
3172 bRes = ( fmod( ::rtl::math::approxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
3196 if (nErr != FormulaError::NONE)
3207 OUStringBuffer
aStr;
3212 if ( *
p !=
' ' ||
p[-1] !=
' ' )
3229 const sal_Int32 nLen =
aStr.getLength();
3236 while(
nPos < nLen )
3260 while ( nIdx <
aStr.getLength() )
3262 aStr.iterateCodePoints( &nIdx );
3281 bool bValue =
false;
3331 PushError( FormulaError::UnknownOpCode);
3337 OUString aInputString;
3406 sal_uInt32 nFIndex = 0;
3421 OUString aInputString;
3422 OUString aGroupSeparator;
3425 if ( nParamCount == 3 )
3428 if ( nParamCount >= 2 )
3431 if ( aDecimalSeparator.getLength() == 1 )
3432 cDecimalSeparator = aDecimalSeparator[ 0 ];
3440 if ( cDecimalSeparator && aGroupSeparator.indexOf( cDecimalSeparator ) != -1 )
3458 if ( aInputString.isEmpty() )
3467 sal_Int32 nDecSep = aInputString.indexOf( cDecimalSeparator );
3470 OUString aTemporary( nDecSep >= 0 ? aInputString.copy( 0, nDecSep ) : aInputString );
3472 while (
nIndex < aGroupSeparator.getLength())
3474 sal_uInt32 nChar = aGroupSeparator.iterateCodePoints( &
nIndex );
3475 aTemporary = aTemporary.replaceAll( OUString( &nChar, 1 ),
"" );
3478 aInputString = aTemporary + aInputString.subView( nDecSep );
3480 aInputString = aTemporary;
3483 for ( sal_Int32
i = aInputString.getLength(); --
i >= 0; )
3486 if ( c == 0x0020 || c == 0x0009 || c == 0x000A || c == 0x000D )
3487 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3489 sal_Int32 nPercentCount = 0;
3490 for ( sal_Int32
i = aInputString.getLength() - 1;
i >= 0 && aInputString[
i ] == 0x0025;
i-- )
3492 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3496 rtl_math_ConversionStatus eStatus;
3497 sal_Int32 nParseEnd;
3498 double fVal = ::rtl::math::stringToDouble( aInputString, cDecimalSeparator, 0, &eStatus, &nParseEnd );
3499 if ( eStatus == rtl_math_ConversionStatus_Ok && nParseEnd == aInputString.getLength() )
3502 fVal *= pow( 10.0, -(nPercentCount * 2));
3511 return ( !u_isISOControl(nCodePoint)
3512 && u_isdefined(nCodePoint) );
3520 OUStringBuffer
aBuf(
aStr.getLength() );
3522 while ( nIdx <
aStr.getLength() )
3524 sal_uInt32 c =
aStr.iterateCodePoints( &nIdx );
3526 aBuf.appendUtf32( c );
3541 const sal_uInt32 convertFlags =
3542 RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
3543 RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE |
3544 RTL_UNICODETOTEXT_FLAGS_FLUSH |
3545 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
3546 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
3547 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE;
3556 if (fVal < 0.0 || fVal >= 256.0)
3561 const sal_uInt32 convertFlags =
3562 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
3563 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
3564 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT;
3566 char cEncodedChar =
static_cast<char>(fVal);
3567 OUString
aStr(&cEncodedChar, 1, osl_getThreadTextEncoding(), convertFlags);
3587 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3599 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3649 if (
nGlobalError != FormulaError::NONE || !rtl::isUnicodeCodePoint(nCodePoint))
3653 OUString
aStr( &nCodePoint, 1 );
3660 const std::function<
void(
SCSIZE i,
double fCurrent )>& MatOpFunc,
bool bDoMatOp )
3663 if (!
p || !
p->IsArrayResult())
3669 assert(nMatRows > 0);
3670 xResMat =
GetNewMat( 1, nMatRows,
true);
3671 xResMat->FillDouble( fCurrent, 0,0, 0,nMatRows-1);
3679 MatOpFunc(
i, fCurrent);
3687 short nParamCount =
GetByte();
3692 double nMin = ::std::numeric_limits<double>::max();
3693 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMin )
3695 double fVecRes = xResMat->GetDouble(0,
i);
3696 if (fVecRes > fCurMin)
3697 xResMat->PutDouble( fCurMin, 0,
i);
3700 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3705 size_t nRefInList = 0;
3706 while (nParamCount-- > 0)
3713 if (nMin > nVal) nMin = nVal;
3725 if (nMin > nVal) nMin = nVal;
3727 else if (bTextAsZero && aCell.
hasString())
3739 nRefArrayPos == std::numeric_limits<size_t>::max()))
3741 nRefArrayPos = nRefInList;
3755 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3762 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3765 MatOpFunc( nRefArrayPos, nMin);
3768 nMin = std::numeric_limits<double>::max();
3770 nRefArrayPos = std::numeric_limits<size_t>::max();
3797 SetError(FormulaError::IllegalParameter);
3802 SetError(FormulaError::IllegalParameter);
3809 if (nMin < std::numeric_limits<double>::max())
3813 MatOpFunc(
i, nMin);
3824 double fVecRes = xResMat->GetDouble(0,
i);
3825 if (fVecRes == std::numeric_limits<double>::max())
3826 xResMat->PutDouble( 0.0, 0,
i);
3833 if (!std::isfinite(nVal))
3835 else if ( nVal < nMin )
3844 short nParamCount =
GetByte();
3849 double nMax = std::numeric_limits<double>::lowest();
3850 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMax )
3852 double fVecRes = xResMat->GetDouble(0,
i);
3853 if (fVecRes < fCurMax)
3854 xResMat->PutDouble( fCurMax, 0,
i);
3857 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3862 size_t nRefInList = 0;
3863 while (nParamCount-- > 0)
3870 if (nMax < nVal) nMax = nVal;
3882 if (nMax < nVal) nMax = nVal;
3884 else if (bTextAsZero && aCell.
hasString())
3896 nRefArrayPos == std::numeric_limits<size_t>::max()))
3898 nRefArrayPos = nRefInList;
3912 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3919 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3922 MatOpFunc( nRefArrayPos, nMax);
3925 nMax = std::numeric_limits<double>::lowest();
3927 nRefArrayPos = std::numeric_limits<size_t>::max();
3954 SetError(FormulaError::IllegalParameter);
3959 SetError(FormulaError::IllegalParameter);
3966 if (nMax > std::numeric_limits<double>::lowest())
3970 MatOpFunc(
i, nMax);
3981 double fVecRes = xResMat->GetDouble(0,
i);
3982 if (fVecRes == -std::numeric_limits<double>::max())
3983 xResMat->PutDouble( 0.0, 0,
i);
3990 if (!std::isfinite(nVal))
3992 else if ( nVal > nMax )
4001 short nParamCount =
GetByte();
4004 struct ArrayRefListValue
4006 std::vector<double> mvValues;
4008 ArrayRefListValue() =
default;
4009 double get()
const {
return mfSum.
get(); }
4011 std::vector<ArrayRefListValue> vArrayValues;
4013 std::vector<double>
values;
4018 size_t nRefInList = 0;
4019 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
4046 else if (bTextAsZero && aCell.
hasString())
4055 if (
p &&
p->IsArrayResult())
4057 size_t nRefArrayPos = nRefInList;
4058 if (vArrayValues.empty())
4061 assert(nMatRows > 0);
4062 vArrayValues.resize(nMatRows);
4063 for (ArrayRefListValue & it : vArrayValues)
4073 for (ArrayRefListValue & it : vArrayValues)
4075 it.mvValues.insert( it.mvValues.end(),
values.begin(),
values.end());
4079 ArrayRefListValue& rArrayValue = vArrayValues[nRefArrayPos];
4087 rArrayValue.mvValues.push_back(fVal);
4088 rArrayValue.mfSum += fVal;
4090 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4092 if ( nErr != FormulaError::NONE )
4097 std::vector<double>().swap(
values);
4115 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4117 if ( nErr != FormulaError::NONE )
4132 pMat->GetDimensions(nC, nR);
4133 for (
SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
4135 for (
SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
4137 if (!pMat->IsStringOrEmpty(nMatCol,nMatRow))
4139 fVal= pMat->GetDouble(nMatCol,nMatRow);
4145 else if (bIgnoreErrVal)
4148 else if ( bTextAsZero )
4165 SetError(FormulaError::IllegalParameter);
4170 SetError(FormulaError::IllegalParameter);
4174 if (!vArrayValues.empty())
4179 for (
auto & it : vArrayValues)
4181 it.mvValues.insert( it.mvValues.end(),
values.begin(),
values.end());
4186 for (
SCSIZE r=0; r < nMatRows; ++r)
4188 ::std::vector<double>::size_type
n = vArrayValues[r].mvValues.size();
4190 xResMat->PutError( FormulaError::DivisionByZero, 0, r);
4193 ArrayRefListValue& rArrayValue = vArrayValues[r];
4195 const double vMean = rArrayValue.get() /
n;
4196 for (::std::vector<double>::size_type
i = 0;
i <
n;
i++)
4197 vSum += ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean) *
4198 ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean);
4199 xResMat->PutDouble( VarResult( vSum,
n), 0, r);
4206 ::std::vector<double>::size_type
n =
values.size();
4208 SetError( FormulaError::DivisionByZero);
4212 const double vMean = fSum.
get() /
n;
4213 for (::std::vector<double>::size_type
i = 0;
i <
n;
i++)
4214 vSum += ::rtl::math::approxSub(
values[
i], vMean) * ::rtl::math::approxSub(
values[
i], vMean);
4222 auto VarResult = [](
double fVal,
size_t nValCount )
4227 return fVal / (nValCount - 1);
4234 auto VarResult = [](
double fVal,
size_t nValCount )
4236 return sc::div( fVal, nValCount);
4244 auto VarResult = [](
double fVal,
size_t nValCount )
4249 return sqrt( fVal / (nValCount - 1));
4256 auto VarResult = [](
double fVal,
size_t nValCount )
4261 return sqrt( fVal / nValCount);
4293 while (nParamCount-- > 0)
4302 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4303 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4304 static_cast<sal_uLong>(nCol2 - nCol1 + 1);
4312 pMat->GetDimensions(nC, nR);
4334 SetError(FormulaError::IllegalParameter);
4350 while (nParamCount-- > 0)
4359 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4360 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4361 static_cast<sal_uLong>(nRow2 - nRow1 + 1);
4369 pMat->GetDimensions(nC, nR);
4391 SetError(FormulaError::IllegalParameter);
4401 if ( nParamCount == 0 )
4412 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
4422 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4423 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1);
4437 SetError( FormulaError::IllegalParameter );
4451 if (nParamCount == 0)
4467 bMayBeScalar =
false;
4471 bMayBeScalar =
true;
4473 if (!bMayBeScalar || nCols != 1 || nRows != 1)
4479 pResMat->PutDouble( nVal +
i,
static_cast<SCSIZE>(
i), 0);
4496 nVal =
static_cast<double>(nCol1 + 1);
4506 nVal =
static_cast<double>( aAbsRef.
Col() + 1 );
4521 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4536 static_cast<SCSIZE>(nCol2-nCol1+1), 1,
true);
4539 for (
SCCOL i = nCol1;
i <= nCol2;
i++)
4540 pResMat->PutDouble(
static_cast<double>(
i+1),
4541 static_cast<SCSIZE>(
i-nCol1), 0);
4547 nVal =
static_cast<double>(nCol1 + 1);
4551 SetError( FormulaError::IllegalParameter );
4564 if (nParamCount == 0)
4580 bMayBeScalar =
false;
4584 bMayBeScalar =
true;
4586 if (!bMayBeScalar || nCols != 1 || nRows != 1)
4592 pResMat->PutDouble( nVal +
i, 0,
static_cast<SCSIZE>(
i));
4609 nVal =
static_cast<double>(nRow1 + 1);
4619 nVal =
static_cast<double>( aAbsRef.
Row() + 1 );
4633 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4648 static_cast<SCSIZE>(nRow2-nRow1+1),
true);
4651 for (
SCROW i = nRow1;
i <= nRow2;
i++)
4652 pResMat->PutDouble(
static_cast<double>(
i+1), 0,
4653 static_cast<SCSIZE>(
i-nRow1));
4659 nVal =
static_cast<double>(nRow1 + 1);
4663 SetError( FormulaError::IllegalParameter );
4676 if ( nParamCount == 0 )
4688 SetError( FormulaError::IllegalArgument );
4708 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4713 SetError( FormulaError::IllegalParameter );
4723class VectorMatrixAccessor
4726 VectorMatrixAccessor(
const ScMatrix& rMat,
bool bColVec) :
4727 mrMat(rMat), mbColVec(bColVec) {}
4729 bool IsEmpty(
SCSIZE i)
const
4731 return mbColVec ? mrMat.IsEmpty(0, i) : mrMat.IsEmpty(i, 0);
4734 bool IsEmptyPath(
SCSIZE i)
const
4736 return mbColVec ? mrMat.IsEmptyPath(0, i) : mrMat.IsEmptyPath(i, 0);
4739 bool IsValue(
SCSIZE i)
const
4741 return mbColVec ? mrMat.IsValue(0, i) : mrMat.IsValue(i, 0);
4744 bool IsStringOrEmpty(
SCSIZE i)
const
4746 return mbColVec ? mrMat.IsStringOrEmpty(0, i) : mrMat.IsStringOrEmpty(i, 0);
4749 double GetDouble(
SCSIZE i)
const
4751 return mbColVec ? mrMat.GetDouble(0, i) : mrMat.GetDouble(i, 0);
4756 return mbColVec ? mrMat.GetString(0, i).getString() : mrMat.GetString(i, 0).getString();
4759 SCSIZE GetElementCount()
const
4762 mrMat.GetDimensions(nC, nR);
4763 return mbColVec ? nR : nC;
4774sal_Int32 lcl_CompareMatrix2Query(
4777 if (rMat.IsEmpty(i))
4788 if (rMat.IsValue(i))
4790 const double nVal1 = rMat.GetDouble(i);
4791 if (!std::isfinite(nVal1))
4807 return nVal1 < nVal2 ? -1 : 1;
4813 OUString aStr1 = rMat.GetString(i);
4821void lcl_GetLastMatch(
SCSIZE& rIndex,
const VectorMatrixAccessor& rMat,
4824 if (rMat.IsValue(rIndex))
4826 double nVal = rMat.GetDouble(rIndex);
4827 while (rIndex < nMatCount-1 && rMat.IsValue(rIndex+1) &&
4828 nVal == rMat.GetDouble(rIndex+1))
4832 else if (rMat.IsEmptyPath(rIndex))
4834 while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
4837 else if (rMat.IsEmpty(rIndex))
4839 while (rIndex < nMatCount-1 && rMat.IsEmpty(rIndex+1))
4842 else if (rMat.IsStringOrEmpty(rIndex))
4844 OUString
aStr( rMat.GetString(rIndex));
4845 while (rIndex < nMatCount-1 && rMat.IsStringOrEmpty(rIndex+1) &&
4846 aStr == rMat.GetString(rIndex+1))
4851 OSL_FAIL(
"lcl_GetLastMatch: unhandled matrix type");
4865 if (nParamCount == 3)
4886 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4887 if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
4918 rParam.
nCol1 = nCol1;
4919 rParam.
nRow1 = nRow1;
4920 rParam.
nCol2 = nCol2;
4921 rParam.
nTab = nTab1;
4929 else if (fTyp > 0.0)
4983 rItem.
mfVal = pToken->GetDouble();
4988 rItem.
maString = pToken->GetString();
5022 pMatSrc->GetDimensions( nC, nR);
5023 if (nC > 1 && nR > 1)
5031 pMatSrc->SetErrorInterpreter(
nullptr);
5033 SCSIZE nMatCount = (nC == 1) ? nR : nC;
5034 VectorMatrixAccessor aMatAcc(*pMatSrc, nC == 1);
5043 if (lcl_CompareMatrix2Query(
i, aMatAcc, rEntry) == 0)
5057 SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
5058 for (
SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
5060 SCSIZE nMid = nFirst + nLen/2;
5061 sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, aMatAcc, rEntry);
5065 lcl_GetLastMatch( nMid, aMatAcc, nMatCount);
5073 nHitIndex = bAscOrder ? nLast : nFirst;
5075 nHitIndex = bAscOrder ? nFirst : nLast;
5095 if (nHitIndex == nMatCount-1)
5097 sal_Int32 nCmp = lcl_CompareMatrix2Query( nHitIndex, aMatAcc, rEntry);
5098 if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
5125 rParam.
nRow2 = nRow2;
5127 ScAddress aResultPos( nCol1, nRow1, nTab1);
5133 nDelta = aResultPos.
Row() - nRow1;
5139 rParam.
nRow2 = nRow1;
5163 nDelta = nC - nCol1;
5224 if (!isCellContentEmpty(aCell))
5233 SCSIZE nRefListArrayPos = 0;
5234 size_t nRefInList = 0;
5235 while (nParam-- > 0)
5237 nRefListArrayPos = nRefInList;
5245 for (
bool bHas = aIter.
first(); bHas; bHas = aIter.
next())
5248 if (!isCellContentEmpty(rCell))
5253 xResMat->PutDouble( nMaxCount -
nCount, 0, nRefListArrayPos);
5265 SetError( FormulaError::IllegalParameter);
5269 xMat->GetDimensions( nC, nR);
5270 nMaxCount = nC * nR;
5275 nCount = xMat->Count(
true,
true,
true);
5279 default :
SetError(FormulaError::IllegalParameter);
break;