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;
2357 else if( aInfoType ==
"COORD" )
2360 OUString aCellStr1 =
2363 OUString aCellStr2 =
2366 OUString aFuncResult = aCellStr1 +
":" + aCellStr2;
2371 else if( aInfoType ==
"CONTENTS" )
2382 else if( aInfoType ==
"TYPE" )
2391 else if( aInfoType ==
"WIDTH" )
2401 pPrinter->
SetFont( aDefFont );
2403 assert(nZeroWidth != 0);
2404 pPrinter->
SetFont( aOldFont );
2409 else if( aInfoType ==
"PREFIX" )
2415 switch( pJustAttr->GetValue() )
2417 case SvxCellHorJustify::Standard:
2418 case SvxCellHorJustify::Left:
2419 case SvxCellHorJustify::Block: c =
'\'';
break;
2420 case SvxCellHorJustify::Center: c =
'^';
break;
2421 case SvxCellHorJustify::Right: c =
'"';
break;
2422 case SvxCellHorJustify::Repeat: c =
'\\';
break;
2427 else if( aInfoType ==
"PROTECT" )
2434 else if( aInfoType ==
"FORMAT" )
2436 OUString aFuncResult;
2438 getFormatString(
pFormatter, nFormat, aFuncResult);
2441 else if( aInfoType ==
"COLOR" )
2446 else if( aInfoType ==
"PARENTHESES" )
2492 if ( aInfoType ==
"COL" )
2494 else if ( aInfoType ==
"ROW" )
2496 else if ( aInfoType ==
"SHEET" )
2506 else if ( aInfoType ==
"ADDRESS" )
2516 else if ( aInfoType ==
"FILENAME" )
2528 OUString
aBuf =
"'" + *
p +
"'#$" + aTabName;
2531 else if ( aInfoType ==
"CONTENTS" )
2533 switch (pToken->GetType())
2539 PushString(OUString::number(pToken->GetDouble()));
2548 else if ( aInfoType ==
"TYPE" )
2551 switch (pToken->GetType())
2564 else if ( aInfoType ==
"FORMAT" )
2571 else if ( aInfoType ==
"COLOR" )
2582 else if ( aInfoType ==
"PARENTHESES" )
2623 bRes = !
x->GetRefList()->empty();
2699 if (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NONE)
2700 bRes = pMat->IsValue( 0, 0);
2704 SCSIZE nCols, nRows, nC, nR;
2705 pMat->GetDimensions( nCols, nRows);
2707 if ( nC < nCols && nR < nRows )
2708 if (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NONE)
2709 bRes = pMat->IsValue( nC, nR);
2732 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2745 static_cast<SCSIZE>(nRow2 - nRow1 + 1),
true);
2755 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2758 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2800 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2806 SetError( FormulaError::IllegalArgument);
2817 for (
SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2820 for (
SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
2831 pResMat->PutError( FormulaError::NotAvailable,
i,j);
2856 SetError( FormulaError::NotAvailable );
2862 SetError( FormulaError::NotAvailable );
2884 bRes = (nErr == FormulaError::NotAvailable);
2893 (pToken && pToken->GetType() ==
svError && pToken->GetError() == FormulaError::NotAvailable))
2904 bRes = (pMat->GetErrorIfNotString( 0, 0) == FormulaError::NotAvailable);
2907 SCSIZE nCols, nRows, nC, nR;
2908 pMat->GetDimensions( nCols, nRows);
2910 if ( nC < nCols && nR < nRows )
2911 bRes = (pMat->GetErrorIfNotString( nC, nR) == FormulaError::NotAvailable);
2941 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
2950 (pToken->GetType() ==
svError && pToken->GetError() != FormulaError::NotAvailable))
2963 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
2967 SCSIZE nCols, nRows, nC, nR;
2968 pMat->GetDimensions( nCols, nRows);
2970 if ( nC < nCols && nR < nRows )
2972 FormulaError nErr = pMat->GetErrorIfNotString( nC, nR);
2973 bRes = (nErr != FormulaError::NONE && nErr != FormulaError::NotAvailable);
3026 bRes = (pMat->GetErrorIfNotString( 0, 0) != FormulaError::NONE);
3029 SCSIZE nCols, nRows, nC, nR;
3030 pMat->GetDimensions( nCols, nRows);
3032 if ( nC < nCols && nR < nRows )
3033 bRes = (pMat->GetErrorIfNotString( nC, nR) != FormulaError::NONE);
3062 if (nErr != FormulaError::NONE)
3097 fVal = pToken->GetDouble();
3110 bRes = pMat->IsValue( 0, 0);
3112 fVal = pMat->GetDouble( 0, 0);
3116 SCSIZE nCols, nRows, nC, nR;
3117 pMat->GetDimensions( nCols, nRows);
3119 if ( nC < nCols && nR < nRows )
3121 bRes = pMat->IsValue( nC, nR);
3123 fVal = pMat->GetDouble( nC, nR);
3134 SetError( FormulaError::IllegalParameter);
3136 bRes = ( fmod( ::rtl::math::approxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
3160 if (nErr != FormulaError::NONE)
3171 OUStringBuffer
aStr;
3176 if ( *
p !=
' ' ||
p[-1] !=
' ' )
3193 const sal_Int32 nLen =
aStr.getLength();
3200 while(
nPos < nLen )
3224 while ( nIdx <
aStr.getLength() )
3226 aStr.iterateCodePoints( &nIdx );
3245 bool bValue =
false;
3295 PushError( FormulaError::UnknownOpCode);
3301 OUString aInputString;
3370 sal_uInt32 nFIndex = 0;
3385 OUString aInputString;
3386 OUString aGroupSeparator;
3389 if ( nParamCount == 3 )
3392 if ( nParamCount >= 2 )
3395 if ( aDecimalSeparator.getLength() == 1 )
3396 cDecimalSeparator = aDecimalSeparator[ 0 ];
3404 if ( cDecimalSeparator && aGroupSeparator.indexOf( cDecimalSeparator ) != -1 )
3422 if ( aInputString.isEmpty() )
3431 sal_Int32 nDecSep = aInputString.indexOf( cDecimalSeparator );
3434 OUString aTemporary( nDecSep >= 0 ? aInputString.copy( 0, nDecSep ) : aInputString );
3436 while (
nIndex < aGroupSeparator.getLength())
3438 sal_uInt32 nChar = aGroupSeparator.iterateCodePoints( &
nIndex );
3439 aTemporary = aTemporary.replaceAll( OUString( &nChar, 1 ),
"" );
3442 aInputString = aTemporary + aInputString.subView( nDecSep );
3444 aInputString = aTemporary;
3447 for ( sal_Int32
i = aInputString.getLength(); --
i >= 0; )
3450 if ( c == 0x0020 || c == 0x0009 || c == 0x000A || c == 0x000D )
3451 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3453 sal_Int32 nPercentCount = 0;
3454 for ( sal_Int32
i = aInputString.getLength() - 1;
i >= 0 && aInputString[
i ] == 0x0025;
i-- )
3456 aInputString = aInputString.replaceAt(
i, 1,
u"" );
3460 rtl_math_ConversionStatus eStatus;
3461 sal_Int32 nParseEnd;
3462 double fVal = ::rtl::math::stringToDouble( aInputString, cDecimalSeparator, 0, &eStatus, &nParseEnd );
3463 if ( eStatus == rtl_math_ConversionStatus_Ok && nParseEnd == aInputString.getLength() )
3466 fVal *= pow( 10.0, -(nPercentCount * 2));
3475 return ( !u_isISOControl(nCodePoint)
3476 && u_isdefined(nCodePoint) );
3484 OUStringBuffer
aBuf(
aStr.getLength() );
3486 while ( nIdx <
aStr.getLength() )
3488 sal_uInt32 c =
aStr.iterateCodePoints( &nIdx );
3490 aBuf.appendUtf32( c );
3505 const sal_uInt32 convertFlags =
3506 RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
3507 RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE |
3508 RTL_UNICODETOTEXT_FLAGS_FLUSH |
3509 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
3510 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
3511 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE;
3520 if (fVal < 0.0 || fVal >= 256.0)
3525 const sal_uInt32 convertFlags =
3526 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
3527 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
3528 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT;
3530 char cEncodedChar =
static_cast<char>(fVal);
3531 OUString
aStr(&cEncodedChar, 1, osl_getThreadTextEncoding(), convertFlags);
3551 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3563 return aTrans.
transliterate( rStr, 0, sal_uInt16( rStr.getLength() ) );
3613 if (
nGlobalError != FormulaError::NONE || !rtl::isUnicodeCodePoint(nCodePoint))
3617 OUString
aStr( &nCodePoint, 1 );
3624 const std::function<
void(
SCSIZE i,
double fCurrent )>& MatOpFunc,
bool bDoMatOp )
3627 if (!
p || !
p->IsArrayResult())
3633 assert(nMatRows > 0);
3634 xResMat =
GetNewMat( 1, nMatRows,
true);
3635 xResMat->FillDouble( fCurrent, 0,0, 0,nMatRows-1);
3643 MatOpFunc(
i, fCurrent);
3651 short nParamCount =
GetByte();
3656 double nMin = ::std::numeric_limits<double>::max();
3657 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMin )
3659 double fVecRes = xResMat->GetDouble(0,
i);
3660 if (fVecRes > fCurMin)
3661 xResMat->PutDouble( fCurMin, 0,
i);
3664 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3669 size_t nRefInList = 0;
3670 while (nParamCount-- > 0)
3677 if (nMin > nVal) nMin = nVal;
3689 if (nMin > nVal) nMin = nVal;
3691 else if (bTextAsZero && aCell.
hasString())
3703 nRefArrayPos == std::numeric_limits<size_t>::max()))
3705 nRefArrayPos = nRefInList;
3719 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3726 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3729 MatOpFunc( nRefArrayPos, nMin);
3732 nMin = std::numeric_limits<double>::max();
3734 nRefArrayPos = std::numeric_limits<size_t>::max();
3761 SetError(FormulaError::IllegalParameter);
3766 SetError(FormulaError::IllegalParameter);
3773 if (nMin < std::numeric_limits<double>::max())
3777 MatOpFunc(
i, nMin);
3788 double fVecRes = xResMat->GetDouble(0,
i);
3789 if (fVecRes == std::numeric_limits<double>::max())
3790 xResMat->PutDouble( 0.0, 0,
i);
3797 if (!std::isfinite(nVal))
3799 else if ( nVal < nMin )
3808 short nParamCount =
GetByte();
3813 double nMax = std::numeric_limits<double>::lowest();
3814 auto MatOpFunc = [&xResMat](
SCSIZE i,
double fCurMax )
3816 double fVecRes = xResMat->GetDouble(0,
i);
3817 if (fVecRes < fCurMax)
3818 xResMat->PutDouble( fCurMax, 0,
i);
3821 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
3826 size_t nRefInList = 0;
3827 while (nParamCount-- > 0)
3834 if (nMax < nVal) nMax = nVal;
3846 if (nMax < nVal) nMax = nVal;
3848 else if (bTextAsZero && aCell.
hasString())
3860 nRefArrayPos == std::numeric_limits<size_t>::max()))
3862 nRefArrayPos = nRefInList;
3876 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(nVal, nErr))
3883 if (nRefArrayPos != std::numeric_limits<size_t>::max())
3886 MatOpFunc( nRefArrayPos, nMax);
3889 nMax = std::numeric_limits<double>::lowest();
3891 nRefArrayPos = std::numeric_limits<size_t>::max();
3918 SetError(FormulaError::IllegalParameter);
3923 SetError(FormulaError::IllegalParameter);
3930 if (nMax > std::numeric_limits<double>::lowest())
3934 MatOpFunc(
i, nMax);
3945 double fVecRes = xResMat->GetDouble(0,
i);
3946 if (fVecRes == -std::numeric_limits<double>::max())
3947 xResMat->PutDouble( 0.0, 0,
i);
3954 if (!std::isfinite(nVal))
3956 else if ( nVal > nMax )
3965 short nParamCount =
GetByte();
3968 struct ArrayRefListValue
3970 std::vector<double> mvValues;
3972 ArrayRefListValue() =
default;
3973 double get()
const {
return mfSum.
get(); }
3975 std::vector<ArrayRefListValue> vArrayValues;
3977 std::vector<double>
values;
3982 size_t nRefInList = 0;
3983 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
4010 else if (bTextAsZero && aCell.
hasString())
4019 if (
p &&
p->IsArrayResult())
4021 size_t nRefArrayPos = nRefInList;
4022 if (vArrayValues.empty())
4025 assert(nMatRows > 0);
4026 vArrayValues.resize(nMatRows);
4027 for (ArrayRefListValue & it : vArrayValues)
4037 for (ArrayRefListValue & it : vArrayValues)
4039 it.mvValues.insert( it.mvValues.end(),
values.begin(),
values.end());
4043 ArrayRefListValue& rArrayValue = vArrayValues[nRefArrayPos];
4051 rArrayValue.mvValues.push_back(fVal);
4052 rArrayValue.mfSum += fVal;
4054 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4056 if ( nErr != FormulaError::NONE )
4061 std::vector<double>().swap(
values);
4079 while ((nErr == FormulaError::NONE) && aValIter.
GetNext(fVal, nErr));
4081 if ( nErr != FormulaError::NONE )
4096 pMat->GetDimensions(nC, nR);
4097 for (
SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
4099 for (
SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
4101 if (!pMat->IsStringOrEmpty(nMatCol,nMatRow))
4103 fVal= pMat->GetDouble(nMatCol,nMatRow);
4109 else if (bIgnoreErrVal)
4112 else if ( bTextAsZero )
4129 SetError(FormulaError::IllegalParameter);
4134 SetError(FormulaError::IllegalParameter);
4138 if (!vArrayValues.empty())
4143 for (
auto & it : vArrayValues)
4145 it.mvValues.insert( it.mvValues.end(),
values.begin(),
values.end());
4150 for (
SCSIZE r=0; r < nMatRows; ++r)
4152 ::std::vector<double>::size_type
n = vArrayValues[r].mvValues.size();
4154 xResMat->PutError( FormulaError::DivisionByZero, 0, r);
4157 ArrayRefListValue& rArrayValue = vArrayValues[r];
4159 const double vMean = rArrayValue.get() /
n;
4160 for (::std::vector<double>::size_type
i = 0;
i <
n;
i++)
4161 vSum += ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean) *
4162 ::rtl::math::approxSub( rArrayValue.mvValues[
i], vMean);
4163 xResMat->PutDouble( VarResult( vSum,
n), 0, r);
4170 ::std::vector<double>::size_type
n =
values.size();
4172 SetError( FormulaError::DivisionByZero);
4176 const double vMean = fSum.
get() /
n;
4177 for (::std::vector<double>::size_type
i = 0;
i <
n;
i++)
4178 vSum += ::rtl::math::approxSub(
values[
i], vMean) * ::rtl::math::approxSub(
values[
i], vMean);
4186 auto VarResult = [](
double fVal,
size_t nValCount )
4191 return fVal / (nValCount - 1);
4198 auto VarResult = [](
double fVal,
size_t nValCount )
4200 return sc::div( fVal, nValCount);
4208 auto VarResult = [](
double fVal,
size_t nValCount )
4213 return sqrt( fVal / (nValCount - 1));
4220 auto VarResult = [](
double fVal,
size_t nValCount )
4225 return sqrt( fVal / nValCount);
4257 while (nParamCount-- > 0)
4266 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4267 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4268 static_cast<sal_uLong>(nCol2 - nCol1 + 1);
4276 pMat->GetDimensions(nC, nR);
4298 SetError(FormulaError::IllegalParameter);
4314 while (nParamCount-- > 0)
4323 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4324 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4325 static_cast<sal_uLong>(nRow2 - nRow1 + 1);
4333 pMat->GetDimensions(nC, nR);
4355 SetError(FormulaError::IllegalParameter);
4365 if ( nParamCount == 0 )
4376 while (
nGlobalError == FormulaError::NONE && nParamCount-- > 0)
4386 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4387 nVal +=
static_cast<sal_uLong>(nTab2 - nTab1 + 1);
4401 SetError( FormulaError::IllegalParameter );
4415 if (nParamCount == 0)
4435 pResMat->PutDouble( nVal +
i,
static_cast<SCSIZE>(
i), 0);
4451 nVal =
static_cast<double>(nCol1 + 1);
4461 nVal =
static_cast<double>( aAbsRef.
Col() + 1 );
4476 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4491 static_cast<SCSIZE>(nCol2-nCol1+1), 1,
true);
4494 for (
SCCOL i = nCol1;
i <= nCol2;
i++)
4495 pResMat->PutDouble(
static_cast<double>(
i+1),
4496 static_cast<SCSIZE>(
i-nCol1), 0);
4502 nVal =
static_cast<double>(nCol1 + 1);
4506 SetError( FormulaError::IllegalParameter );
4519 if (nParamCount == 0)
4539 pResMat->PutDouble( nVal +
i, 0,
static_cast<SCSIZE>(
i));
4555 nVal =
static_cast<double>(nRow1 + 1);
4565 nVal =
static_cast<double>( aAbsRef.
Row() + 1 );
4579 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4594 static_cast<SCSIZE>(nRow2-nRow1+1),
true);
4597 for (
SCROW i = nRow1;
i <= nRow2;
i++)
4598 pResMat->PutDouble(
static_cast<double>(
i+1), 0,
4599 static_cast<SCSIZE>(
i-nRow1));
4605 nVal =
static_cast<double>(nRow1 + 1);
4609 SetError( FormulaError::IllegalParameter );
4622 if ( nParamCount == 0 )
4634 SetError( FormulaError::IllegalArgument );
4654 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4659 SetError( FormulaError::IllegalParameter );
4669class VectorMatrixAccessor
4672 VectorMatrixAccessor(
const ScMatrix& rMat,
bool bColVec) :
4673 mrMat(rMat), mbColVec(bColVec) {}
4675 bool IsEmpty(
SCSIZE i)
const
4677 return mbColVec ? mrMat.IsEmpty(0, i) : mrMat.IsEmpty(i, 0);
4680 bool IsEmptyPath(
SCSIZE i)
const
4682 return mbColVec ? mrMat.IsEmptyPath(0, i) : mrMat.IsEmptyPath(i, 0);
4685 bool IsValue(
SCSIZE i)
const
4687 return mbColVec ? mrMat.IsValue(0, i) : mrMat.IsValue(i, 0);
4690 bool IsStringOrEmpty(
SCSIZE i)
const
4692 return mbColVec ? mrMat.IsStringOrEmpty(0, i) : mrMat.IsStringOrEmpty(i, 0);
4695 double GetDouble(
SCSIZE i)
const
4697 return mbColVec ? mrMat.GetDouble(0, i) : mrMat.GetDouble(i, 0);
4702 return mbColVec ? mrMat.GetString(0, i).getString() : mrMat.GetString(i, 0).getString();
4705 SCSIZE GetElementCount()
const
4708 mrMat.GetDimensions(nC, nR);
4709 return mbColVec ? nR : nC;
4720sal_Int32 lcl_CompareMatrix2Query(
4723 if (rMat.IsEmpty(i))
4734 if (rMat.IsValue(i))
4736 const double nVal1 = rMat.GetDouble(i);
4737 if (!std::isfinite(nVal1))
4753 return nVal1 < nVal2 ? -1 : 1;
4759 OUString aStr1 = rMat.GetString(i);
4767void lcl_GetLastMatch(
SCSIZE& rIndex,
const VectorMatrixAccessor& rMat,
4770 if (rMat.IsValue(rIndex))
4772 double nVal = rMat.GetDouble(rIndex);
4773 while (rIndex < nMatCount-1 && rMat.IsValue(rIndex+1) &&
4774 nVal == rMat.GetDouble(rIndex+1))
4778 else if (rMat.IsEmptyPath(rIndex))
4780 while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
4783 else if (rMat.IsEmpty(rIndex))
4785 while (rIndex < nMatCount-1 && rMat.IsEmpty(rIndex+1))
4788 else if (rMat.IsStringOrEmpty(rIndex))
4790 OUString
aStr( rMat.GetString(rIndex));
4791 while (rIndex < nMatCount-1 && rMat.IsStringOrEmpty(rIndex+1) &&
4792 aStr == rMat.GetString(rIndex+1))
4797 OSL_FAIL(
"lcl_GetLastMatch: unhandled matrix type");
4811 if (nParamCount == 3)
4832 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4833 if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
4864 rParam.
nCol1 = nCol1;
4865 rParam.
nRow1 = nRow1;
4866 rParam.
nCol2 = nCol2;
4867 rParam.
nTab = nTab1;
4875 else if (fTyp > 0.0)
4929 rItem.
mfVal = pToken->GetDouble();
4934 rItem.
maString = pToken->GetString();
4968 pMatSrc->GetDimensions( nC, nR);
4969 if (nC > 1 && nR > 1)
4977 pMatSrc->SetErrorInterpreter(
nullptr);
4979 SCSIZE nMatCount = (nC == 1) ? nR : nC;
4980 VectorMatrixAccessor aMatAcc(*pMatSrc, nC == 1);
4989 if (lcl_CompareMatrix2Query(
i, aMatAcc, rEntry) == 0)
5003 SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
5004 for (
SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
5006 SCSIZE nMid = nFirst + nLen/2;
5007 sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, aMatAcc, rEntry);
5011 lcl_GetLastMatch( nMid, aMatAcc, nMatCount);
5019 nHitIndex = bAscOrder ? nLast : nFirst;
5021 nHitIndex = bAscOrder ? nFirst : nLast;
5041 if (nHitIndex == nMatCount-1)
5043 sal_Int32 nCmp = lcl_CompareMatrix2Query( nHitIndex, aMatAcc, rEntry);
5044 if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
5071 rParam.
nRow2 = nRow2;
5073 ScAddress aResultPos( nCol1, nRow1, nTab1);
5079 nDelta = aResultPos.
Row() - nRow1;
5085 rParam.
nRow2 = nRow1;
5109 nDelta = nC - nCol1;
5170 if (!isCellContentEmpty(aCell))
5179 SCSIZE nRefListArrayPos = 0;
5180 size_t nRefInList = 0;
5181 while (nParam-- > 0)
5183 nRefListArrayPos = nRefInList;
5191 for (
bool bHas = aIter.
first(); bHas; bHas = aIter.
next())
5194 if (!isCellContentEmpty(rCell))
5199 xResMat->PutDouble( nMaxCount -
nCount, 0, nRefListArrayPos);
5211 SetError( FormulaError::IllegalParameter);
5215 xMat->GetDimensions( nC, nR);
5216 nMaxCount = nC * nR;
5221 nCount = xMat->Count(
true,
true,
true);
5225 default :
SetError(FormulaError::IllegalParameter);
break;
5244 bool bSumExtraRange = (nParamCount == 3);
5257 PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
5258 if ( nTabJunk != nTab3 )
5260 PushError( FormulaError::IllegalParameter);
5284 pSumExtraMatrix->PutDouble(pToken->GetDouble(), 0, 0);
5286 pSumExtraMatrix->PutString(pToken->GetString(), 0, 0);